Compare commits

...

9 Commits

Author SHA1 Message Date
793e544eb0 포매팅 2026-02-01 19:42:47 +09:00
e4566118f7 EdenAutoMorpherEditor 디컴파일 소스 추가 2026-02-01 19:42:18 +09:00
7637ff2ac0 수동 정제 2026-02-01 19:40:04 +09:00
6c2bb74df3 포매팅 2026-02-01 19:30:24 +09:00
34507ca208 EdenAutoMorpherScript 디컴파일 소스 추가 2026-02-01 19:26:39 +09:00
15efd5b720 포매팅 2026-02-01 19:23:23 +09:00
ff3a3c522e EdenAutoMorpher_ProfileSaver_Editor 디컴파일 소스 추가 2026-02-01 19:23:02 +09:00
bf39155bf3 포매팅 2026-02-01 19:20:25 +09:00
5d4f773fe5 EdenAutoMorpher_ProfileSaver_Script 디컴파일 소스 추가 2026-02-01 19:19:37 +09:00
137 changed files with 14921 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: dcd2dae79e135544e8f59bbfd335d224
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,139 @@
// 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.
// EdenAutoMorpherEditor, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.AutoMorpherLogCollector
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
public class AutoMorpherLogCollector
{
private struct LogEntry
{
public DateTime utcTime;
public LogType type;
public string condition;
public string stackTrace;
}
private bool _isCapturing;
private DateTime _captureStartUtc;
private readonly List<LogEntry> _entries = new List<LogEntry>(2048);
private int entriesCapacity = 5000;
private const string logSavePath = "Assets/@Eden_Tools/Eden_AutoMorpher/Logs";
public void BeginCapture()
{
if (!this._isCapturing)
{
this._isCapturing = true;
this._entries.Clear();
this._captureStartUtc = DateTime.UtcNow;
Application.logMessageReceived += this.OnLogMessageReceived;
}
}
public void EndCapture()
{
if (this._isCapturing)
{
this._isCapturing = false;
Application.logMessageReceived -= this.OnLogMessageReceived;
}
}
public string SaveToTextFile(string defaultFileName, bool includeWarningsAndInfo)
{
this.EnsureLogDirectoryExists();
string text = defaultFileName;
if (string.IsNullOrEmpty(text))
{
text = "EdenAutoMorpher_Report.txt";
}
if (!text.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
{
text += ".txt";
}
string text2 = Path.Combine("Assets/@Eden_Tools/Eden_AutoMorpher/Logs", text);
string contents = this.BuildReportText(includeWarningsAndInfo);
File.WriteAllText(text2, contents, Encoding.UTF8);
AssetDatabase.Refresh();
Debug.Log("[AutoMorpher] Log report saved: " + text2);
return text2;
}
private void EnsureLogDirectoryExists()
{
if (AssetDatabase.IsValidFolder("Assets/@Eden_Tools/Eden_AutoMorpher/Logs"))
{
return;
}
string[] array = "Assets/@Eden_Tools/Eden_AutoMorpher/Logs".Split('/', StringSplitOptions.None);
string text = array[0];
for (int i = 1; i < array.Length; i++)
{
string text2 = text + "/" + array[i];
if (!AssetDatabase.IsValidFolder(text2))
{
AssetDatabase.CreateFolder(text, array[i]);
}
text = text2;
}
}
public string BuildReportText(bool includeWarningsAndInfo)
{
StringBuilder stringBuilder = new StringBuilder(65536);
stringBuilder.AppendLine("==== EDEN AUTO MORPHER LOG REPORT ====");
stringBuilder.AppendLine($"Captured (UTC) : {this._captureStartUtc:yyyy-MM-dd HH:mm:ss} ~ {DateTime.UtcNow:yyyy-MM-dd HH:mm:ss}");
stringBuilder.AppendLine("Unity Version : " + Application.unityVersion);
stringBuilder.AppendLine($"Platform : {Application.platform}");
stringBuilder.AppendLine("Project : " + Application.productName);
stringBuilder.AppendLine();
stringBuilder.AppendLine("---- Logs ----");
for (int i = 0; i < this._entries.Count; i++)
{
LogEntry logEntry = this._entries[i];
if (includeWarningsAndInfo || logEntry.type == LogType.Error || logEntry.type == LogType.Assert || logEntry.type == LogType.Exception)
{
stringBuilder.AppendLine($"[{i:0000}] - [{logEntry.type}] | {logEntry.utcTime:HH:mm:ss.fff} UTC");
stringBuilder.AppendLine(logEntry.condition ?? string.Empty);
if (!string.IsNullOrEmpty(logEntry.stackTrace))
{
stringBuilder.AppendLine("Details:");
stringBuilder.AppendLine(logEntry.stackTrace);
}
stringBuilder.AppendLine();
}
}
return stringBuilder.ToString();
}
private void OnLogMessageReceived(string condition, string stackTrace, LogType type)
{
if (this._isCapturing)
{
this._entries.Add(new LogEntry
{
utcTime = DateTime.UtcNow,
type = type,
condition = condition,
stackTrace = stackTrace
});
if (this._entries.Count > this.entriesCapacity)
{
this._entries.RemoveRange(0, 1000);
}
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 48dbd59641bef954eb938512667a41d1

View File

@@ -0,0 +1,304 @@
// 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.
// EdenAutoMorpherEditor, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.AutoMorpherValidator
using Eden.AutoMorpher;
using System.Text;
using UnityEngine;
public class AutoMorpherValidator
{
public bool ValidateAutoModeObjects(GameObject sourceAvatar, GameObject sourceClothes, GameObject targetAvatar, out string errorMessage)
{
return this.ValidateAutoModeObjects_Internal(sourceAvatar, sourceClothes, targetAvatar, out errorMessage);
}
public bool ValidateManualMode_AutoSetup_Objects(GameObject sourceAvatar, GameObject sourceClothes, GameObject targetAvatar, out string errorMessage)
{
return this.ValidateManualMode_AutoSetup_Objects_Internal(sourceAvatar, sourceClothes, targetAvatar, out errorMessage);
}
public bool ValidateManualModeObjects(GameObject sourceAvatar, GameObject sourceClothes, GameObject targetAvatar, GameObject targetClothes, out string errorMessage)
{
return this.ValidateManualModeObjects_Internal(sourceAvatar, sourceClothes, targetAvatar, targetClothes, out errorMessage);
}
public bool ValidateProfileModeObjects(GameObject sourceClothes, GameObject targetAvatar, out string errorMessage)
{
return this.ValidateProfileModeObjects_Internal(sourceClothes, targetAvatar, out errorMessage);
}
public bool ValidateAutoModeObjects_Internal(GameObject sourceAvatar, GameObject sourceClothes, GameObject targetAvatar, out string errorMessage)
{
StringBuilder stringBuilder = new StringBuilder();
this.ObjectNullCheck(stringBuilder, (sourceAvatar, "- Source Avatar Object"), (sourceClothes, "- Source Clothes Object"), (targetAvatar, "- Target Avatar Object"));
if (sourceClothes != null)
{
this.ClothesChildCheck(stringBuilder, sourceAvatar, sourceClothes, LanguageManager.Get("UI.Validator.SourceClothesChildCheck"));
this.HasSMRInClothes(stringBuilder, sourceClothes, "ClothesObject - There is No SkinnedMeshRenderer");
this.HasLocalArmature(stringBuilder, sourceClothes, "Source " + LanguageManager.Get("UI.Validator.ClothesArmatureCheck"));
}
if (sourceAvatar != null)
{
this.IsHumanoid(stringBuilder, sourceAvatar, LanguageManager.Get("UI.Validator.SourceAvatarAnimatorCheck"));
}
if (targetAvatar != null)
{
this.IsHumanoid(stringBuilder, targetAvatar, LanguageManager.Get("UI.Validator.TargetAvatarAnimatorCheck"));
}
if (stringBuilder.Length == 0)
{
errorMessage = null;
return true;
}
errorMessage = "Auto Mode: " + LanguageManager.Get("UI.Validator.Can'tFitting") + stringBuilder.ToString();
return false;
}
public bool ValidateProfileModeObjects_Internal(GameObject sourceClothes, GameObject targetAvatar, out string errorMessage)
{
StringBuilder stringBuilder = new StringBuilder();
this.ObjectNullCheck(stringBuilder, (sourceClothes, "- Source Clothes Object"), (targetAvatar, "- Target Avatar Object"));
if (sourceClothes != null)
{
this.HasSMRInClothes(stringBuilder, sourceClothes, "ClothesObject - There is No SkinnedMeshRenderer");
this.HasLocalArmature(stringBuilder, sourceClothes, "Source " + LanguageManager.Get("UI.Validator.ClothesArmatureCheck"));
}
if (targetAvatar != null)
{
this.IsHumanoid(stringBuilder, targetAvatar, LanguageManager.Get("UI.Validator.TargetAvatarAnimatorCheck"));
}
if (stringBuilder.Length == 0)
{
errorMessage = null;
return true;
}
errorMessage = "Profile Mode: " + LanguageManager.Get("UI.Validator.Can'tFitting") + stringBuilder.ToString();
return false;
}
public bool ValidateManualMode_AutoSetup_Objects_Internal(GameObject sourceAvatar, GameObject sourceClothes, GameObject targetAvatar, out string errorMessage)
{
StringBuilder stringBuilder = new StringBuilder();
this.ObjectNullCheck(stringBuilder, (sourceAvatar, "- Source Avatar Object"), (sourceClothes, "- Source Clothes Object"), (targetAvatar, "- Target Avatar Object"));
if (sourceClothes != null)
{
this.ClothesChildCheck(stringBuilder, sourceAvatar, sourceClothes, LanguageManager.Get("UI.Validator.SourceClothesChildCheck"));
this.HasSMRInClothes(stringBuilder, sourceClothes, "ClothesObject - There is No SkinnedMeshRenderer");
this.HasLocalArmature(stringBuilder, sourceClothes, "Source " + LanguageManager.Get("UI.Validator.ClothesArmatureCheck"));
}
if (sourceAvatar != null)
{
this.IsHumanoid(stringBuilder, sourceAvatar, LanguageManager.Get("UI.Validator.SourceAvatarAnimatorCheck"));
}
if (targetAvatar != null)
{
this.IsHumanoid(stringBuilder, targetAvatar, LanguageManager.Get("UI.Validator.TargetAvatarAnimatorCheck"));
}
if (stringBuilder.Length == 0)
{
errorMessage = null;
return true;
}
errorMessage = "Manual Mode - Auto Setup: " + LanguageManager.Get("UI.Validator.Can'tFitting") + stringBuilder.ToString();
return false;
}
private bool ValidateManualModeObjects_Internal(GameObject sourceAvatar, GameObject sourceClothes, GameObject targetAvatar, GameObject targetClothes, out string errorMessage)
{
StringBuilder stringBuilder = new StringBuilder();
this.ObjectNullCheck(stringBuilder, (sourceAvatar, "- Source Avatar Object"), (sourceClothes, "- Source Clothes Object"), (targetAvatar, "- Target Avatar Object"), (targetClothes, "- Target Clothes Object"));
if (sourceClothes != null)
{
this.ClothesChildCheck(stringBuilder, sourceAvatar, sourceClothes, LanguageManager.Get("UI.Validator.SourceClothesChildCheck"));
this.HasSMRInClothes(stringBuilder, sourceClothes, "ClothesObject - There is No SkinnedMeshRenderer");
this.HasLocalArmature(stringBuilder, sourceClothes, "Source " + LanguageManager.Get("UI.Validator.ClothesArmatureCheck"));
}
if (targetClothes != null)
{
this.ClothesChildCheck(stringBuilder, targetAvatar, targetClothes, LanguageManager.Get("UI.Validator.TargetClothesChildCheck"));
this.HasSMRInClothes(stringBuilder, targetClothes, "ClothesObject - There is No SkinnedMeshRenderer");
this.HasLocalArmature(stringBuilder, targetClothes, "Target " + LanguageManager.Get("UI.Validator.ClothesArmatureCheck"));
}
if (sourceAvatar != null)
{
this.IsHumanoid(stringBuilder, sourceAvatar, LanguageManager.Get("UI.Validator.SourceAvatarAnimatorCheck"));
}
if (targetAvatar != null)
{
this.IsHumanoid(stringBuilder, targetAvatar, LanguageManager.Get("UI.Validator.TargetAvatarAnimatorCheck"));
}
if (sourceClothes != null && targetClothes != null)
{
this.AppendSmrAndVertexCheck(stringBuilder, sourceClothes, targetClothes);
}
if (stringBuilder.Length == 0)
{
errorMessage = null;
return true;
}
errorMessage = "Manual Mode: " + LanguageManager.Get("UI.Validator.Can'tFitting") + stringBuilder.ToString();
return false;
}
private void ObjectNullCheck(StringBuilder sb, params (GameObject obj, string label)[] refs)
{
bool flag = false;
for (int i = 0; i < refs.Length; i++)
{
if (refs[i].obj == null)
{
flag = true;
break;
}
}
if (!flag)
{
return;
}
sb.AppendLine(LanguageManager.Get("UI.Validator.ReferenceCheck"));
for (int j = 0; j < refs.Length; j++)
{
if (refs[j].obj == null)
{
sb.AppendLine(refs[j].label);
}
}
}
private void ClothesChildCheck(StringBuilder sb, GameObject parentObject, GameObject childObject, string messageOnInvalid)
{
if (!(childObject == null) && (parentObject == null || !childObject.transform.IsChildOf(parentObject.transform)))
{
if (sb.Length > 0)
{
sb.AppendLine();
}
sb.AppendLine(messageOnInvalid);
}
}
private void HasSMRInClothes(StringBuilder sb, GameObject clothesRoot, string messageOnInvalid)
{
if (clothesRoot == null)
{
return;
}
SkinnedMeshRenderer[] componentsInChildren = clothesRoot.GetComponentsInChildren<SkinnedMeshRenderer>(includeInactive: true);
if (componentsInChildren == null || componentsInChildren.Length == 0)
{
if (sb.Length > 0)
{
sb.AppendLine();
}
sb.AppendLine(messageOnInvalid);
}
}
private void HasLocalArmature(StringBuilder sb, GameObject clothesRoot, string messageOnInvalid)
{
if (clothesRoot == null)
{
return;
}
SkinnedMeshRenderer[] componentsInChildren = clothesRoot.GetComponentsInChildren<SkinnedMeshRenderer>(includeInactive: true);
if (componentsInChildren == null || componentsInChildren.Length == 0)
{
return;
}
Transform transform = clothesRoot.transform;
bool flag = true;
SkinnedMeshRenderer[] array = componentsInChildren;
for (int i = 0; i < array.Length; i++)
{
Transform[] bones = array[i].bones;
if (bones == null || bones.Length == 0)
{
continue;
}
Transform[] array2 = bones;
foreach (Transform transform2 in array2)
{
if (!(transform2 == null) && !transform2.transform.IsChildOf(transform))
{
flag = false;
}
}
}
if (!flag)
{
if (sb.Length > 0)
{
sb.AppendLine();
}
sb.AppendLine(messageOnInvalid);
}
}
private bool IsHumanoid(StringBuilder sb, GameObject avatarObject, string messageOnInvalid)
{
if (avatarObject == null)
{
return false;
}
Animator component = avatarObject.GetComponent<Animator>();
if (component == null)
{
return false;
}
if (component.avatar == null)
{
return false;
}
if (!component.avatar.isHuman)
{
return false;
}
return true;
}
private void AppendSmrAndVertexCheck(StringBuilder sb, GameObject sourceClothes, GameObject targetClothes)
{
if (sourceClothes == null || targetClothes == null)
{
return;
}
SkinnedMeshRenderer[] componentsInChildren = sourceClothes.GetComponentsInChildren<SkinnedMeshRenderer>(includeInactive: true);
SkinnedMeshRenderer[] componentsInChildren2 = targetClothes.GetComponentsInChildren<SkinnedMeshRenderer>(includeInactive: true);
int num = ((componentsInChildren != null) ? componentsInChildren.Length : 0);
int num2 = ((componentsInChildren2 != null) ? componentsInChildren2.Length : 0);
if (num != num2)
{
if (sb.Length > 0)
{
sb.AppendLine();
}
sb.AppendLine(LanguageManager.Get("UI.Validator.CheckRendererCountCheck"));
sb.AppendLine($"- Source Clothes SMR : {num}");
sb.AppendLine($"- Target Clothes SMR : {num2}");
return;
}
for (int i = 0; i < num; i++)
{
SkinnedMeshRenderer skinnedMeshRenderer = componentsInChildren[i];
SkinnedMeshRenderer skinnedMeshRenderer2 = componentsInChildren2[i];
if (skinnedMeshRenderer == null || skinnedMeshRenderer2 == null)
{
continue;
}
Mesh sharedMesh = skinnedMeshRenderer.sharedMesh;
Mesh sharedMesh2 = skinnedMeshRenderer2.sharedMesh;
if (!(sharedMesh == null) && !(sharedMesh2 == null) && sharedMesh.vertexCount != sharedMesh2.vertexCount)
{
if (sb.Length > 0)
{
sb.AppendLine();
}
sb.AppendLine(LanguageManager.Get("UI.Validator.VertexCountCheck"));
sb.AppendLine($"- Source: {skinnedMeshRenderer.name} (vertices: {sharedMesh.vertexCount})");
sb.AppendLine($"- Target: {skinnedMeshRenderer2.name} (vertices: {sharedMesh2.vertexCount})");
break;
}
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 367e223b416de1d4d92bdcaee21b1df7

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 2a5cebf384008fb4fa1e1141a4845238

View File

@@ -0,0 +1,16 @@
// 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.
// EdenAutoMorpherEditor, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.ResultInfo
public class ResultInfo
{
public bool isComplicated;
public string processTyep = "";
public string processEndState = "";
public string processTime = "";
public string errorMessage = "";
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 45a0e5ffc6837dc48b871f340e85e7a4

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3f15b8b51b341c647a98a34a47707efb
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f4b157cb0292d6a43b5b593c5d80b658
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,195 @@
// 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.
// EdenAutoMorpher_ProfileSaver_Editor, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// EdenAutoMorpher_ProfileSaverEditor
using Eden.AutoMorpher;
using System;
using System.IO;
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(EdenAutoMorpher_ProfileSaver))]
public class EdenAutoMorpher_ProfileSaverEditor : Editor
{
private EdenAutoMorpher_ProfileSaver saver;
private ProfileUtils profileUtils;
private string errorMessage;
private bool hasError;
private void OnEnable()
{
this.saver = (EdenAutoMorpher_ProfileSaver)base.target;
this.profileUtils = new ProfileUtils();
}
public override void OnInspectorGUI()
{
base.serializedObject.Update();
this.DrawProfileVersion();
EditorGUILayout.Space(8f);
this.DrawGuideMessage();
EditorGUILayout.Space(10f);
this.DrawRequiredInputFields();
EditorGUILayout.Space(10f);
this.DrawSavePath();
EditorGUILayout.Space(8f);
this.ValidateInputs();
this.DrawErrorMessage();
EditorGUILayout.Space(12f);
this.DrawSaveButton();
base.serializedObject.ApplyModifiedProperties();
}
private void DrawProfileVersion()
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
int profileVersion = this.profileUtils.GetProfileVersion();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("EDEN Auto Morpher - Profile Saver", EditorStyles.boldLabel);
GUILayout.FlexibleSpace();
Language currentLanguage = LanguageManager.CurrentLanguage;
Language val = currentLanguage;
val = (Language)(object)EditorGUILayout.EnumPopup((Enum)(object)currentLanguage, GUILayout.Width(80f));
if (val != currentLanguage)
{
LanguageManager.SetLanguage(val);
GUI.FocusControl(null);
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.LabelField($"Profile Version : {profileVersion}", EditorStyles.boldLabel);
EditorGUILayout.Space(6f);
}
private void DrawGuideMessage()
{
EditorGUILayout.HelpBox("\n" + LanguageManager.Get("UI.ProfileSaver.Guide") + "\n", MessageType.Info);
}
private void DrawRequiredInputFields()
{
EditorGUILayout.LabelField("Required Input Fields", EditorStyles.boldLabel);
using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox))
{
EditorGUI.indentLevel++;
EditorGUILayout.Space(4f);
EditorGUILayout.PropertyField(base.serializedObject.FindProperty("profileName"), new GUIContent("Profile Name", LanguageManager.Get("UI.ProfileSaver.ProfileName.Tooltip")));
EditorGUILayout.Space(6f);
EditorGUILayout.PropertyField(base.serializedObject.FindProperty("sourceAvatar"), new GUIContent("Source Avatar", LanguageManager.Get("UI.ProfileSaver.SourceAvatar.Tooltip")));
EditorGUILayout.Space(6f);
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(base.serializedObject.FindProperty("sourceBodyMeshes"), new GUIContent("Source Body Meshes", LanguageManager.Get("UI.ProfileSaver.SourceBodyMeshes.Tooltip")), true);
EditorGUILayout.Space(4f);
EditorGUI.indentLevel--;
EditorGUI.indentLevel--;
}
}
private void DrawSavePath()
{
EditorGUILayout.LabelField("Save Path", EditorStyles.boldLabel);
string text = Path.Combine(this.profileUtils.GetProfileBasePath(), this.saver.profileName ?? string.Empty);
using (new EditorGUI.DisabledScope(disabled: true))
{
EditorGUILayout.TextField(text);
}
}
private void ValidateInputs()
{
this.errorMessage = "\n";
this.hasError = false;
if (string.IsNullOrEmpty(this.saver.profileName))
{
this.errorMessage = this.errorMessage + LanguageManager.Get("UI.ProfileSaver.Error.ProfileNameEmpty") + "\n";
this.hasError = true;
}
if (this.saver.sourceAvatar == null)
{
this.errorMessage = this.errorMessage + LanguageManager.Get("UI.ProfileSaver.Error.SourceAvatarNull") + "\n";
this.hasError = true;
}
else if (this.saver.sourceAvatar.GetComponent<Animator>() == null)
{
this.errorMessage = this.errorMessage + LanguageManager.Get("UI.ProfileSaver.Error.SourceAvatarAnimatorMissing") + "\n";
this.hasError = true;
}
if (this.saver.sourceBodyMeshes == null || this.saver.sourceBodyMeshes.Count == 0)
{
this.errorMessage = this.errorMessage + LanguageManager.Get("UI.ProfileSaver.Error.SourceBodyMeshesEmpty") + "\n";
this.hasError = true;
}
else
{
if (this.IsBodyMeshesContainNull())
{
this.errorMessage = this.errorMessage + LanguageManager.Get("UI.ProfileSaver.Error.SourceBodyMeshesContainNull") + "\n";
this.hasError = true;
}
if (this.saver.sourceAvatar != null && this.IsBodyMeshNotChildOfAvatar())
{
this.errorMessage = this.errorMessage + LanguageManager.Get("UI.ProfileSaver.Error.BodyMeshNotChildOfAvatar") + "\n";
this.hasError = true;
}
}
if (!this.saver.IsExistBaseData())
{
this.errorMessage = this.errorMessage + LanguageManager.Get("UI.ProfileSaver.Error.BaseDataMissing") + "\n";
this.hasError = true;
}
}
private bool IsBodyMeshesContainNull()
{
foreach (SkinnedMeshRenderer sourceBodyMesh in this.saver.sourceBodyMeshes)
{
if (sourceBodyMesh == null)
{
return true;
}
}
return false;
}
private bool IsBodyMeshNotChildOfAvatar()
{
foreach (SkinnedMeshRenderer sourceBodyMesh in this.saver.sourceBodyMeshes)
{
if (sourceBodyMesh != null && !sourceBodyMesh.transform.IsChildOf(this.saver.sourceAvatar.transform))
{
return true;
}
}
return false;
}
private void DrawErrorMessage()
{
if (this.hasError)
{
EditorGUILayout.HelpBox(this.errorMessage, MessageType.Error);
}
}
private void DrawSaveButton()
{
using (new EditorGUI.DisabledScope(this.hasError))
{
if (GUILayout.Button("Save Profile", GUILayout.Height(34f)))
{
this.saver.SaveProfile();
}
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 06e603c0e6910f74e8ae69f4b1025e99

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0a87e8255c6175649ab3d14c5d7390a0
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,17 @@
// EdenAutoMorpher_ProfileSaver_Script, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.profile.BaseKey3
public struct BaseKey3
{
public uint x;
public uint y;
public uint z;
public BaseKey3(uint x, uint y, uint z)
{
this.x = x;
this.y = y;
this.z = z;
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 33819e87e935234448269d35d6e155b5

View File

@@ -0,0 +1,29 @@
// EdenAutoMorpher_ProfileSaver_Script, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.profile.BoneData
using System;
using System.Collections.Generic;
using UnityEngine;
[Serializable]
public class BoneData
{
public int id;
public string boneName;
public string parentName;
public string hierarchyPath;
public HumanBodyBones hBone;
public int parentId;
public List<int> childrenIds;
public Vector3 rootLocalPosition;
public Quaternion rootLocalRotation;
public Vector3 rootLocalScale;
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 8d3573fd768baee41b6e2b78d647bf04

View File

@@ -0,0 +1,14 @@
// EdenAutoMorpher_ProfileSaver_Script, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.profile.BoneSpatialData
using System;
using UnityEngine;
[Serializable]
public class BoneSpatialData
{
public HumanBodyBones refBone;
public PCAData pcaData;
public VolumeData volumeData;
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 48d80c2519b3d8b4a97a8d6d5cd7b159

View File

@@ -0,0 +1,326 @@
// EdenAutoMorpher_ProfileSaver_Script, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.profile.EdenAutoMorpher_ProfileSaver
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
public class EdenAutoMorpher_ProfileSaver : MonoBehaviour
{
public Transform sourceAvatar;
public List<SkinnedMeshRenderer> sourceBodyMeshes = new List<SkinnedMeshRenderer>();
public string profileName;
private const float adjustHigh = 1.5f;
[ContextMenu("SaveProfile")]
public void SaveProfile()
{
Vector3 position = this.sourceAvatar.position;
Quaternion rotation = this.sourceAvatar.rotation;
Vector3 localScale = this.sourceAvatar.localScale;
Transform parent = this.sourceAvatar.parent;
this.sourceAvatar.SetParent(null);
this.sourceAvatar.position = Vector3.zero;
this.sourceAvatar.rotation = Quaternion.identity;
this.sourceAvatar.localScale = Vector3.one;
ProfileData newProfileData = new ProfileData();
ProfileUtils profileUtils = new ProfileUtils();
newProfileData.version = profileUtils.GetProfileVersion();
Animator component = this.sourceAvatar.GetComponent<Animator>();
if (component == null)
{
Debug.LogError("[EdenAutoMorpher_ProfileSaver] Source Avatar Has No Animator\nSet Animator to Source Avatar " + this.sourceAvatar.name);
}
Dictionary<HumanBodyBones, HashSet<Transform>> humanoidMeshBoneMap = profileUtils.GetHumanoidMeshBoneMap(component, this.sourceBodyMeshes);
List<ProfileBakedBodyMesh> list = new List<ProfileBakedBodyMesh>();
foreach (SkinnedMeshRenderer sourceBodyMesh in this.sourceBodyMeshes)
{
list.Add(new ProfileBakedBodyMesh(sourceBodyMesh));
}
this.SaveBoneData(ref newProfileData, this.sourceAvatar, humanoidMeshBoneMap, list);
ProfileUtils_BVHUtil profileUtils_BVHUtil = new ProfileUtils_BVHUtil();
ProfileBVH bVHData = profileUtils_BVHUtil.GetBVHData(this.sourceAvatar, list);
profileUtils_BVHUtil.SaveProfileBVH(bVHData, Path.Combine(profileUtils.GetProfileBasePath(), this.profileName), this.profileName);
newProfileData.neckTargetHeight = 1.5f;
this.AdjustAvatarHigh(this.sourceAvatar, humanoidMeshBoneMap, 1.5f);
foreach (ProfileBakedBodyMesh item in list)
{
item.ReBakeMesh();
}
this.SaveSpatialData(ref newProfileData, humanoidMeshBoneMap, list);
this.SaveProfileToJson(newProfileData, Path.Combine(profileUtils.GetProfileBasePath(), this.profileName), this.profileName);
this.sourceAvatar.SetParent(parent);
this.sourceAvatar.position = position;
this.sourceAvatar.rotation = rotation;
this.sourceAvatar.localScale = localScale;
}
public void SaveSpatialData(ref ProfileData newProfileData, Dictionary<HumanBodyBones, HashSet<Transform>> sourceBoneMap, List<ProfileBakedBodyMesh> sourceBodyBakedMeshes)
{
ProfileUtils profileUtils = new ProfileUtils();
HumanBodyBones[] influencedBones = new HumanBodyBones[1] { HumanBodyBones.Neck };
newProfileData.NeckSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.Neck, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[3]
{
HumanBodyBones.LeftUpperArm,
HumanBodyBones.LeftLowerArm,
HumanBodyBones.LeftHand
};
newProfileData.LeftUpperArmSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftUpperArm, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[3]
{
HumanBodyBones.RightUpperArm,
HumanBodyBones.RightLowerArm,
HumanBodyBones.RightHand
};
newProfileData.RightUpperArmSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightUpperArm, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.LeftLowerArm };
newProfileData.LeftLowerArmSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftLowerArm, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.RightLowerArm };
newProfileData.RightLowerArmSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightLowerArm, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.LeftHand };
newProfileData.LeftLowerArm_HandSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftLowerArm, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.RightHand };
newProfileData.RightLowerArm_HandSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightLowerArm, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[2]
{
HumanBodyBones.LeftUpperLeg,
HumanBodyBones.LeftLowerLeg
};
newProfileData.LeftUpperLegSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftUpperLeg, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[2]
{
HumanBodyBones.RightUpperLeg,
HumanBodyBones.RightLowerLeg
};
newProfileData.RightUpperLegSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightUpperLeg, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.LeftFoot };
newProfileData.LeftFootSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftFoot, influencedBones, sourceBoneMap, sourceBodyBakedMeshes, addChildBones: true);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.RightFoot };
newProfileData.RightFootSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightFoot, influencedBones, sourceBoneMap, sourceBodyBakedMeshes, addChildBones: true);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.Chest };
newProfileData.ChestSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.Chest, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.UpperChest };
newProfileData.UpperChestSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.UpperChest, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[2]
{
HumanBodyBones.Chest,
HumanBodyBones.UpperChest
};
newProfileData.IntegratedChestSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.Chest, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.Spine };
newProfileData.SpineSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.Spine, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.LeftHand };
newProfileData.LeftHandSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftHand, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[3]
{
HumanBodyBones.LeftThumbProximal,
HumanBodyBones.LeftThumbIntermediate,
HumanBodyBones.LeftThumbDistal
};
newProfileData.LeftHandThumbSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftThumbProximal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes, addChildBones: true);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.LeftThumbProximal };
newProfileData.LeftHandThumbProximalSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftThumbProximal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.LeftThumbIntermediate };
newProfileData.LeftHandThumbIntermediateSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftThumbIntermediate, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.LeftThumbDistal };
newProfileData.LeftHandThumbDistalSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftThumbDistal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[3]
{
HumanBodyBones.LeftIndexProximal,
HumanBodyBones.LeftIndexIntermediate,
HumanBodyBones.LeftIndexDistal
};
newProfileData.LeftHandIndexSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftIndexProximal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes, addChildBones: true);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.LeftIndexProximal };
newProfileData.LeftHandIndexProximalSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftIndexProximal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.LeftIndexIntermediate };
newProfileData.LeftHandIndexIntermediateSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftIndexIntermediate, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.LeftIndexDistal };
newProfileData.LeftHandIndexDistalSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftIndexDistal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[3]
{
HumanBodyBones.LeftMiddleProximal,
HumanBodyBones.LeftMiddleIntermediate,
HumanBodyBones.LeftMiddleDistal
};
newProfileData.LeftHandMiddleSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftMiddleProximal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes, addChildBones: true);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.LeftMiddleProximal };
newProfileData.LeftHandMiddleProximalSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftMiddleProximal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.LeftMiddleIntermediate };
newProfileData.LeftHandMiddleIntermediateSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftMiddleIntermediate, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.LeftMiddleDistal };
newProfileData.LeftHandMiddleDistalSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftMiddleDistal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[3]
{
HumanBodyBones.LeftRingProximal,
HumanBodyBones.LeftRingIntermediate,
HumanBodyBones.LeftRingDistal
};
newProfileData.LeftHandRingSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftRingProximal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes, addChildBones: true);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.LeftRingProximal };
newProfileData.LeftHandRingProximalSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftRingProximal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.LeftRingIntermediate };
newProfileData.LeftHandRingIntermediateSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftRingIntermediate, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.LeftRingDistal };
newProfileData.LeftHandRingDistalSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftRingDistal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[3]
{
HumanBodyBones.LeftLittleProximal,
HumanBodyBones.LeftLittleIntermediate,
HumanBodyBones.LeftLittleDistal
};
newProfileData.LeftHandLittleSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftLittleProximal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes, addChildBones: true);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.LeftLittleProximal };
newProfileData.LeftHandLittleProximalSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftLittleProximal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.LeftLittleIntermediate };
newProfileData.LeftHandLittleIntermediateSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftLittleIntermediate, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.LeftLittleDistal };
newProfileData.LeftHandLittleDistalSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.LeftLittleDistal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.RightHand };
newProfileData.RightHandSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightHand, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[3]
{
HumanBodyBones.RightThumbProximal,
HumanBodyBones.RightThumbIntermediate,
HumanBodyBones.RightThumbDistal
};
newProfileData.RightHandThumbSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightThumbProximal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes, addChildBones: true);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.RightThumbProximal };
newProfileData.RightHandThumbProximalSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightThumbProximal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.RightThumbIntermediate };
newProfileData.RightHandThumbIntermediateSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightThumbIntermediate, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.RightThumbDistal };
newProfileData.RightHandThumbDistalSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightThumbDistal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[3]
{
HumanBodyBones.RightIndexProximal,
HumanBodyBones.RightIndexIntermediate,
HumanBodyBones.RightIndexDistal
};
newProfileData.RightHandIndexSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightIndexProximal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes, addChildBones: true);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.RightIndexProximal };
newProfileData.RightHandIndexProximalSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightIndexProximal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.RightIndexIntermediate };
newProfileData.RightHandIndexIntermediateSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightIndexIntermediate, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.RightIndexDistal };
newProfileData.RightHandIndexDistalSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightIndexDistal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[3]
{
HumanBodyBones.RightMiddleProximal,
HumanBodyBones.RightMiddleIntermediate,
HumanBodyBones.RightMiddleDistal
};
newProfileData.RightHandMiddleSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightMiddleProximal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes, addChildBones: true);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.RightMiddleProximal };
newProfileData.RightHandMiddleProximalSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightMiddleProximal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.RightMiddleIntermediate };
newProfileData.RightHandMiddleIntermediateSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightMiddleIntermediate, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.RightMiddleDistal };
newProfileData.RightHandMiddleDistalSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightMiddleDistal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[3]
{
HumanBodyBones.RightRingProximal,
HumanBodyBones.RightRingIntermediate,
HumanBodyBones.RightRingDistal
};
newProfileData.RightHandRingSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightRingProximal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes, addChildBones: true);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.RightRingProximal };
newProfileData.RightHandRingProximalSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightRingProximal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.RightRingIntermediate };
newProfileData.RightHandRingIntermediateSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightRingIntermediate, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.RightRingDistal };
newProfileData.RightHandRingDistalSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightRingDistal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[3]
{
HumanBodyBones.RightLittleProximal,
HumanBodyBones.RightLittleIntermediate,
HumanBodyBones.RightLittleDistal
};
newProfileData.RightHandLittleSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightLittleProximal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes, addChildBones: true);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.RightLittleProximal };
newProfileData.RightHandLittleProximalSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightLittleProximal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.RightLittleIntermediate };
newProfileData.RightHandLittleIntermediateSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightLittleIntermediate, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
influencedBones = new HumanBodyBones[1] { HumanBodyBones.RightLittleDistal };
newProfileData.RightHandLittleDistalSpatialData = profileUtils.GetBoneSpatialData(HumanBodyBones.RightLittleDistal, influencedBones, sourceBoneMap, sourceBodyBakedMeshes);
}
public void SaveBoneData(ref ProfileData newProfileData, Transform sourceAvatar, Dictionary<HumanBodyBones, HashSet<Transform>> sourceBoneMap, List<ProfileBakedBodyMesh> sourceBodyBakedMeshes)
{
ProfileUtils profileUtils = new ProfileUtils();
HashSet<Transform> hashSet = new HashSet<Transform>();
foreach (ProfileBakedBodyMesh sourceBodyBakedMesh in sourceBodyBakedMeshes)
{
foreach (Transform bodyMeshBone in profileUtils.GetBodyMeshBones(sourceBodyBakedMesh.smr))
{
hashSet.Add(bodyMeshBone);
}
}
if (hashSet.Count == 0)
{
Debug.LogWarning("[EdenAutoMorpher_ProfileSaver] SaveBoneData - avatarBones is empty.");
newProfileData.boneRootId = -1;
newProfileData.bones = new List<BoneData>();
}
else
{
newProfileData.boneRootId = 0;
newProfileData.bones = profileUtils.GetBoneDatas(sourceAvatar, hashSet, sourceBoneMap);
}
}
private void AdjustAvatarHigh(Transform sourceRoot, Dictionary<HumanBodyBones, HashSet<Transform>> sourceBoneMap, float targetHeight)
{
if (!sourceBoneMap.TryGetValue(HumanBodyBones.Neck, out var value) || value.Count == 0)
{
Debug.LogError("[EdenAutoMorpher_ProfileSaver] Can't Find Neck Bones");
return;
}
float num = value.FirstOrDefault().position.y - sourceRoot.position.y;
if (Mathf.Approximately(num, 0f))
{
Debug.LogWarning($"[EdenAutoMorpher_ProfileSaver] {sourceRoot.name} Neck Y가 0에 가까워 스케일 계산을 건너뜁니다. (neckY = {num})");
return;
}
float num2 = targetHeight / num;
Vector3 localScale = sourceRoot.localScale;
localScale *= num2;
sourceRoot.localScale = localScale;
}
private void SaveProfileToJson(ProfileData profileData, string savePath, string profileName)
{
if (profileData == null)
{
Debug.LogError("[EdenAutoMorpher_ProfileSaver] ProfileData is null. Abort save.");
return;
}
if (string.IsNullOrEmpty(profileName))
{
Debug.LogError("[EdenAutoMorpher_ProfileSaver] profileName is empty.");
return;
}
string path = (profileName.EndsWith(".json") ? profileName : (profileName + ".json"));
string text = Path.Combine(Application.dataPath, savePath ?? string.Empty);
if (!Directory.Exists(text))
{
Directory.CreateDirectory(text);
}
string text2 = Path.Combine(text, path);
string contents = JsonUtility.ToJson(profileData, prettyPrint: true);
File.WriteAllText(text2, contents);
Debug.Log("[EdenAutoMorpher_ProfileSaver] Profile saved successfully.\nPath: " + text2);
AssetDatabase.Refresh();
}
public bool IsExistBaseData()
{
ProfileUtils profileUtils = new ProfileUtils();
return File.Exists(Path.Combine(Application.dataPath, profileUtils.GetBaseDataPath()));
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 2fd1a8210b48a8d49843a3f2859e67b6

View File

@@ -0,0 +1,16 @@
// EdenAutoMorpher_ProfileSaver_Script, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.profile.PCAData
using System;
using UnityEngine;
[Serializable]
public class PCAData
{
public Vector3 pcaCenter;
public Vector3 pcaPrincipalAxis;
public float pcaLength;
public float pcaAvgRadius;
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ba923ad66ccb9824aa21217281bc8f03

View File

@@ -0,0 +1,15 @@
// EdenAutoMorpher_ProfileSaver_Script, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.profile.ProfileBVH
using System.Collections.Generic;
using UnityEngine;
public class ProfileBVH
{
public List<Vector3> vertices;
public profileBVHData[] datas;
public profileBVHNode[] nodes;
public int[] dataIndices;
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ca85c008bacb4c04fab51354ef3d6365

View File

@@ -0,0 +1,89 @@
// EdenAutoMorpher_ProfileSaver_Script, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.profile.ProfileBakedBodyMesh
using UnityEngine;
public class ProfileBakedBodyMesh
{
public SkinnedMeshRenderer smr;
public Mesh bakedMesh;
public Vector3[] worldVertices;
public BoneWeight[] boneWeights
{
get
{
if (!(this.smr != null))
{
return null;
}
return this.smr.sharedMesh.boneWeights;
}
}
public Transform[] bones
{
get
{
if (!(this.smr != null))
{
return null;
}
return this.smr.bones;
}
}
public ProfileBakedBodyMesh(SkinnedMeshRenderer _smr)
{
if (_smr == null)
{
Debug.LogError("[ProfileUtil - ProfileBakedBodyMesh] BakeBodyMesh Init : SkinnedMeshRenderer " + _smr.gameObject.name + " is null");
}
this.smr = _smr;
if (_smr.sharedMesh == null)
{
Debug.LogError("[ProfileUtil - ProfileBakedBodyMesh] BakeBodyMesh Init : SkinnedMeshRenderer " + _smr.gameObject.name + " has null sharedMesh.");
}
this.bakedMesh = new Mesh();
this.smr.BakeMesh(this.bakedMesh);
this.worldVertices = this.CalculateWorldVertices(this.smr, this.bakedMesh);
}
public void ReBakeMesh()
{
this.smr.BakeMesh(this.bakedMesh);
this.worldVertices = this.CalculateWorldVertices(this.smr, this.bakedMesh);
}
~ProfileBakedBodyMesh()
{
this.smr = null;
this.bakedMesh = null;
}
private Vector3[] CalculateWorldVertices(SkinnedMeshRenderer smr, Mesh bakedMesh)
{
if (smr == null)
{
Debug.LogError("[ProfileUtil - ProfileBakedBodyMesh] CalculateWorldVertices: smr " + smr.gameObject.name + " == null");
return null;
}
if (bakedMesh == null)
{
return null;
}
Transform transform = smr.transform;
Vector3 lossyScale = transform.lossyScale;
Vector3 vector = new Vector3(1f / Mathf.Max(lossyScale.x, 1E-08f), 1f / Mathf.Max(lossyScale.y, 1E-08f), 1f / Mathf.Max(lossyScale.z, 1E-08f));
Matrix4x4 matrix4x = transform.localToWorldMatrix * Matrix4x4.Scale(vector);
Vector3[] vertices = bakedMesh.vertices;
int num = vertices.Length;
Vector3[] array = new Vector3[num];
for (int i = 0; i < num; i++)
{
array[i] = matrix4x.MultiplyPoint3x4(vertices[i]);
}
return array;
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 1b9accce356c005478e76fd0fa193f3a

View File

@@ -0,0 +1,130 @@
// EdenAutoMorpher_ProfileSaver_Script, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.profile.ProfileData
using System;
using System.Collections.Generic;
[Serializable]
public class ProfileData
{
public int version = 1;
public float neckTargetHeight = 1.5f;
public BoneSpatialData NeckSpatialData;
public BoneSpatialData LeftUpperArmSpatialData;
public BoneSpatialData RightUpperArmSpatialData;
public BoneSpatialData LeftLowerArmSpatialData;
public BoneSpatialData RightLowerArmSpatialData;
public BoneSpatialData LeftLowerArm_HandSpatialData;
public BoneSpatialData RightLowerArm_HandSpatialData;
public BoneSpatialData LeftUpperLegSpatialData;
public BoneSpatialData RightUpperLegSpatialData;
public BoneSpatialData LeftFootSpatialData;
public BoneSpatialData RightFootSpatialData;
public BoneSpatialData ChestSpatialData;
public BoneSpatialData UpperChestSpatialData;
public BoneSpatialData IntegratedChestSpatialData;
public BoneSpatialData SpineSpatialData;
public BoneSpatialData LeftHandSpatialData;
public BoneSpatialData LeftHandThumbSpatialData;
public BoneSpatialData LeftHandThumbProximalSpatialData;
public BoneSpatialData LeftHandThumbIntermediateSpatialData;
public BoneSpatialData LeftHandThumbDistalSpatialData;
public BoneSpatialData LeftHandIndexSpatialData;
public BoneSpatialData LeftHandIndexProximalSpatialData;
public BoneSpatialData LeftHandIndexIntermediateSpatialData;
public BoneSpatialData LeftHandIndexDistalSpatialData;
public BoneSpatialData LeftHandMiddleSpatialData;
public BoneSpatialData LeftHandMiddleProximalSpatialData;
public BoneSpatialData LeftHandMiddleIntermediateSpatialData;
public BoneSpatialData LeftHandMiddleDistalSpatialData;
public BoneSpatialData LeftHandRingSpatialData;
public BoneSpatialData LeftHandRingProximalSpatialData;
public BoneSpatialData LeftHandRingIntermediateSpatialData;
public BoneSpatialData LeftHandRingDistalSpatialData;
public BoneSpatialData LeftHandLittleSpatialData;
public BoneSpatialData LeftHandLittleProximalSpatialData;
public BoneSpatialData LeftHandLittleIntermediateSpatialData;
public BoneSpatialData LeftHandLittleDistalSpatialData;
public BoneSpatialData RightHandSpatialData;
public BoneSpatialData RightHandThumbSpatialData;
public BoneSpatialData RightHandThumbProximalSpatialData;
public BoneSpatialData RightHandThumbIntermediateSpatialData;
public BoneSpatialData RightHandThumbDistalSpatialData;
public BoneSpatialData RightHandIndexSpatialData;
public BoneSpatialData RightHandIndexProximalSpatialData;
public BoneSpatialData RightHandIndexIntermediateSpatialData;
public BoneSpatialData RightHandIndexDistalSpatialData;
public BoneSpatialData RightHandMiddleSpatialData;
public BoneSpatialData RightHandMiddleProximalSpatialData;
public BoneSpatialData RightHandMiddleIntermediateSpatialData;
public BoneSpatialData RightHandMiddleDistalSpatialData;
public BoneSpatialData RightHandRingSpatialData;
public BoneSpatialData RightHandRingProximalSpatialData;
public BoneSpatialData RightHandRingIntermediateSpatialData;
public BoneSpatialData RightHandRingDistalSpatialData;
public BoneSpatialData RightHandLittleSpatialData;
public BoneSpatialData RightHandLittleProximalSpatialData;
public BoneSpatialData RightHandLittleIntermediateSpatialData;
public BoneSpatialData RightHandLittleDistalSpatialData;
public int boneRootId;
public List<BoneData> bones;
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d62ebbd77f472fd4bb8abf3546d9d12a

View File

@@ -0,0 +1,264 @@
// EdenAutoMorpher_ProfileSaver_Script, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.profile.ProfileUtil_IndexUtil
using UnityEngine;
public class ProfileUtil_IndexUtil
{
public class BlockPermutations
{
private struct XorShift32
{
private uint _state;
public XorShift32(uint seed)
{
this._state = ((seed != 0) ? seed : 1831565813u);
}
public uint NextUInt()
{
uint state = this._state;
state ^= state << 13;
state ^= state >> 17;
return this._state = state ^ (state << 5);
}
public int NextInt(int maxExclusive)
{
return (int)(this.NextUInt() % (uint)maxExclusive);
}
}
private readonly int _blockSize;
private int[] _px;
private int[] _py;
private int[] _pz;
private int[] _pall;
private uint _checksum;
private int _cachedLen = -1;
private int[] _pxLen;
private int[] _pyLen;
private int[] _pzLen;
private int[] _pallLen;
public BlockPermutations(int blockSize)
{
this._blockSize = blockSize;
}
public void Build(int seed)
{
if (this._blockSize <= 1)
{
Debug.LogError("[ProfileUtil_IndexUtil] BlockPermutations.Build - invalid blockSize");
return;
}
XorShift32 rng = new XorShift32((uint)(seed ^ -1556008596));
XorShift32 rng2 = new XorShift32((uint)(seed ^ -939442524));
XorShift32 rng3 = new XorShift32((uint)(seed ^ -1383041155));
XorShift32 rng4 = new XorShift32((uint)(seed ^ 0x7E95761E));
this._px = this.MakePermutation(this._blockSize, ref rng);
this._py = this.MakePermutation(this._blockSize, ref rng2);
this._pz = this.MakePermutation(this._blockSize, ref rng3);
this._pall = this.MakePermutation(this._blockSize, ref rng4);
this._checksum = this.ComputeChecksum(this._px, this._py, this._pz, this._pall);
this._cachedLen = -1;
this._pxLen = (this._pyLen = (this._pzLen = (this._pallLen = null)));
}
public bool ValidateRebuild(int seed)
{
uint checksum = this._checksum;
BlockPermutations blockPermutations = new BlockPermutations(this._blockSize);
blockPermutations.Build(seed);
return blockPermutations._checksum == checksum;
}
public void GetPermutationsForLen(int len, out int[] pxUse, out int[] pyUse, out int[] pzUse, out int[] pallUse)
{
if (len == this._blockSize)
{
pxUse = this._px;
pyUse = this._py;
pzUse = this._pz;
pallUse = this._pall;
return;
}
if (this._cachedLen != len)
{
this._cachedLen = len;
this._pxLen = this.MakeSubPermutation(this._px, len);
this._pyLen = this.MakeSubPermutation(this._py, len);
this._pzLen = this.MakeSubPermutation(this._pz, len);
this._pallLen = this.MakeSubPermutation(this._pall, len);
}
pxUse = this._pxLen;
pyUse = this._pyLen;
pzUse = this._pzLen;
pallUse = this._pallLen;
}
private int[] MakeSubPermutation(int[] fullPerm, int len)
{
int[] array = new int[len];
int num = 0;
for (int i = 0; i < fullPerm.Length; i++)
{
if (num >= len)
{
break;
}
int num2 = fullPerm[i];
if (num2 < len)
{
array[num++] = num2;
}
}
return array;
}
private int[] MakePermutation(int n, ref XorShift32 rng)
{
int[] array = new int[n];
for (int i = 0; i < n; i++)
{
array[i] = i;
}
for (int num = n - 1; num > 0; num--)
{
int num2 = rng.NextInt(num + 1);
ref int reference = ref array[num];
ref int reference2 = ref array[num2];
int num3 = array[num2];
int num4 = array[num];
reference = num3;
reference2 = num4;
}
return array;
}
private uint ComputeChecksum(int[] a, int[] b, int[] c, int[] d)
{
uint h = 2166136261u;
this.MixArray(ref h, a);
this.MixArray(ref h, b);
this.MixArray(ref h, c);
this.MixArray(ref h, d);
return h;
}
private void MixArray(ref uint h, int[] arr)
{
for (int i = 0; i < arr.Length; i++)
{
uint num = (uint)arr[i];
h ^= num;
h *= 16777619u;
}
}
}
public readonly int blockSize = 9783;
private readonly BlockPermutations _perm;
private float[] _xTmp;
private float[] _yTmp;
private float[] _zTmp;
public ProfileUtil_IndexUtil(int blockSize = 9783)
{
this.blockSize = blockSize;
this._perm = new BlockPermutations(blockSize);
this._xTmp = new float[blockSize];
this._yTmp = new float[blockSize];
this._zTmp = new float[blockSize];
}
public void Build(int seed)
{
this._perm.Build(seed);
}
public void EncodeInto(Vector3[] input, Vector3[] output)
{
if (input == null || output == null)
{
Debug.LogError("[ProfileUtil_IndexUtil] EncodeInto - null args");
return;
}
if (output.Length < input.Length)
{
Debug.LogError("[ProfileUtil_IndexUtil] EncodeInto - output too small");
return;
}
int num = input.Length;
int num2 = this.blockSize;
int num3 = (num + num2 - 1) / num2;
for (int i = 0; i < num3; i++)
{
int num4 = i * num2;
int num5 = Mathf.Min(num2, num - num4);
this._perm.GetPermutationsForLen(num5, out var pxUse, out var pyUse, out var pzUse, out var pallUse);
for (int j = 0; j < num5; j++)
{
Vector3 vector = input[num4 + j];
this._xTmp[pxUse[j]] = vector.x;
this._yTmp[pyUse[j]] = vector.y;
this._zTmp[pzUse[j]] = vector.z;
}
for (int k = 0; k < num5; k++)
{
int num6 = pallUse[k];
output[num4 + num6] = new Vector3(this._xTmp[k], this._yTmp[k], this._zTmp[k]);
}
}
}
public void DecodeInto(Vector3[] encoded, Vector3[] output)
{
if (encoded == null || output == null)
{
Debug.LogError("[ProfileUtil_IndexUtil] DecodeInto - null args");
return;
}
if (output.Length < encoded.Length)
{
Debug.LogError("[ProfileUtil_IndexUtil] DecodeInto - output too small");
return;
}
int num = encoded.Length;
int num2 = this.blockSize;
int num3 = (num + num2 - 1) / num2;
for (int i = 0; i < num3; i++)
{
int num4 = i * num2;
int num5 = Mathf.Min(num2, num - num4);
this._perm.GetPermutationsForLen(num5, out var pxUse, out var pyUse, out var pzUse, out var pallUse);
for (int j = 0; j < num5; j++)
{
int num6 = pallUse[j];
Vector3 vector = encoded[num4 + num6];
this._xTmp[j] = vector.x;
this._yTmp[j] = vector.y;
this._zTmp[j] = vector.z;
}
for (int k = 0; k < num5; k++)
{
output[num4 + k] = new Vector3(this._xTmp[pxUse[k]], this._yTmp[pyUse[k]], this._zTmp[pzUse[k]]);
}
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 08f2754ac23e3bd419413380289a1d1f

View File

@@ -0,0 +1,72 @@
// EdenAutoMorpher_ProfileSaver_Script, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.profile.ProfileUtils
using System.Collections.Generic;
using UnityEngine;
public class ProfileUtils
{
private ProfileUtils_BoneUtil boneUtil;
private ProfileUtils_PoseUtil poseUtil;
private string profileBasePath = "@Eden_Tools\\Eden_AutoMorpher\\Profiles";
private string baseDataPath = "@Eden_Tools\\Eden_AutoMorpher\\ProfileSaver\\BaseData\\base.vb";
private int profileVersion = 1;
private string profileMagic = "PBVH";
private string baseMagic = "PVTB";
public ProfileUtils()
{
this.boneUtil = new ProfileUtils_BoneUtil();
this.poseUtil = new ProfileUtils_PoseUtil();
}
public string GetProfileBasePath()
{
return this.profileBasePath;
}
public string GetBaseDataPath()
{
return this.baseDataPath;
}
public int GetProfileVersion()
{
return this.profileVersion;
}
public string GetProfileMagic()
{
return this.profileMagic;
}
public string GetBaseMagic()
{
return this.baseMagic;
}
public Dictionary<HumanBodyBones, HashSet<Transform>> GetHumanoidMeshBoneMap(Animator animator, IReadOnlyList<SkinnedMeshRenderer> bodyMeshes, float posTolerance = 0.0001f, float weightThreshold = 0.0001f)
{
return this.boneUtil.GetHumanoidMeshBoneMap(animator, bodyMeshes, posTolerance, weightThreshold);
}
public BoneSpatialData GetBoneSpatialData(HumanBodyBones refBone, HumanBodyBones[] influencedBones, Dictionary<HumanBodyBones, HashSet<Transform>> boneMap, List<ProfileBakedBodyMesh> sourceBodyBakedMeshes, bool addChildBones = false)
{
return this.poseUtil.GetBoneSpatialData(refBone, influencedBones, boneMap, sourceBodyBakedMeshes, addChildBones);
}
public HashSet<Transform> GetBodyMeshBones(SkinnedMeshRenderer smr, float weightThreshold = 0.0001f)
{
return this.boneUtil.GetBodyMeshBones(smr, weightThreshold);
}
public List<BoneData> GetBoneDatas(Transform rootTransform, HashSet<Transform> avatarBones, Dictionary<HumanBodyBones, HashSet<Transform>> sourceBoneMap)
{
return this.boneUtil.GetBoneDatas(rootTransform, avatarBones, sourceBoneMap);
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 0575b5a00bd94c64d96d49da0465ee70

View File

@@ -0,0 +1,283 @@
// EdenAutoMorpher_ProfileSaver_Script, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.profile.ProfileUtils_BVHUtil
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;
public class ProfileUtils_BVHUtil
{
private const int LeafMaxTriangles = 4;
public ProfileBVH GetBVHData(Transform rootTransform, List<ProfileBakedBodyMesh> bakedBodyMeshes)
{
return this.BuildFromSkinnedMeshes(rootTransform, bakedBodyMeshes);
}
public ProfileBVH BuildFromSkinnedMeshes(Transform rootTransform, List<ProfileBakedBodyMesh> bakedBodyMeshes)
{
ProfileBVH profileBVH = new ProfileBVH
{
vertices = new List<Vector3>(1024)
};
int num = 0;
foreach (ProfileBakedBodyMesh bakedBodyMesh in bakedBodyMeshes)
{
if (bakedBodyMesh != null && !(bakedBodyMesh.smr == null) && !(bakedBodyMesh.smr.sharedMesh == null))
{
num += bakedBodyMesh.smr.sharedMesh.triangles.Length / 3;
}
}
if (num == 0)
{
return null;
}
profileBVH.datas = new profileBVHData[num];
Matrix4x4 worldToLocalMatrix = rootTransform.worldToLocalMatrix;
int num2 = 0;
foreach (ProfileBakedBodyMesh bakedBodyMesh2 in bakedBodyMeshes)
{
if (bakedBodyMesh2 != null && !(bakedBodyMesh2.smr == null) && !(bakedBodyMesh2.smr.sharedMesh == null))
{
int count = profileBVH.vertices.Count;
for (int i = 0; i < bakedBodyMesh2.worldVertices.Length; i++)
{
Vector3 item = worldToLocalMatrix.MultiplyPoint3x4(bakedBodyMesh2.worldVertices[i]);
profileBVH.vertices.Add(item);
}
int[] triangles = bakedBodyMesh2.smr.sharedMesh.triangles;
int num3 = triangles.Length / 3;
for (int j = 0; j < num3; j++)
{
int num4 = triangles[j * 3];
int num5 = triangles[j * 3 + 1];
int num6 = triangles[j * 3 + 2];
profileBVH.datas[num2++] = new profileBVHData
{
verA = count + num4,
verB = count + num5,
verC = count + num6
};
}
}
}
int num7 = num;
int[] array = new int[num7];
for (int k = 0; k < num7; k++)
{
array[k] = k;
}
profileBVH.dataIndices = array;
List<profileBVHNode> list = new List<profileBVHNode>();
this.BuildRecursive(profileBVH, array, 0, num7, list);
profileBVH.nodes = list.ToArray();
return profileBVH;
}
private int BuildRecursive(ProfileBVH bvh, int[] triIndices, int start, int count, List<profileBVHNode> outNodes)
{
int count2 = outNodes.Count;
profileBVHNode profileBVHNode2 = new profileBVHNode();
Bounds bounds = default(Bounds);
bool flag = true;
for (int i = start; i < start + count; i++)
{
profileBVHData profileBVHData2 = bvh.datas[triIndices[i]];
Vector3 vector = bvh.vertices[profileBVHData2.verA];
Vector3 point = bvh.vertices[profileBVHData2.verB];
Vector3 point2 = bvh.vertices[profileBVHData2.verC];
if (flag)
{
bounds = new Bounds(vector, Vector3.zero);
bounds.Encapsulate(point);
bounds.Encapsulate(point2);
flag = false;
}
else
{
bounds.Encapsulate(vector);
bounds.Encapsulate(point);
bounds.Encapsulate(point2);
}
}
profileBVHNode2.bounds = bounds;
if (count <= 4)
{
profileBVHNode2.isLeaf = true;
profileBVHNode2.start = start;
profileBVHNode2.count = count;
profileBVHNode2.leftChild = -1;
profileBVHNode2.rightChild = -1;
outNodes.Add(profileBVHNode2);
return count2;
}
Vector3 size = bounds.size;
int num = 0;
if (size.y > size.x && size.y > size.z)
{
num = 1;
}
else if (size.z > size.x && size.z > size.y)
{
num = 2;
}
float num2 = 0f;
for (int j = start; j < start + count; j++)
{
profileBVHData profileBVHData3 = bvh.datas[triIndices[j]];
Vector3 vector2 = bvh.vertices[profileBVHData3.verA];
Vector3 vector3 = bvh.vertices[profileBVHData3.verB];
Vector3 vector4 = bvh.vertices[profileBVHData3.verC];
num2 += ((vector2 + vector3 + vector4) / 3f)[num];
}
num2 /= (float)count;
int num3 = this.Partition(bvh, triIndices, start, count, num, num2);
if (num3 == start || num3 == start + count)
{
num3 = start + count / 2;
}
profileBVHNode2.isLeaf = false;
profileBVHNode2.start = -1;
profileBVHNode2.count = 0;
outNodes.Add(profileBVHNode2);
int leftChild = this.BuildRecursive(bvh, triIndices, start, num3 - start, outNodes);
int rightChild = this.BuildRecursive(bvh, triIndices, num3, start + count - num3, outNodes);
profileBVHNode2.leftChild = leftChild;
profileBVHNode2.rightChild = rightChild;
outNodes[count2] = profileBVHNode2;
return count2;
}
private int Partition(ProfileBVH bvh, int[] triIndices, int start, int count, int axis, float splitPos)
{
int num = start;
int num2 = start + count - 1;
while (num <= num2)
{
profileBVHData profileBVHData2 = bvh.datas[triIndices[num]];
profileBVHData profileBVHData3 = bvh.datas[triIndices[num2]];
Vector3 vector = bvh.vertices[profileBVHData2.verA];
Vector3 vector2 = bvh.vertices[profileBVHData2.verB];
Vector3 vector3 = bvh.vertices[profileBVHData2.verC];
Vector3 vector4 = bvh.vertices[profileBVHData3.verA];
Vector3 vector5 = bvh.vertices[profileBVHData3.verB];
Vector3 vector6 = bvh.vertices[profileBVHData3.verC];
float num3 = (vector[axis] + vector2[axis] + vector3[axis]) / 3f;
_ = (vector4[axis] + vector5[axis] + vector6[axis]) / 3f;
if (num3 < splitPos)
{
num++;
continue;
}
ref int reference = ref triIndices[num];
ref int reference2 = ref triIndices[num2];
int num4 = triIndices[num2];
int num5 = triIndices[num];
reference = num4;
reference2 = num5;
num2--;
}
return num;
}
public void SaveProfileBVH(ProfileBVH bvh, string savePath, string profileName)
{
if (bvh == null || bvh.vertices == null || bvh.datas == null || bvh.nodes == null || bvh.dataIndices == null)
{
Debug.LogError("[ProfileUtils_BVHUtil] SaveProfileBVH - bvh or fields are null");
return;
}
ProfileUtils profileUtils = new ProfileUtils();
int num = new System.Random().Next(int.MinValue, int.MaxValue);
int count = bvh.vertices.Count;
int version;
int countInFile;
BaseKey3[] array = new ProfileUtils_VertexUtil().LoadTable(profileUtils.GetBaseDataPath(), out version, out countInFile);
if (array == null || array.Length == 0)
{
Debug.LogError("[ProfileUtils_BVHUtil] SaveProfileBVH - failed to load base vertex table");
return;
}
Vector3[] array2 = bvh.vertices.ToArray();
for (int i = 0; i < array2.Length; i++)
{
array2[i] = this.TransformVec3(array2[i], array[i % array.Length]);
}
ProfileUtil_IndexUtil profileUtil_IndexUtil = new ProfileUtil_IndexUtil();
profileUtil_IndexUtil.Build(num);
Vector3[] array3 = new Vector3[array2.Length];
profileUtil_IndexUtil.EncodeInto(array2, array3);
StringBuilder stringBuilder = new StringBuilder(1024);
stringBuilder.Append(profileUtils.GetProfileMagic());
this.AppendHexInt(stringBuilder, profileUtils.GetProfileVersion());
this.AppendHexInt(stringBuilder, num);
this.AppendHexInt(stringBuilder, count);
this.AppendHexInt(stringBuilder, bvh.datas.Length);
this.AppendHexInt(stringBuilder, bvh.nodes.Length);
this.AppendHexInt(stringBuilder, bvh.dataIndices.Length);
for (int j = 0; j < array3.Length; j++)
{
this.AppendHexVec3(stringBuilder, array3[j]);
}
for (int k = 0; k < bvh.datas.Length; k++)
{
profileBVHData profileBVHData2 = bvh.datas[k];
this.AppendHexInt(stringBuilder, profileBVHData2.verA);
this.AppendHexInt(stringBuilder, profileBVHData2.verB);
this.AppendHexInt(stringBuilder, profileBVHData2.verC);
}
for (int l = 0; l < bvh.nodes.Length; l++)
{
profileBVHNode profileBVHNode2 = bvh.nodes[l];
this.AppendHexVec3(stringBuilder, profileBVHNode2.bounds.center);
this.AppendHexVec3(stringBuilder, profileBVHNode2.bounds.extents);
this.AppendHexInt(stringBuilder, profileBVHNode2.leftChild);
this.AppendHexInt(stringBuilder, profileBVHNode2.rightChild);
this.AppendHexInt(stringBuilder, profileBVHNode2.start);
this.AppendHexInt(stringBuilder, profileBVHNode2.count);
stringBuilder.Append(profileBVHNode2.isLeaf ? '1' : '0');
}
for (int m = 0; m < bvh.dataIndices.Length; m++)
{
this.AppendHexInt(stringBuilder, bvh.dataIndices[m]);
}
string path = (profileName.EndsWith(".eb") ? profileName : (profileName + ".eb"));
string text = Path.Combine(Application.dataPath, savePath ?? string.Empty);
if (!Directory.Exists(text))
{
Directory.CreateDirectory(text);
}
File.WriteAllText(Path.Combine(text, path), stringBuilder.ToString(), Encoding.UTF8);
}
private void AppendHexVec3(StringBuilder sb, Vector3 v)
{
this.AppendHexFloat(sb, v.x);
this.AppendHexFloat(sb, v.y);
this.AppendHexFloat(sb, v.z);
}
private void AppendHexFloat(StringBuilder sb, float v)
{
int num = BitConverter.SingleToInt32Bits(v);
uint num2 = (uint)num;
sb.Append(num2.ToString("X8"));
}
private void AppendHexInt(StringBuilder sb, int v)
{
uint num = (uint)v;
sb.Append(num.ToString("X8"));
}
private Vector3 TransformVec3(Vector3 v, BaseKey3 k)
{
return new Vector3(this.TransformFloatBits(v.x, k.x), this.TransformFloatBits(v.y, k.y), this.TransformFloatBits(v.z, k.z));
}
private float TransformFloatBits(float a, uint keyBits)
{
return BitConverter.Int32BitsToSingle(BitConverter.SingleToInt32Bits(a) ^ (int)keyBits);
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c2016668835db4f418cb2b3ef14bd00e

View File

@@ -0,0 +1,344 @@
// EdenAutoMorpher_ProfileSaver_Script, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.profile.ProfileUtils_BoneUtil
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class ProfileUtils_BoneUtil
{
public HashSet<Transform> GetBodyMeshBones(SkinnedMeshRenderer smr, float weightThreshold = 0.0001f)
{
Mesh sharedMesh = smr.sharedMesh;
if (sharedMesh == null)
{
Debug.LogError("[ProfileUtils_BoneUtil] 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>> GetHumanoidMeshBoneMap(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)
{
Debug.LogError("[MeshHumanoidBoneMatcher] Animator is Empty");
return dictionary;
}
HashSet<Transform> hashSet = new HashSet<Transform>();
if (bodyMeshes != null)
{
foreach (SkinnedMeshRenderer bodyMesh in bodyMeshes)
{
if (bodyMesh == null)
{
continue;
}
foreach (Transform activeBone in this.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 this.FindBonesByPosition(boneTransform, hashSet, posTolerance))
{
hashSet2.Add(item);
}
dictionary[humanBodyBones] = hashSet2;
}
return dictionary;
}
public HashSet<Transform> GetActiveBones(SkinnedMeshRenderer smr, float weightThreshold = 0.0001f)
{
Mesh sharedMesh = smr.sharedMesh;
if (sharedMesh == null)
{
Debug.LogError("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;
}
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) && this.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 = this.TokenizeBoneName(boneToCheckName);
string[] array2 = this.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;
}
public List<BoneData> GetBoneDatas(Transform rootTransform, HashSet<Transform> avatarBones, Dictionary<HumanBodyBones, HashSet<Transform>> sourceBoneMap)
{
Dictionary<Transform, HumanBodyBones> dictionary = new Dictionary<Transform, HumanBodyBones>();
foreach (KeyValuePair<HumanBodyBones, HashSet<Transform>> item2 in sourceBoneMap)
{
HumanBodyBones key = item2.Key;
HashSet<Transform> value = item2.Value;
if (value == null)
{
continue;
}
foreach (Transform item3 in value)
{
if (!(item3 == null) && !dictionary.ContainsKey(item3))
{
dictionary[item3] = key;
}
}
}
List<BoneData> list = new List<BoneData>();
BoneData item = new BoneData
{
id = 0,
boneName = ((rootTransform != null) ? rootTransform.name : "Root"),
parentName = null,
hierarchyPath = "",
hBone = HumanBodyBones.LastBone,
parentId = -1,
childrenIds = new List<int>(),
rootLocalPosition = Vector3.zero,
rootLocalRotation = Quaternion.identity,
rootLocalScale = Vector3.one
};
list.Add(item);
List<Transform> list2 = (from t in avatarBones
where t != null
orderby this.GetDepthFromSkeletonRoot(rootTransform, t), this.GetHierarchyPath(rootTransform, t)
select t).ToList();
Dictionary<Transform, int> dictionary2 = new Dictionary<Transform, int>(list2.Count);
int num = 1;
foreach (Transform item4 in list2)
{
dictionary2[item4] = num++;
string hierarchyPath = this.GetHierarchyPath(rootTransform, item4);
HumanBodyBones value2;
HumanBodyBones hBone = (dictionary.TryGetValue(item4, out value2) ? value2 : HumanBodyBones.LastBone);
Vector3 rootLocalPosition = ((rootTransform != null) ? rootTransform.InverseTransformPoint(item4.position) : item4.position);
Quaternion rootLocalRotation = ((rootTransform != null) ? (Quaternion.Inverse(rootTransform.rotation) * item4.rotation) : item4.rotation);
Vector3 rootLocalScale = item4.lossyScale;
if (rootTransform != null)
{
Vector3 lossyScale = rootTransform.lossyScale;
rootLocalScale = new Vector3(this.SafeDiv(rootLocalScale.x, lossyScale.x), this.SafeDiv(rootLocalScale.y, lossyScale.y), this.SafeDiv(rootLocalScale.z, lossyScale.z));
}
list.Add(new BoneData
{
id = dictionary2[item4],
boneName = item4.name,
parentName = ((item4.parent != null) ? item4.parent.name : ""),
hierarchyPath = hierarchyPath,
hBone = hBone,
parentId = -1,
childrenIds = new List<int>(),
rootLocalPosition = rootLocalPosition,
rootLocalRotation = rootLocalRotation,
rootLocalScale = rootLocalScale
});
}
Dictionary<int, List<int>> dictionary3 = new Dictionary<int, List<int>>();
foreach (BoneData item5 in list)
{
dictionary3[item5.id] = new List<int>();
}
foreach (BoneData node in list.Where((BoneData n) => n.id != 0))
{
Transform key2 = dictionary2.FirstOrDefault((KeyValuePair<Transform, int> kv) => kv.Value == node.id).Key;
int num2 = 0;
if (key2 != null)
{
Transform parent = key2.parent;
while (parent != null)
{
if (dictionary2.TryGetValue(parent, out var value3))
{
num2 = value3;
break;
}
if (parent == rootTransform)
{
num2 = 0;
break;
}
parent = parent.parent;
}
}
node.parentId = num2;
dictionary3[num2].Add(node.id);
}
foreach (BoneData item6 in list)
{
item6.childrenIds = dictionary3[item6.id];
}
return list;
}
private float SafeDiv(float a, float b)
{
if (!(Mathf.Abs(b) < 1E-08f))
{
return a / b;
}
return 0f;
}
private int GetDepthFromSkeletonRoot(Transform root, Transform t)
{
int num = 0;
Transform transform = t;
while (transform != null && transform != root)
{
num++;
transform = transform.parent;
}
return num;
}
private string GetHierarchyPath(Transform root, Transform t)
{
if (t == null)
{
return "";
}
if (root == null)
{
return t.name;
}
if (!t.IsChildOf(root) && t != root)
{
Debug.LogError("[ProfileUtils_BoneUtil] GetHierarchyPath - bone " + t.name + " is not child of root " + root.name);
return "";
}
if (t == root)
{
return "";
}
Stack<string> stack = new Stack<string>();
Transform transform = t;
while (transform != null && transform != root)
{
stack.Push(transform.name);
transform = transform.parent;
}
return string.Join("/", stack);
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: b987b9b34807b3b48b843afcb2aefa28

View File

@@ -0,0 +1,159 @@
// EdenAutoMorpher_ProfileSaver_Script, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.profile.ProfileUtils_PCAUtil
using System.Collections.Generic;
using UnityEngine;
public class ProfileUtils_PCAUtil
{
public PCAData ComputeRegionStats(IList<Vector3> points)
{
PCAData pCAData = new PCAData();
if (points == null || points.Count == 0)
{
return pCAData;
}
int count = points.Count;
Vector3 zero = Vector3.zero;
for (int i = 0; i < count; i++)
{
zero += points[i];
}
zero /= (float)count;
float num = 0f;
float num2 = 0f;
float num3 = 0f;
float num4 = 0f;
float num5 = 0f;
float num6 = 0f;
for (int j = 0; j < count; j++)
{
Vector3 vector = points[j] - zero;
num += vector.x * vector.x;
num2 += vector.x * vector.y;
num3 += vector.x * vector.z;
num4 += vector.y * vector.y;
num5 += vector.y * vector.z;
num6 += vector.z * vector.z;
}
float num7 = 1f / (float)count;
num *= num7;
num2 *= num7;
num3 *= num7;
num4 *= num7;
num5 *= num7;
num6 *= num7;
this.JacobiEigenDecomposition3x3(num, num2, num3, num4, num5, num6, out var eigenValues, out var eigenVectors);
int num8 = 0;
if (eigenValues[1] > eigenValues[num8])
{
num8 = 1;
}
if (eigenValues[2] > eigenValues[num8])
{
num8 = 2;
}
Vector3 normalized = eigenVectors[num8].normalized;
float num9 = float.PositiveInfinity;
float num10 = float.NegativeInfinity;
float num11 = 0f;
for (int k = 0; k < count; k++)
{
float num12 = Vector3.Dot(points[k] - zero, normalized);
if (num12 < num9)
{
num9 = num12;
}
if (num12 > num10)
{
num10 = num12;
}
Vector3 vector2 = zero + normalized * num12;
float magnitude = (points[k] - vector2).magnitude;
num11 += magnitude;
}
pCAData.pcaCenter = zero;
pCAData.pcaPrincipalAxis = normalized;
pCAData.pcaLength = num10 - num9;
pCAData.pcaAvgRadius = num11 / (float)count;
return pCAData;
}
private void JacobiEigenDecomposition3x3(float c00, float c01, float c02, float c11, float c12, float c22, out float[] eigenValues, out Vector3[] eigenVectors)
{
float[,] array = new float[3, 3]
{
{ c00, c01, c02 },
{ c01, c11, c12 },
{ c02, c12, c22 }
};
float[,] array2 = new float[3, 3]
{
{ 1f, 0f, 0f },
{ 0f, 1f, 0f },
{ 0f, 0f, 1f }
};
for (int i = 0; i < 32; i++)
{
int num = 0;
int num2 = 1;
float num3 = Mathf.Abs(array[0, 1]);
float num4 = Mathf.Abs(array[0, 2]);
if (num4 > num3)
{
num3 = num4;
num = 0;
num2 = 2;
}
float num5 = Mathf.Abs(array[1, 2]);
if (num5 > num3)
{
num3 = num5;
num = 1;
num2 = 2;
}
if (num3 < 1E-10f)
{
break;
}
float num6 = array[num, num];
float num7 = array[num2, num2];
float num8 = array[num, num2];
float f = 0.5f * Mathf.Atan2(2f * num8, num7 - num6);
float num9 = Mathf.Cos(f);
float num10 = Mathf.Sin(f);
for (int j = 0; j < 3; j++)
{
if (j != num && j != num2)
{
float num11 = array[j, num];
float num12 = array[j, num2];
array[j, num] = num9 * num11 - num10 * num12;
array[num, j] = array[j, num];
array[j, num2] = num10 * num11 + num9 * num12;
array[num2, j] = array[j, num2];
}
}
float num13 = num9 * num9 * num6 - 2f * num10 * num9 * num8 + num10 * num10 * num7;
float num14 = num10 * num10 * num6 + 2f * num10 * num9 * num8 + num9 * num9 * num7;
array[num, num] = num13;
array[num2, num2] = num14;
array[num, num2] = 0f;
array[num2, num] = 0f;
for (int k = 0; k < 3; k++)
{
float num15 = array2[k, num];
float num16 = array2[k, num2];
array2[k, num] = num9 * num15 - num10 * num16;
array2[k, num2] = num10 * num15 + num9 * num16;
}
}
eigenValues = new float[3];
eigenVectors = new Vector3[3];
eigenValues[0] = array[0, 0];
eigenValues[1] = array[1, 1];
eigenValues[2] = array[2, 2];
eigenVectors[0] = new Vector3(array2[0, 0], array2[1, 0], array2[2, 0]);
eigenVectors[1] = new Vector3(array2[0, 1], array2[1, 1], array2[2, 1]);
eigenVectors[2] = new Vector3(array2[0, 2], array2[1, 2], array2[2, 2]);
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 404cff939caffe44bbb6cfbb33580445

View File

@@ -0,0 +1,145 @@
// EdenAutoMorpher_ProfileSaver_Script, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.profile.ProfileUtils_PoseUtil
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class ProfileUtils_PoseUtil
{
public BoneSpatialData GetBoneSpatialData(HumanBodyBones refBone, HumanBodyBones[] influencedBones, Dictionary<HumanBodyBones, HashSet<Transform>> boneMap, List<ProfileBakedBodyMesh> sourceBodyBakedMeshes, bool addChildBones = false)
{
BoneSpatialData boneSpatialData = new BoneSpatialData();
boneSpatialData.refBone = refBone;
Transform baseBoneFromBoneMap = this.GetBaseBoneFromBoneMap(boneMap, refBone);
if (baseBoneFromBoneMap == null)
{
return null;
}
List<Vector3> refVertices = this.GetRefVertices(influencedBones, boneMap, sourceBodyBakedMeshes, addChildBones);
boneSpatialData.pcaData = this.GetPCAData(baseBoneFromBoneMap, refVertices);
Transform baseBoneFromBoneMap2 = this.GetBaseBoneFromBoneMap(boneMap, HumanBodyBones.Hips);
boneSpatialData.volumeData = this.GetVolumeData(baseBoneFromBoneMap, baseBoneFromBoneMap2, refVertices);
return boneSpatialData;
}
private List<Vector3> GetRefVertices(HumanBodyBones[] influencedBones, Dictionary<HumanBodyBones, HashSet<Transform>> boneMap, List<ProfileBakedBodyMesh> sourceBodyBakedMeshes, bool addChildBones = false, float weightThreshold = 0.15f, int sampleStep = 1)
{
List<Vector3> list = new List<Vector3>();
HashSet<Transform> targetBoneSet = new HashSet<Transform>();
foreach (HumanBodyBones key in influencedBones)
{
if (!boneMap.TryGetValue(key, out var value) || value == null)
{
continue;
}
foreach (Transform item in value)
{
if (item != null)
{
targetBoneSet.Add(item);
}
}
}
if (targetBoneSet.Count == 0)
{
string text = string.Join(", ", influencedBones.Select((HumanBodyBones b) => b.ToString()));
Debug.LogError("[ProfileSaver_PoseUtil] CollectBodyPartVerticesWorld: targetBoneSet is empty.\nMissing Humanoid Set : " + text);
return list;
}
if (addChildBones)
{
Transform[] array = targetBoneSet.ToArray();
targetBoneSet.Clear();
Transform[] array2 = array;
for (int i = 0; i < array2.Length; i++)
{
AddDescendants(array2[i]);
}
}
foreach (ProfileBakedBodyMesh sourceBodyBakedMesh in sourceBodyBakedMeshes)
{
BoneWeight[] boneWeights = sourceBodyBakedMesh.boneWeights;
Transform[] bones = sourceBodyBakedMesh.bones;
if (boneWeights == null || boneWeights.Length == 0 || bones == null || bones.Length == 0)
{
continue;
}
Vector3[] worldVertices = sourceBodyBakedMesh.worldVertices;
if (worldVertices == null || worldVertices.Length == 0)
{
continue;
}
int num = Mathf.Min(worldVertices.Length, boneWeights.Length);
for (int num2 = 0; num2 < num; num2 += sampleStep)
{
BoneWeight boneWeight = boneWeights[num2];
float wSum = 0f;
Acc(boneWeight.boneIndex0, boneWeight.weight0);
Acc(boneWeight.boneIndex1, boneWeight.weight1);
Acc(boneWeight.boneIndex2, boneWeight.weight2);
Acc(boneWeight.boneIndex3, boneWeight.weight3);
if (!(wSum < weightThreshold))
{
list.Add(worldVertices[num2]);
}
void Acc(int index, float w)
{
if (index >= 0 && index < bones.Length && !(w <= 0f))
{
Transform transform = bones[index];
if (transform != null && targetBoneSet.Contains(transform))
{
wSum += w;
}
}
}
}
}
return list;
void AddDescendants(Transform t)
{
if (!(t == null) && targetBoneSet.Add(t))
{
for (int j = 0; j < t.childCount; j++)
{
AddDescendants(t.GetChild(j));
}
}
}
}
private PCAData GetPCAData(Transform originTransform, List<Vector3> points)
{
PCAData pCAData = new ProfileUtils_PCAUtil().ComputeRegionStats(points);
if (originTransform == null)
{
return pCAData;
}
PCAData result = new PCAData
{
pcaCenter = originTransform.InverseTransformPoint(pCAData.pcaCenter),
pcaPrincipalAxis = originTransform.InverseTransformDirection(pCAData.pcaPrincipalAxis).normalized,
pcaLength = pCAData.pcaLength,
pcaAvgRadius = pCAData.pcaAvgRadius
};
if (Mathf.Abs(pCAData.pcaLength) < 0.0001f)
{
Debug.LogWarning("[ProfileUtils_PoseUtil] GetPCAData - " + originTransform.name + " Pca Length is to Small");
}
return result;
}
private VolumeData GetVolumeData(Transform originTransform, Transform axisTransform, List<Vector3> points)
{
return new ProfileUtils_VolumeUtil().GetVolumeData(originTransform, axisTransform, points);
}
private Transform GetBaseBoneFromBoneMap(Dictionary<HumanBodyBones, HashSet<Transform>> boneMap, HumanBodyBones bone)
{
if (boneMap == null || !boneMap.TryGetValue(bone, out var value) || value == null)
{
return null;
}
return value.FirstOrDefault();
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 094b9fc668fbf684aa9bd5db84b2aaad

View File

@@ -0,0 +1,77 @@
// EdenAutoMorpher_ProfileSaver_Script, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.profile.ProfileUtils_VertexUtil
using System;
using System.IO;
using System.Text;
using UnityEngine;
public class ProfileUtils_VertexUtil
{
public BaseKey3[] LoadTable(string path, out int version, out int countInFile)
{
version = 0;
countInFile = 0;
if (string.IsNullOrEmpty(path))
{
Debug.LogError("[ProfileUtil_VertexUtil] LoadTable - path is null or empty");
return null;
}
path = Path.Combine(Application.dataPath, path);
if (!File.Exists(path))
{
Debug.LogError("[ProfileUtil_VertexUtil] LoadTable - file not found");
return null;
}
string text;
try
{
text = File.ReadAllText(path, Encoding.UTF8);
}
catch (Exception ex)
{
Debug.LogError("[ProfileUtil_VertexUtil] LoadTable - read failed: " + ex.Message);
return null;
}
int num = 0;
string baseMagic = new ProfileUtils().GetBaseMagic();
if (text.Length < 4 || text.Substring(0, 4) != baseMagic)
{
Debug.LogError("[ProfileUtil_VertexUtil] LoadTable - MAGIC mismatch");
return null;
}
num += 4;
version = this.ReadHexIntSafe(text, ref num);
countInFile = this.ReadHexIntSafe(text, ref num);
if (countInFile <= 0)
{
Debug.LogError("[ProfileUtil_VertexUtil] LoadTable - invalid count");
return null;
}
BaseKey3[] array = new BaseKey3[countInFile];
for (int i = 0; i < countInFile; i++)
{
array[i] = this.ReadHexKey3Safe(text, ref num);
}
return array;
}
private int ReadHexIntSafe(string s, ref int p)
{
if (p + 8 > s.Length)
{
Debug.LogError("[ProfileUtil_VertexUtil] ReadHexIntSafe - out of range");
return 0;
}
string value = s.Substring(p, 8);
p += 8;
return (int)Convert.ToUInt32(value, 16);
}
private BaseKey3 ReadHexKey3Safe(string s, ref int p)
{
int x = this.ReadHexIntSafe(s, ref p);
uint y = (uint)this.ReadHexIntSafe(s, ref p);
uint z = (uint)this.ReadHexIntSafe(s, ref p);
return new BaseKey3((uint)x, y, z);
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 26eb8c4f9b6a08e4abb70a33d9b81ccf

View File

@@ -0,0 +1,77 @@
// EdenAutoMorpher_ProfileSaver_Script, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.profile.ProfileUtils_VolumeUtil
using System.Collections.Generic;
using UnityEngine;
public class ProfileUtils_VolumeUtil
{
public VolumeData GetVolumeData(Transform originTransform, Transform axisTransform, List<Vector3> points, int sampleStep = 1)
{
if (originTransform == null)
{
Debug.LogError("[ProfileUtils_VolumeUtil] originTransform is null");
return null;
}
if (axisTransform == null)
{
Debug.LogError("[ProfileUtils_VolumeUtil] axisTransform is null");
return null;
}
if (points == null || points.Count == 0)
{
Debug.LogError("[ProfileUtils_VolumeUtil] There is No Points to calculate volume");
return null;
}
VolumeData volumeData = new VolumeData();
Vector3 forward = axisTransform.forward;
Vector3 right = axisTransform.right;
Vector3 up = axisTransform.up;
float num = float.PositiveInfinity;
float num2 = float.NegativeInfinity;
float num3 = float.PositiveInfinity;
float num4 = float.NegativeInfinity;
float num5 = float.PositiveInfinity;
float num6 = float.NegativeInfinity;
for (int i = 0; i < points.Count; i += sampleStep)
{
Vector3 lhs = points[i] - originTransform.position;
float num7 = Vector3.Dot(lhs, up);
if (num7 < num)
{
num = num7;
}
if (num7 > num2)
{
num2 = num7;
}
float num8 = Vector3.Dot(lhs, forward);
if (num8 < num3)
{
num3 = num8;
}
if (num8 > num4)
{
num4 = num8;
}
float num9 = Vector3.Dot(lhs, right);
if (num9 < num5)
{
num5 = num9;
}
if (num9 > num6)
{
num6 = num9;
}
}
volumeData.forwardDir = forward;
volumeData.rightDir = right;
volumeData.upDir = up;
volumeData.fMaxLocalPos = originTransform.InverseTransformPoint(originTransform.position + forward * num4);
volumeData.fMinLocalPos = originTransform.InverseTransformPoint(originTransform.position + forward * num3);
volumeData.rMaxLocalPos = originTransform.InverseTransformPoint(originTransform.position + right * num6);
volumeData.rMinLocalPos = originTransform.InverseTransformPoint(originTransform.position + right * num5);
volumeData.uMaxLocalPos = originTransform.InverseTransformPoint(originTransform.position + up * num2);
volumeData.uMinLocalPos = originTransform.InverseTransformPoint(originTransform.position + up * num);
return volumeData;
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: b1bc4188262eb1140b111907361dfc56

View File

@@ -0,0 +1,26 @@
// EdenAutoMorpher_ProfileSaver_Script, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.profile.VolumeData
using System;
using UnityEngine;
[Serializable]
public class VolumeData
{
public Vector3 forwardDir;
public Vector3 rightDir;
public Vector3 upDir;
public Vector3 fMaxLocalPos;
public Vector3 fMinLocalPos;
public Vector3 rMaxLocalPos;
public Vector3 rMinLocalPos;
public Vector3 uMaxLocalPos;
public Vector3 uMinLocalPos;
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c9990806ed64171428cb56bac9d781fa

View File

@@ -0,0 +1,10 @@
// EdenAutoMorpher_ProfileSaver_Script, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.profile.profileBVHData
public class profileBVHData
{
public int verA;
public int verB;
public int verC;
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 3e693ae64a726864a88a172c17d13af9

View File

@@ -0,0 +1,18 @@
// EdenAutoMorpher_ProfileSaver_Script, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Eden.AutoMorpher.profile.profileBVHNode
using UnityEngine;
public class profileBVHNode
{
public Bounds bounds;
public int leftChild;
public int rightChild;
public int start;
public int count;
public bool isLeaf;
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d1647fc2736619c4fbf9804e952bf2c6

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 43568339d28ae25468f26127090298f4
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,56 @@
// 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.AutoMorpherDev
using System;
using System.Diagnostics;
public static class AutoMorpherDev
{
public readonly struct ScopeTimer : IDisposable
{
private readonly bool _enabled;
private readonly string _label;
private readonly Stopwatch _sw;
public ScopeTimer(bool enabled, string label)
{
this._enabled = enabled;
this._label = label;
if (enabled)
{
this._sw = Stopwatch.StartNew();
}
else
{
this._sw = null;
}
}
public void Dispose()
{
if (this._enabled && this._sw != null)
{
this._sw.Stop();
UnityEngine.Debug.Log($"[DevTimer] {this._label}: {this._sw.ElapsedMilliseconds} ms");
}
}
}
public static bool isDeveloperMode;
public static void Log(string message)
{
if (isDeveloperMode)
{
UnityEngine.Debug.Log(message);
}
}
public static ScopeTimer Profile(string label)
{
return new ScopeTimer(isDeveloperMode, label);
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 73372fe46c4d1bd4e8f8bb36159b8bb7

View File

@@ -0,0 +1,16 @@
// 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.AutoMorpherException
using System;
public class AutoMorpherException : Exception
{
public string title;
public AutoMorpherException(string title, string message)
: base(message)
{
this.title = title;
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 514ced1d3e497a246952dc49c763f668

View File

@@ -0,0 +1,30 @@
// 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.BakedBodyMesh
using UnityEngine;
public class BakedBodyMesh
{
public SkinnedMeshRenderer smr;
public Mesh bakedMesh;
public BakedBodyMesh(SkinnedMeshRenderer _smr)
{
this.smr = _smr;
this.bakedMesh = new Mesh();
this.smr.BakeMesh(this.bakedMesh);
}
public void ReBakeMesh()
{
this.smr.BakeMesh(this.bakedMesh);
}
~BakedBodyMesh()
{
this.smr = null;
this.bakedMesh = null;
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 988a170527bb2d74da01c54552bc6b7d

View File

@@ -0,0 +1,194 @@
// 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.BodyPoseMatchSetupUtil
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class BodyPoseMatchSetupUtil
{
public void AdjustAvatarScaleByNeck(Transform avatarRoot, Dictionary<HumanBodyBones, HashSet<Transform>> humanBoneMap, float targetHeight)
{
if (avatarRoot == null)
{
Debug.LogWarning("[AvatarBodyMatchUtil] NormalizeAvatarScaleByNeck: avatar == null");
return;
}
Transform boneFromBoneMap = new BodyPoseMatch_CommonUtil().GetBoneFromBoneMap(humanBoneMap, HumanBodyBones.Neck);
if (boneFromBoneMap == null)
{
Debug.LogWarning("[AvatarBodyMatchUtil] " + avatarRoot.name + " 에서 Neck 본을 찾지 못했습니다. 스케일 정규화를 건너뜁니다.");
return;
}
Transform transform = avatarRoot.transform;
float num = boneFromBoneMap.position.y - transform.position.y;
if (Mathf.Approximately(num, 0f))
{
Debug.LogWarning($"[AvatarBodyMatchUtil] {avatarRoot.name} Neck Y가 0에 가까워 스케일 계산을 건너뜁니다. (neckY = {num})");
return;
}
float num2 = targetHeight / num;
Vector3 localScale = transform.localScale;
localScale *= num2;
transform.localScale = localScale;
}
public GameObject CreateBodyProxy(Animator sourceAvatar, IReadOnlyList<SkinnedMeshRenderer> sourceBodyMeshes, out List<SkinnedMeshRenderer> proxyBodyMeshes, out Dictionary<Transform, Transform> sourceToProxy)
{
proxyBodyMeshes = null;
if (sourceAvatar == null)
{
Debug.LogError("[AvatarBodyMatchUtil] CreateSourceBodyProxy: sourceAvatar == null");
sourceToProxy = new Dictionary<Transform, Transform>();
return null;
}
GameObject clone = Object.Instantiate(sourceAvatar.gameObject);
clone.name = sourceAvatar.name + "_BodyProxy";
HashSet<Transform> remainTransforms = new HashSet<Transform>();
remainTransforms.Add(clone.transform);
Animator component = clone.GetComponent<Animator>();
if (component != null)
{
component.enabled = false;
remainTransforms.Add(component.transform);
}
if (component != null && component.avatar != null && component.avatar.isHuman)
{
for (int i = 0; i < 55; i++)
{
HumanBodyBones humanBoneId = (HumanBodyBones)i;
Transform boneTransform = component.GetBoneTransform(humanBoneId);
if (boneTransform != null)
{
remainTransforms.Add(boneTransform);
}
}
}
HashSet<Mesh> hashSet = new HashSet<Mesh>();
if (sourceBodyMeshes != null)
{
foreach (SkinnedMeshRenderer sourceBodyMesh in sourceBodyMeshes)
{
if (!(sourceBodyMesh == null) && !(sourceBodyMesh.sharedMesh == null))
{
hashSet.Add(sourceBodyMesh.sharedMesh);
}
}
}
SkinnedMeshRenderer[] componentsInChildren = clone.GetComponentsInChildren<SkinnedMeshRenderer>(includeInactive: true);
List<SkinnedMeshRenderer> list = new List<SkinnedMeshRenderer>();
SkinnedMeshRenderer[] array = componentsInChildren;
foreach (SkinnedMeshRenderer skinnedMeshRenderer in array)
{
if (!(skinnedMeshRenderer == null))
{
Mesh sharedMesh = skinnedMeshRenderer.sharedMesh;
if (!(sharedMesh == null) && hashSet.Contains(sharedMesh))
{
list.Add(skinnedMeshRenderer);
}
}
}
if (list.Count == 0)
{
Debug.LogWarning("[AvatarBodyMatchUtil] CreateSourceBodyProxy: clone에서 동일 sharedMesh를 가진 BodyMesh를 찾지 못했습니다.");
}
if (list.Count > 0)
{
MeshClassifier meshClassifier = new MeshClassifier();
foreach (SkinnedMeshRenderer item in list)
{
if (item == null)
{
continue;
}
remainTransforms.Add(item.transform);
HashSet<Transform> activeBones = meshClassifier.GetActiveBones(item);
if (activeBones == null)
{
Debug.LogWarning("[AvatarBodyMatchUtil] CreateSourceBodyProxy: clone smr '" + item.name + "' has null bones array (mesh='" + item.sharedMesh?.name + "')");
continue;
}
foreach (Transform item2 in activeBones)
{
if (!(item2 == null))
{
remainTransforms.Add(item2);
}
}
}
}
foreach (Transform item3 in remainTransforms.ToList())
{
AddWithParents(item3);
}
Transform[] componentsInChildren2 = clone.GetComponentsInChildren<Transform>(includeInactive: true);
for (int num = componentsInChildren2.Length - 1; num >= 0; num--)
{
Transform transform = componentsInChildren2[num];
if (!(transform == null) && !(transform == clone.transform) && !remainTransforms.Contains(transform))
{
Object.DestroyImmediate(transform.gameObject);
}
}
proxyBodyMeshes = list;
new BoneMatchUtil().BuildSourceToProxyBoneMap(sourceAvatar, component, out sourceToProxy);
return clone;
void AddWithParents(Transform t)
{
while (t != null && t != clone.transform)
{
remainTransforms.Add(t);
t = t.parent;
}
}
}
public Vector3 GetComprehensiveScale(Transform rootT, Dictionary<HumanBodyBones, HashSet<Transform>> clothHumanoidBoneMap, ProfileData profileData)
{
if (rootT == null)
{
throw new AutoMorpherException("Root Transform is Missing", "[BodyPoseMatch_CommonUtil] GetComprehensiveScale\n - rootT is null");
}
if (profileData.bones == null || profileData.bones.Count == 0)
{
throw new AutoMorpherException("Profile Bones are Missing", "[BodyPoseMatch_CommonUtil] GetComprehensiveScale\n - profileData.bones is null or empty");
}
Transform transform = null;
if (clothHumanoidBoneMap.TryGetValue(HumanBodyBones.Hips, out var value) && value != null && value.Count > 0)
{
foreach (Transform item in value)
{
if (item != null)
{
transform = item;
break;
}
}
}
if (transform == null)
{
throw new AutoMorpherException("Hip Transform is Missing", "[BodyPoseMatch_CommonUtil] GetComprehensiveScale\n - failed to get [hip] transform from clothHumanoidBoneMap");
}
BoneData boneData = null;
for (int i = 0; i < profileData.bones.Count; i++)
{
BoneData boneData2 = profileData.bones[i];
if (boneData2 != null && boneData2.hBone == HumanBodyBones.Hips)
{
boneData = boneData2;
break;
}
}
if (boneData == null)
{
throw new AutoMorpherException("Hip Bone Data is Missing in Profile", "[BodyPoseMatch_CommonUtil] GetComprehensiveScale\n - profileData bones does not contain Hips");
}
Vector3 rootLocalScale = boneData.rootLocalScale;
Vector3 lossyScale = rootT.lossyScale;
Vector3 lossyScale2 = transform.lossyScale;
Vector3 vector = new Vector3(lossyScale2.x / lossyScale.x, lossyScale2.y / lossyScale.y, lossyScale2.z / lossyScale.z);
return new Vector3(vector.x / rootLocalScale.x, vector.y / rootLocalScale.y, vector.z / rootLocalScale.z);
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c9574059c6a92f24bbab8bf1fdc02d9a

View File

@@ -0,0 +1,114 @@
// 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.BodyPoseMatchUtil
using System.Collections.Generic;
using UnityEngine;
public class BodyPoseMatchUtil
{
private WorldVertexUtil _worldVertexUtil;
private MeshClassifier meshClassifier;
private BodyPoseMatch_CommonUtil poseMatchCommonUtil;
private bool doDebug;
public BodyPoseMatchUtil()
{
this._worldVertexUtil = new WorldVertexUtil();
this.meshClassifier = new MeshClassifier();
this.poseMatchCommonUtil = new BodyPoseMatch_CommonUtil();
}
public GameObject AutoAdjustBodyPose(GameObject sourceAvatar, IReadOnlyList<SkinnedMeshRenderer> sourceBodyMeshes, GameObject targetAvatar, IReadOnlyList<SkinnedMeshRenderer> targetBodyMeshes, out Dictionary<Transform, Transform> sourceToProxy, float neckTargetHeight = 1.5f, bool onlyScaling = false)
{
Animator component = sourceAvatar.GetComponent<Animator>();
Animator component2 = targetAvatar.GetComponent<Animator>();
if (component == null || component2 == null)
{
Debug.LogError("[AvatarBodyMatchUtil] sourceAvatar 또는 targetAvatar가 null입니다.");
sourceToProxy = new Dictionary<Transform, Transform>();
return null;
}
Dictionary<HumanBodyBones, HashSet<Transform>> humanBoneMap = this.meshClassifier.MeshHumanoidBoneMatcher(component, sourceBodyMeshes);
Dictionary<HumanBodyBones, HashSet<Transform>> dictionary = this.meshClassifier.MeshHumanoidBoneMatcher(component2, targetBodyMeshes);
BodyPoseMatchSetupUtil bodyPoseMatchSetupUtil = new BodyPoseMatchSetupUtil();
bodyPoseMatchSetupUtil.AdjustAvatarScaleByNeck(sourceAvatar.transform, humanBoneMap, neckTargetHeight);
bodyPoseMatchSetupUtil.AdjustAvatarScaleByNeck(targetAvatar.transform, dictionary, neckTargetHeight);
List<SkinnedMeshRenderer> proxyBodyMeshes;
GameObject gameObject = bodyPoseMatchSetupUtil.CreateBodyProxy(component, sourceBodyMeshes, out proxyBodyMeshes, out sourceToProxy);
Animator component3 = gameObject.GetComponent<Animator>();
if (onlyScaling)
{
gameObject.transform.SetParent(targetAvatar.transform);
gameObject.transform.localPosition = Vector3.zero;
return gameObject;
}
Dictionary<HumanBodyBones, HashSet<Transform>> dictionary2 = this.meshClassifier.MeshHumanoidBoneMatcher(component3, proxyBodyMeshes);
if (dictionary2 == null || dictionary2.Count == 0)
{
throw new AutoMorpherException("Proxy Bone Map is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters\n - proxyBoneMap is null");
}
gameObject.transform.SetParent(targetAvatar.transform);
gameObject.transform.localPosition = Vector3.zero;
List<BakedBodyMesh> list = new List<BakedBodyMesh>();
foreach (SkinnedMeshRenderer item in proxyBodyMeshes)
{
list.Add(new BakedBodyMesh(item));
}
List<BakedBodyMesh> list2 = new List<BakedBodyMesh>();
foreach (SkinnedMeshRenderer targetBodyMesh in targetBodyMeshes)
{
list2.Add(new BakedBodyMesh(targetBodyMesh));
}
BodyPoseMatch_Torso bodyPoseMatch_Torso = new BodyPoseMatch_Torso();
bodyPoseMatch_Torso.AlignTorsoByNeck(gameObject, list, dictionary2, targetAvatar, list2, dictionary);
if (this.doDebug)
{
bodyPoseMatch_Torso.DrawTorsoPcaDebug(gameObject, list, dictionary2, Color.yellow, Color.cyan, 1f, 20f);
bodyPoseMatch_Torso.DrawTorsoPcaDebug(targetAvatar, list2, dictionary, Color.red, Color.green, 1f, 20f);
}
foreach (BakedBodyMesh item2 in list)
{
item2.ReBakeMesh();
}
BodyPoseMatch_Arm bodyPoseMatch_Arm = new BodyPoseMatch_Arm();
bodyPoseMatch_Arm.AlignUpperArmByArmPcaCenters(list, dictionary2, list2, dictionary);
if (this.doDebug)
{
bodyPoseMatch_Arm.DrawArmPcaDebug(gameObject, list, dictionary2, isLeft: true, Color.yellow, Color.cyan, 1f, 20f);
bodyPoseMatch_Arm.DrawArmPcaDebug(targetAvatar, list2, dictionary, isLeft: true, Color.red, Color.green, 1f, 20f);
}
foreach (BakedBodyMesh item3 in list)
{
item3.ReBakeMesh();
}
bodyPoseMatch_Arm.ScalingBothArmsLength(list, dictionary2, list2, dictionary);
foreach (BakedBodyMesh item4 in list)
{
item4.ReBakeMesh();
}
BodyPoseMatch_Leg bodyPoseMatch_Leg = new BodyPoseMatch_Leg();
bodyPoseMatch_Leg.AlignBothUpperLegs(gameObject, list, dictionary2, targetAvatar, list2, dictionary);
foreach (BakedBodyMesh item5 in list)
{
item5.ReBakeMesh();
}
bodyPoseMatch_Leg.ScalingBothLegsAndFoots(gameObject, list, dictionary2, targetAvatar, list2, dictionary);
if (this.doDebug)
{
foreach (BakedBodyMesh item6 in list)
{
item6.ReBakeMesh();
}
bodyPoseMatch_Leg.DrawLegPcaDebug(gameObject, list, dictionary2, isLeft: true, Color.yellow, Color.cyan, 1f, 5f);
bodyPoseMatch_Leg.DrawLegPcaDebug(gameObject, list, dictionary2, isLeft: false, Color.yellow, Color.cyan, 1f, 5f);
bodyPoseMatch_Leg.DrawLegPcaDebug(targetAvatar, list2, dictionary, isLeft: true, Color.magenta, Color.green, 1f, 5f);
bodyPoseMatch_Leg.DrawLegPcaDebug(targetAvatar, list2, dictionary, isLeft: false, Color.magenta, Color.green, 1f, 5f);
bodyPoseMatch_Arm.DrawForearmExtremeDebugPair(gameObject.gameObject, proxyBodyMeshes, targetAvatar, targetBodyMeshes, isLeft: true, 1f, 5f);
}
return gameObject;
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 40b77c723c5c82c40a80c64f4a9d7589

View File

@@ -0,0 +1,554 @@
// 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.BodyPoseMatch_Arm
using System.Collections.Generic;
using UnityEngine;
public class BodyPoseMatch_Arm
{
private readonly BodyPoseMatch_CommonUtil poseMatchCommonUtil;
public BodyPoseMatch_Arm()
{
this.poseMatchCommonUtil = new BodyPoseMatch_CommonUtil();
}
public void AlignUpperArmByArmCenters(IReadOnlyCollection<Transform> sourceLeftUpperArmSet, IReadOnlyCollection<Transform> sourceRightUpperArmSet, Vector3 sourceShoulderCenterWorld, Vector3 targetShoulderCenterWorld, Transform axisReferenceTransform, bool lockRightAxis = true)
{
if (sourceLeftUpperArmSet == null || sourceLeftUpperArmSet.Count == 0)
{
throw new AutoMorpherException("Source Left UpperArm Set is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmCenters\n - sourceLeftUpperArmSet is null or empty");
}
if (sourceRightUpperArmSet == null || sourceRightUpperArmSet.Count == 0)
{
throw new AutoMorpherException("Source Right UpperArm Set is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmCenters\n - sourceRightUpperArmSet is null or empty");
}
if (axisReferenceTransform == null)
{
throw new AutoMorpherException("Axis Reference Transform is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmCenters\n - axisReferenceTransform is null");
}
Vector3 vector = targetShoulderCenterWorld - sourceShoulderCenterWorld;
if (lockRightAxis)
{
Vector3 right = axisReferenceTransform.right;
float num = Vector3.Dot(vector, right);
vector -= right * num;
}
foreach (Transform item in sourceLeftUpperArmSet)
{
if (!(item == null))
{
item.position += vector;
}
}
foreach (Transform item2 in sourceRightUpperArmSet)
{
if (!(item2 == null))
{
item2.position += vector;
}
}
}
public void AlignUpperArmByArmPcaCenters(IReadOnlyList<BakedBodyMesh> proxyBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> proxyBoneMap, IReadOnlyList<BakedBodyMesh> targetBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap)
{
if (proxyBoneMap == null)
{
throw new AutoMorpherException("Proxy Bone Map is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters\n - proxyBoneMap is null");
}
Transform boneFromBoneMap = this.poseMatchCommonUtil.GetBoneFromBoneMap(proxyBoneMap, HumanBodyBones.Hips);
if (boneFromBoneMap == null)
{
throw new AutoMorpherException("Proxy Hips is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters\n - proxy hips transform is null");
}
RegionStats regionStats = this.ComputeArmRegionStats(proxyBakedBodyMeshes, proxyBoneMap, isLeft: true);
RegionStats regionStats2 = this.ComputeArmRegionStats(proxyBakedBodyMeshes, proxyBoneMap, isLeft: false);
bool flag = regionStats.length > 0.0001f;
bool flag2 = regionStats2.length > 0.0001f;
if (!flag && !flag2)
{
Debug.LogWarning("[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters: proxy arm PCA failed. Skip.");
return;
}
Vector3 sourceShoulderCenterWorld = this.CalculateShoulderCenter(flag, flag2, regionStats.center, regionStats2.center);
RegionStats regionStats3 = this.ComputeArmRegionStats(targetBakedBodyMeshes, targetBoneMap, isLeft: true);
RegionStats regionStats4 = this.ComputeArmRegionStats(targetBakedBodyMeshes, targetBoneMap, isLeft: false);
bool flag3 = regionStats3.length > 0.0001f;
bool flag4 = regionStats4.length > 0.0001f;
if (!flag3 && !flag4)
{
Debug.LogWarning("[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters: target arm PCA failed. Skip.");
return;
}
Vector3 targetShoulderCenterWorld = this.CalculateShoulderCenter(flag3, flag4, regionStats3.center, regionStats4.center);
if (!proxyBoneMap.TryGetValue(HumanBodyBones.LeftUpperArm, out var value) || value == null || value.Count == 0)
{
throw new AutoMorpherException("Proxy Left UpperArm Set is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters\n - proxyBoneMap has no LeftUpperArm set");
}
if (!proxyBoneMap.TryGetValue(HumanBodyBones.RightUpperArm, out var value2) || value2 == null || value2.Count == 0)
{
throw new AutoMorpherException("Proxy Right UpperArm Set is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters\n - proxyBoneMap has no RightUpperArm set");
}
this.AlignUpperArmByArmCenters(value, value2, sourceShoulderCenterWorld, targetShoulderCenterWorld, boneFromBoneMap);
}
public void AlignUpperArmByArmPcaCenters(IReadOnlyList<BakedBodyMesh> targetBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap, Dictionary<HumanBodyBones, HashSet<Transform>> clothBoneMap, Transform clothesTransform, ProfileData profileData, Vector3 comprehensiveScale)
{
if (clothBoneMap == null)
{
throw new AutoMorpherException("Cloth Bone Map is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters\n - clothBoneMap is null");
}
if (profileData == null)
{
throw new AutoMorpherException("Profile Data is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters\n - profileData is null");
}
Transform boneFromBoneMap = this.poseMatchCommonUtil.GetBoneFromBoneMap(clothBoneMap, HumanBodyBones.Hips);
if (boneFromBoneMap == null)
{
throw new AutoMorpherException("Cloth Hips is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters\n - cloth hips transform is null");
}
bool flag = profileData.LeftUpperArmSpatialData != null && profileData.LeftUpperArmSpatialData.pcaData != null && profileData.LeftUpperArmSpatialData.pcaData.pcaLength > 0.0001f;
bool flag2 = profileData.RightUpperArmSpatialData != null && profileData.RightUpperArmSpatialData.pcaData != null && profileData.RightUpperArmSpatialData.pcaData.pcaLength > 0.0001f;
if (!flag && !flag2)
{
Debug.LogWarning("[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters: profile arm data invalid. Skip.");
return;
}
Vector3 leftCenter = Vector3.zero;
if (flag)
{
leftCenter = this.poseMatchCommonUtil.GetProfilePcaCenterWorld(clothBoneMap, profileData.LeftUpperArmSpatialData, comprehensiveScale);
}
Vector3 rightCenter = Vector3.zero;
if (flag2)
{
rightCenter = this.poseMatchCommonUtil.GetProfilePcaCenterWorld(clothBoneMap, profileData.RightUpperArmSpatialData, comprehensiveScale);
}
Vector3 sourceShoulderCenterWorld = this.CalculateShoulderCenter(flag, flag2, leftCenter, rightCenter);
RegionStats regionStats = this.ComputeArmRegionStats(targetBakedBodyMeshes, targetBoneMap, isLeft: true);
RegionStats regionStats2 = this.ComputeArmRegionStats(targetBakedBodyMeshes, targetBoneMap, isLeft: false);
bool flag3 = regionStats.length > 0.0001f;
bool flag4 = regionStats2.length > 0.0001f;
if (!flag3 && !flag4)
{
Debug.LogWarning("[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters: target arm PCA failed. Skip.");
return;
}
Vector3 targetShoulderCenterWorld = this.CalculateShoulderCenter(flag3, flag4, regionStats.center, regionStats2.center);
if (!clothBoneMap.TryGetValue(HumanBodyBones.LeftUpperArm, out var value) || value == null || value.Count == 0)
{
throw new AutoMorpherException("Cloth Left UpperArm Set is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters\n - clothBoneMap has no LeftUpperArm set");
}
if (!clothBoneMap.TryGetValue(HumanBodyBones.RightUpperArm, out var value2) || value2 == null || value2.Count == 0)
{
throw new AutoMorpherException("Cloth Right UpperArm Set is Missing", "[BodyPoseMatch_Arm] AlignUpperArmByArmPcaCenters\n - clothBoneMap has no RightUpperArm set");
}
this.AlignUpperArmByArmCenters(value, value2, sourceShoulderCenterWorld, targetShoulderCenterWorld, boneFromBoneMap);
}
private Vector3 CalculateShoulderCenter(bool leftValid, bool rightValid, Vector3 leftCenter, Vector3 rightCenter)
{
if (leftValid && rightValid)
{
return 0.5f * (leftCenter + rightCenter);
}
if (leftValid)
{
return leftCenter;
}
return rightCenter;
}
public RegionStats ComputeArmRegionStats(IReadOnlyList<BakedBodyMesh> avatarBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> avatarBoneMap, bool isLeft)
{
HumanBodyBones[] targetHumanBones = ((!isLeft) ? new HumanBodyBones[3]
{
HumanBodyBones.RightUpperArm,
HumanBodyBones.RightLowerArm,
HumanBodyBones.RightHand
} : new HumanBodyBones[3]
{
HumanBodyBones.LeftUpperArm,
HumanBodyBones.LeftLowerArm,
HumanBodyBones.LeftHand
});
List<Vector3> list = this.poseMatchCommonUtil.CollectHumanoidVerticesWorld(targetHumanBones, avatarBakedBodyMeshes, avatarBoneMap);
if (list == null || list.Count == 0)
{
Debug.LogWarning($"[BodyPoseMatch_Arm] ComputeArmRegionStats: arm vertices 0. isLeft={isLeft}");
return default(RegionStats);
}
RegionStats result = new PcaUtil().ComputeRegionStats(list);
Transform boneFromBoneMap = this.poseMatchCommonUtil.GetBoneFromBoneMap(avatarBoneMap, isLeft ? HumanBodyBones.LeftUpperArm : HumanBodyBones.RightUpperArm);
Transform boneFromBoneMap2 = this.poseMatchCommonUtil.GetBoneFromBoneMap(avatarBoneMap, isLeft ? HumanBodyBones.LeftLowerArm : HumanBodyBones.RightLowerArm);
Transform boneFromBoneMap3 = this.poseMatchCommonUtil.GetBoneFromBoneMap(avatarBoneMap, isLeft ? HumanBodyBones.LeftHand : HumanBodyBones.RightHand);
Vector3 principalAxis = Vector3.zero;
if (boneFromBoneMap != null && boneFromBoneMap3 != null)
{
principalAxis = boneFromBoneMap3.position - boneFromBoneMap.position;
}
else if (boneFromBoneMap != null && boneFromBoneMap2 != null)
{
principalAxis = boneFromBoneMap2.position - boneFromBoneMap.position;
}
else if (boneFromBoneMap2 != null && boneFromBoneMap3 != null)
{
principalAxis = boneFromBoneMap3.position - boneFromBoneMap2.position;
}
if (principalAxis.sqrMagnitude > 1E-08f)
{
principalAxis.Normalize();
result.principalAxis = principalAxis;
}
return result;
}
private void ScalingUpperArmLength(Dictionary<HumanBodyBones, HashSet<Transform>> sourceBoneMap, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap, bool isLeft, bool autoDetectAxis, int forceAxisIndex)
{
HumanBodyBones humanBodyBones = (isLeft ? HumanBodyBones.LeftUpperArm : HumanBodyBones.RightUpperArm);
HumanBodyBones bone = (isLeft ? HumanBodyBones.LeftLowerArm : HumanBodyBones.RightLowerArm);
HumanBodyBones bone2 = (isLeft ? HumanBodyBones.LeftHand : HumanBodyBones.RightHand);
Transform boneFromBoneMap = this.poseMatchCommonUtil.GetBoneFromBoneMap(sourceBoneMap, humanBodyBones);
Transform boneFromBoneMap2 = this.poseMatchCommonUtil.GetBoneFromBoneMap(sourceBoneMap, bone);
Transform boneFromBoneMap3 = this.poseMatchCommonUtil.GetBoneFromBoneMap(sourceBoneMap, bone2);
Transform boneFromBoneMap4 = this.poseMatchCommonUtil.GetBoneFromBoneMap(targetBoneMap, humanBodyBones);
Transform boneFromBoneMap5 = this.poseMatchCommonUtil.GetBoneFromBoneMap(targetBoneMap, bone);
Transform boneFromBoneMap6 = this.poseMatchCommonUtil.GetBoneFromBoneMap(targetBoneMap, bone2);
HashSet<Transform> value;
if (boneFromBoneMap == null || boneFromBoneMap2 == null || boneFromBoneMap3 == null || boneFromBoneMap4 == null || boneFromBoneMap5 == null || boneFromBoneMap6 == null)
{
Debug.LogWarning("[BodyPoseMatch_Arm] ScalingSingArmLenght: some arm bones are null. Skip.");
}
else if (sourceBoneMap == null || !sourceBoneMap.TryGetValue(humanBodyBones, out value) || value == null || value.Count == 0)
{
Debug.LogWarning("[BodyPoseMatch_Arm] ScalingSingArmLenght: sourceUpperSet missing. Skip.");
}
else
{
this.poseMatchCommonUtil.BoneLengthAdjust(boneFromBoneMap, boneFromBoneMap2, boneFromBoneMap4, boneFromBoneMap5, value, autoDetectAxis, forceAxisIndex);
}
}
private void ScalingLowerArmLength(Dictionary<HumanBodyBones, HashSet<Transform>> sourceBoneMap, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap, bool isLeft, bool autoDetectAxis, int forceAxisIndex, float sourceLowerarmExtremeX, float targetLowerarmExtremeX)
{
HumanBodyBones humanBodyBones = (isLeft ? HumanBodyBones.LeftLowerArm : HumanBodyBones.RightLowerArm);
HumanBodyBones bone = (isLeft ? HumanBodyBones.LeftHand : HumanBodyBones.RightHand);
Transform boneFromBoneMap = this.poseMatchCommonUtil.GetBoneFromBoneMap(sourceBoneMap, humanBodyBones);
Transform boneFromBoneMap2 = this.poseMatchCommonUtil.GetBoneFromBoneMap(sourceBoneMap, bone);
Transform boneFromBoneMap3 = this.poseMatchCommonUtil.GetBoneFromBoneMap(targetBoneMap, humanBodyBones);
if (boneFromBoneMap == null || boneFromBoneMap2 == null || boneFromBoneMap3 == null)
{
Debug.LogWarning("[BodyPoseMatch_Arm] ScalingSingArmLenght: some arm bones are null. Skip.");
return;
}
float x = boneFromBoneMap.position.x;
float x2 = boneFromBoneMap3.position.x;
float num = Mathf.Abs(sourceLowerarmExtremeX - x);
float num2 = Mathf.Abs(targetLowerarmExtremeX - x2);
if (num < 0.0001f || num2 < 0.0001f)
{
Debug.LogWarning($"[BodyPoseMatch_Arm] ScalingSingArmLenght: span too small. source={num}, target={num2}");
return;
}
float num3 = num2 / num;
int num4 = this.ResolveArmLengthAxisIndex(boneFromBoneMap, boneFromBoneMap2, autoDetectAxis, forceAxisIndex);
Vector3 localScale = boneFromBoneMap.localScale;
switch (num4)
{
case 0:
localScale.x *= num3;
break;
case 1:
localScale.y *= num3;
break;
case 2:
localScale.z *= num3;
break;
}
foreach (Transform item in sourceBoneMap[humanBodyBones])
{
if (!(item == null))
{
item.localScale = localScale;
}
}
}
public void ScalingBothArmsLength(IReadOnlyList<BakedBodyMesh> proxyBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> proxyBoneMap, IReadOnlyList<BakedBodyMesh> targetBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap, bool autoDetectAxis = true, int forceAxisIndex = 1)
{
if (proxyBoneMap == null || targetBoneMap == null)
{
throw new AutoMorpherException("Cloth Bone Map is Missing", "[BodyPoseMatch_Arm] ScalingSingArmLenght\n - BoneMap is null");
}
this.ScalingUpperArmLength(proxyBoneMap, targetBoneMap, isLeft: true, autoDetectAxis, forceAxisIndex);
this.ScalingUpperArmLength(proxyBoneMap, targetBoneMap, isLeft: false, autoDetectAxis, forceAxisIndex);
if (proxyBakedBodyMeshes != null)
{
foreach (BakedBodyMesh proxyBakedBodyMesh in proxyBakedBodyMeshes)
{
proxyBakedBodyMesh.ReBakeMesh();
}
}
this.ScalingLowerArmLength_BodyMatch(proxyBakedBodyMeshes, proxyBoneMap, targetBakedBodyMeshes, targetBoneMap, autoDetectAxis, forceAxisIndex);
}
private void ScalingLowerArmLength_BodyMatch(IReadOnlyList<BakedBodyMesh> proxyBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> proxyBoneMap, IReadOnlyList<BakedBodyMesh> targetBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap, bool autoDetectAxis, int forceAxisIndex)
{
if (this.TryGetForearmExtremeX(proxyBakedBodyMeshes, proxyBoneMap, HumanBodyBones.LeftHand, isLeft: true, out var extremeX) && this.TryGetForearmExtremeX(targetBakedBodyMeshes, targetBoneMap, HumanBodyBones.LeftHand, isLeft: true, out var extremeX2))
{
this.ScalingLowerArmLength(proxyBoneMap, targetBoneMap, isLeft: true, autoDetectAxis, forceAxisIndex, extremeX, extremeX2);
}
else
{
Debug.LogWarning("[BodyPoseMatch_Arm] ScalingLowerArmLength_BodyMatch: left extreme calc failed. Skip left lower.");
}
if (this.TryGetForearmExtremeX(proxyBakedBodyMeshes, proxyBoneMap, HumanBodyBones.RightHand, isLeft: false, out var extremeX3) && this.TryGetForearmExtremeX(targetBakedBodyMeshes, targetBoneMap, HumanBodyBones.RightHand, isLeft: false, out var extremeX4))
{
this.ScalingLowerArmLength(proxyBoneMap, targetBoneMap, isLeft: false, autoDetectAxis, forceAxisIndex, extremeX3, extremeX4);
}
else
{
Debug.LogWarning("[BodyPoseMatch_Arm] ScalingLowerArmLength_BodyMatch: right extreme calc failed. Skip right lower.");
}
}
public void ScalingBothArmsLength(IReadOnlyList<BakedBodyMesh> targetBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap, Dictionary<HumanBodyBones, HashSet<Transform>> clothBoneMap, ProfileData profileData, Vector3 comprehensiveScale, bool autoDetectAxis = true, int forceAxisIndex = 1)
{
if (clothBoneMap == null || targetBoneMap == null)
{
throw new AutoMorpherException("Cloth Bone Map is Missing", "[BodyPoseMatch_Arm] ScalingSingArmLenght\n - BoneMap is null");
}
if (profileData == null)
{
throw new AutoMorpherException("Profile Data is Missing", "[BodyPoseMatch_Arm] ScalingSingArmLenght\n - profileData is null");
}
this.ScalingUpperArmLength(clothBoneMap, targetBoneMap, isLeft: true, autoDetectAxis, forceAxisIndex);
this.ScalingUpperArmLength(clothBoneMap, targetBoneMap, isLeft: false, autoDetectAxis, forceAxisIndex);
this.ScalingLowerArmLength_ProfileMatch(targetBakedBodyMeshes, targetBoneMap, clothBoneMap, profileData, comprehensiveScale, autoDetectAxis, forceAxisIndex);
}
private void ScalingLowerArmLength_ProfileMatch(IReadOnlyList<BakedBodyMesh> targetBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap, Dictionary<HumanBodyBones, HashSet<Transform>> clothBoneMap, ProfileData profileData, Vector3 comprehensiveScale, bool autoDetectAxis, int forceAxisIndex)
{
float extremeX;
if (profileData.LeftLowerArm_HandSpatialData == null || profileData.LeftLowerArm_HandSpatialData.volumeData == null)
{
Debug.LogWarning("[BodyPoseMatch_Arm] ScalingLowerArmLength_ProfileMatch: left spatial data missing. Skip left lower.");
}
else if (this.TryGetForearmExtremeX(targetBakedBodyMeshes, targetBoneMap, HumanBodyBones.LeftHand, isLeft: true, out extremeX))
{
float profileForearmExtremeX = this.GetProfileForearmExtremeX(clothBoneMap, profileData.LeftLowerArm_HandSpatialData, comprehensiveScale, isLeft: true);
this.ScalingLowerArmLength(clothBoneMap, targetBoneMap, isLeft: true, autoDetectAxis, forceAxisIndex, profileForearmExtremeX, extremeX);
}
else
{
Debug.LogWarning("[BodyPoseMatch_Arm] ScalingLowerArmLength_ProfileMatch: left target extreme calc failed. Skip left lower.");
}
float extremeX2;
if (profileData.RightLowerArm_HandSpatialData == null || profileData.RightLowerArm_HandSpatialData.volumeData == null)
{
Debug.LogWarning("[BodyPoseMatch_Arm] ScalingLowerArmLength_ProfileMatch: right spatial data missing. Skip right lower.");
}
else if (this.TryGetForearmExtremeX(targetBakedBodyMeshes, targetBoneMap, HumanBodyBones.RightHand, isLeft: false, out extremeX2))
{
float profileForearmExtremeX2 = this.GetProfileForearmExtremeX(clothBoneMap, profileData.RightLowerArm_HandSpatialData, comprehensiveScale, isLeft: false);
this.ScalingLowerArmLength(clothBoneMap, targetBoneMap, isLeft: false, autoDetectAxis, forceAxisIndex, profileForearmExtremeX2, extremeX2);
}
else
{
Debug.LogWarning("[BodyPoseMatch_Arm] ScalingLowerArmLength_ProfileMatch: right target extreme calc failed. Skip right lower.");
}
}
private bool TryGetForearmExtremeX(IReadOnlyList<BakedBodyMesh> bakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> boneMap, HumanBodyBones targetBone, bool isLeft, out float extremeX, float weightThreshold = 0.15f, int sampleStep = 1)
{
extremeX = (isLeft ? float.PositiveInfinity : float.NegativeInfinity);
if (bakedBodyMeshes == null || boneMap == null)
{
return false;
}
if (!boneMap.TryGetValue(targetBone, out var value) || value == null || value.Count == 0)
{
return false;
}
List<Vector3> list = this.poseMatchCommonUtil.CollectWeightedVerticesWorld(bakedBodyMeshes, value, weightThreshold, sampleStep);
if (list == null || list.Count == 0)
{
return false;
}
for (int i = 0; i < list.Count; i++)
{
float x = list[i].x;
if (isLeft)
{
if (x < extremeX)
{
extremeX = x;
}
}
else if (x > extremeX)
{
extremeX = x;
}
}
return true;
}
private float GetProfileForearmExtremeX(Dictionary<HumanBodyBones, HashSet<Transform>> clothBoneMap, BoneSpatialData spatialData, Vector3 comprehensiveScale, bool isLeft)
{
if (spatialData == null || spatialData.volumeData == null)
{
throw new AutoMorpherException("Profile Volume Data is Missing", "[BodyPoseMatch_Arm] GetProfileForearmExtremeX\n - spatialData or spatialData.volumeData is null");
}
if (this.poseMatchCommonUtil.GetBoneFromBoneMap(clothBoneMap, spatialData.refBone) == null)
{
throw new AutoMorpherException("Profile Ref Bone Transform is Missing", "[BodyPoseMatch_Arm] GetProfileForearmExtremeX\n - refBone transform is null");
}
BodyPoseMatch_CommonUtil bodyPoseMatch_CommonUtil = new BodyPoseMatch_CommonUtil();
float x = bodyPoseMatch_CommonUtil.GetProfileVolumeMinWorld(clothBoneMap, spatialData, 1, comprehensiveScale).x;
float x2 = bodyPoseMatch_CommonUtil.GetProfileVolumeMaxWorld(clothBoneMap, spatialData, 1, comprehensiveScale).x;
if (!isLeft)
{
return x2;
}
return x;
}
private int ResolveArmLengthAxisIndex(Transform lowerArm, Transform hand, bool autoDetectAxis, int forceAxisIndex)
{
if (!autoDetectAxis)
{
return Mathf.Clamp(forceAxisIndex, 0, 2);
}
Vector3 direction = hand.position - lowerArm.position;
Vector3 vector = lowerArm.InverseTransformDirection(direction);
float num = Mathf.Abs(vector.x);
float num2 = Mathf.Abs(vector.y);
float num3 = Mathf.Abs(vector.z);
if (num2 >= num && num2 >= num3)
{
return 1;
}
if (num >= num3)
{
return 0;
}
return 2;
}
public void DrawArmPcaDebug(GameObject avatarObject, IReadOnlyList<BakedBodyMesh> avatarBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> avatarBoneMap, bool isLeft, Color centerColor, Color axisColor, float axisScale = 1f, float duration = 0.1f)
{
if (avatarBakedBodyMeshes != null && avatarBoneMap != null)
{
RegionStats regionStats = this.ComputeArmRegionStats(avatarBakedBodyMeshes, avatarBoneMap, isLeft);
if (!(regionStats.length < 0.0001f))
{
Vector3 center = regionStats.center;
Vector3 vector = ((regionStats.principalAxis.sqrMagnitude > 1E-08f) ? regionStats.principalAxis.normalized : Vector3.up);
float num = 0.02f * axisScale;
Debug.DrawLine(center + Vector3.up * num, center - Vector3.up * num, centerColor, duration);
Debug.DrawLine(center + Vector3.right * num, center - Vector3.right * num, centerColor, duration);
Debug.DrawLine(center + Vector3.forward * num, center - Vector3.forward * num, centerColor, duration);
float num2 = regionStats.length * 0.5f * axisScale;
Debug.DrawLine(center - vector * num2, center + vector * num2, axisColor, duration);
}
}
}
public void DrawForearmExtremeDebugPair(GameObject proxyObject, IReadOnlyList<SkinnedMeshRenderer> proxyBodyMeshes, GameObject targetObject, IReadOnlyList<SkinnedMeshRenderer> targetBodyMeshes, bool isLeft, float size = 0.03f, float duration = 3f)
{
this.DrawForearmExtremeDebugSingle(proxyObject, proxyBodyMeshes, isLeft, Color.blue, Color.cyan, size, duration);
this.DrawForearmExtremeDebugSingle(targetObject, targetBodyMeshes, isLeft, Color.red, Color.magenta, size, duration);
}
public void DrawForearmExtremeDebugSingle(GameObject avatarObject, IReadOnlyList<SkinnedMeshRenderer> bodyMeshes, bool isLeft, Color lineColor, Color pointColor, float size = 0.03f, float duration = 3f)
{
if (avatarObject == null || bodyMeshes == null || bodyMeshes.Count == 0)
{
return;
}
Animator component = avatarObject.GetComponent<Animator>();
if (!(component == null))
{
HumanBodyBones humanBoneId = (isLeft ? HumanBodyBones.LeftLowerArm : HumanBodyBones.RightLowerArm);
Transform boneTransform = component.GetBoneTransform(humanBoneId);
if (boneTransform == null)
{
Debug.LogWarning($"[BodyPoseMatch_Arm] DrawForearmExtremeDebugSingle: elbow bone missing. isLeft={isLeft}");
return;
}
if (!this.TryGetForearmExtremePoint(component, bodyMeshes, isLeft, out var extremePos))
{
Debug.LogWarning($"[BodyPoseMatch_Arm] DrawForearmExtremeDebugSingle: extreme vertex not found. isLeft={isLeft}");
return;
}
Debug.DrawLine(boneTransform.position, extremePos, lineColor, duration);
Debug.DrawLine(extremePos + Vector3.up * size, extremePos - Vector3.up * size, pointColor, duration);
Debug.DrawLine(extremePos + Vector3.right * size, extremePos - Vector3.right * size, pointColor, duration);
Debug.DrawLine(extremePos + Vector3.forward * size, extremePos - Vector3.forward * size, pointColor, duration);
}
}
private bool TryGetForearmExtremePoint(Animator avatar, IReadOnlyList<SkinnedMeshRenderer> bodyMeshes, bool isLeft, out Vector3 extremePos)
{
extremePos = default(Vector3);
if (avatar == null || bodyMeshes == null || bodyMeshes.Count == 0)
{
return false;
}
HumanBodyBones humanBoneId = (isLeft ? HumanBodyBones.LeftHand : HumanBodyBones.RightHand);
Transform boneTransform = avatar.GetBoneTransform(humanBoneId);
if (boneTransform == null)
{
return false;
}
HashSet<Transform> targetBoneSet = new HashSet<Transform> { boneTransform };
List<BakedBodyMesh> list = new List<BakedBodyMesh>(bodyMeshes.Count);
for (int i = 0; i < bodyMeshes.Count; i++)
{
SkinnedMeshRenderer skinnedMeshRenderer = bodyMeshes[i];
if (!(skinnedMeshRenderer == null))
{
BakedBodyMesh bakedBodyMesh = new BakedBodyMesh(skinnedMeshRenderer);
bakedBodyMesh.ReBakeMesh();
list.Add(bakedBodyMesh);
}
}
if (list.Count == 0)
{
return false;
}
List<Vector3> list2 = this.poseMatchCommonUtil.CollectWeightedVerticesWorld(list, targetBoneSet, 0.1f);
if (list2 == null || list2.Count == 0)
{
return false;
}
bool flag = false;
float num = (isLeft ? float.PositiveInfinity : float.NegativeInfinity);
for (int j = 0; j < list2.Count; j++)
{
Vector3 vector = list2[j];
float x = vector.x;
if (!flag)
{
flag = true;
num = x;
extremePos = vector;
}
else if (isLeft)
{
if (x < num)
{
num = x;
extremePos = vector;
}
}
else if (x > num)
{
num = x;
extremePos = vector;
}
}
return flag;
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 60d86795fca316b438216c5648161dce

View File

@@ -0,0 +1,246 @@
// 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.BodyPoseMatch_CommonUtil
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class BodyPoseMatch_CommonUtil
{
public Transform GetBoneFromBoneMap(Dictionary<HumanBodyBones, HashSet<Transform>> boneMap, HumanBodyBones bone)
{
if (boneMap == null || !boneMap.TryGetValue(bone, out var value) || value == null)
{
return null;
}
return value.FirstOrDefault();
}
public Vector3 GetProfilePcaCenterWorld(Dictionary<HumanBodyBones, HashSet<Transform>> clothBoneMap, BoneSpatialData boneSpatialData, Vector3 comprehensiveScale, string errorContext = "")
{
if (clothBoneMap == null)
{
throw new AutoMorpherException("Cloth Bone Map is Missing", "[BodyPoseMatch_CommonUtil] GetProfilePcaCenterWorld\n - clothBoneMap is null (context=" + errorContext + ")");
}
if (boneSpatialData == null || boneSpatialData.pcaData == null)
{
throw new AutoMorpherException("Profile Bone Spatial Data is Missing", "[BodyPoseMatch_CommonUtil] GetProfilePcaCenterWorld\n - boneSpatialData or boneSpatialData.pcaData is null (context=" + errorContext + ")");
}
Transform boneFromBoneMap = this.GetBoneFromBoneMap(clothBoneMap, boneSpatialData.refBone);
if (boneFromBoneMap == null)
{
throw new AutoMorpherException("Profile Ref Bone Transform is Missing", "[BodyPoseMatch_CommonUtil] GetProfilePcaCenterWorld" + $"\n - refBone transform is null (refBone={boneSpatialData.refBone}, context={errorContext})");
}
if (this.GetBoneFromBoneMap(clothBoneMap, HumanBodyBones.Hips) == null)
{
throw new AutoMorpherException("Hip Transform is Missing", "[BodyPoseMatch_CommonUtil] GetProfilePcaCenterWorld\n - hip transform is null (context=" + errorContext + ")");
}
Vector3 pcaCenter = boneSpatialData.pcaData.pcaCenter;
Vector3 position = new Vector3(pcaCenter.x / comprehensiveScale.x, pcaCenter.y / comprehensiveScale.y, pcaCenter.z / comprehensiveScale.z);
return boneFromBoneMap.TransformPoint(position);
}
public Vector3 GetProfileVolumeMinWorld(Dictionary<HumanBodyBones, HashSet<Transform>> clothBoneMap, BoneSpatialData spatialData, int axis, Vector3 comprehensiveScale)
{
return this.GetProfileVolumeWorld(clothBoneMap, spatialData, axis, comprehensiveScale, isMin: true);
}
public Vector3 GetProfileVolumeMaxWorld(Dictionary<HumanBodyBones, HashSet<Transform>> clothBoneMap, BoneSpatialData spatialData, int axis, Vector3 comprehensiveScale)
{
return this.GetProfileVolumeWorld(clothBoneMap, spatialData, axis, comprehensiveScale, isMin: false);
}
public Vector3 GetProfileVolumeWorld(Dictionary<HumanBodyBones, HashSet<Transform>> clothBoneMap, BoneSpatialData spatialData, int axisIndex, Vector3 comprehensiveScale, bool isMin)
{
if (clothBoneMap == null)
{
throw new AutoMorpherException("Cloth Bone Map is Missing", "[BodyPoseMatch_CommonUtil] GetProfileVolumeWorld\n - clothBoneMap is null");
}
if (spatialData == null || spatialData.volumeData == null)
{
throw new AutoMorpherException("Profile Volume Data is Missing", "[BodyPoseMatch_CommonUtil] GetProfileVolumeWorld\n - spatialData or spatialData.volumeData is null");
}
Transform boneFromBoneMap = this.GetBoneFromBoneMap(clothBoneMap, spatialData.refBone);
if (boneFromBoneMap == null)
{
throw new AutoMorpherException("Profile Ref Bone Transform is Missing", "[BodyPoseMatch_CommonUtil] GetProfileVolumeWorld" + $"\n - refBone transform is null (refBone={spatialData.refBone})");
}
Vector3 vector = axisIndex switch
{
0 => isMin ? spatialData.volumeData.fMinLocalPos : spatialData.volumeData.fMaxLocalPos,
1 => isMin ? spatialData.volumeData.rMinLocalPos : spatialData.volumeData.rMaxLocalPos,
2 => isMin ? spatialData.volumeData.uMinLocalPos : spatialData.volumeData.uMaxLocalPos,
_ => throw new AutoMorpherException("Unsupported Volume Axis Index", "[BodyPoseMatch_CommonUtil] GetProfileVolumeWorld" + $"\n - axisIndex must be 0(Forward), 1(Right), 2(Up) (axisIndex={axisIndex})"),
};
Vector3 position = new Vector3(vector.x / comprehensiveScale.x, vector.y / comprehensiveScale.y, vector.z / comprehensiveScale.z);
return boneFromBoneMap.TransformPoint(position);
}
public List<Vector3> CollectWeightedVerticesWorld(IReadOnlyList<BakedBodyMesh> bakedBodyMeshes, HashSet<Transform> targetBoneSet, float weightThreshold = 0.15f, int sampleStep = 1)
{
List<Vector3> list = new List<Vector3>();
if (bakedBodyMeshes == null || targetBoneSet == null || targetBoneSet.Count == 0)
{
return list;
}
foreach (BakedBodyMesh bakedBodyMesh in bakedBodyMeshes)
{
if (bakedBodyMesh == null || bakedBodyMesh.smr == null)
{
continue;
}
Mesh sharedMesh = bakedBodyMesh.smr.sharedMesh;
if (sharedMesh == null)
{
continue;
}
BoneWeight[] boneWeights = sharedMesh.boneWeights;
Transform[] bones = bakedBodyMesh.smr.bones;
if (boneWeights == null || boneWeights.Length == 0 || bones == null || bones.Length == 0)
{
continue;
}
Vector3[] worldVerticesWithBakedMesh = new WorldVertexUtil().GetWorldVerticesWithBakedMesh(bakedBodyMesh.smr, bakedBodyMesh.bakedMesh);
if (worldVerticesWithBakedMesh == null)
{
continue;
}
int num = Mathf.Min(worldVerticesWithBakedMesh.Length, boneWeights.Length);
for (int i = 0; i < num; i += sampleStep)
{
BoneWeight boneWeight = boneWeights[i];
float wSum = 0f;
Acc(boneWeight.boneIndex0, boneWeight.weight0);
Acc(boneWeight.boneIndex1, boneWeight.weight1);
Acc(boneWeight.boneIndex2, boneWeight.weight2);
Acc(boneWeight.boneIndex3, boneWeight.weight3);
if (!(wSum < weightThreshold))
{
list.Add(worldVerticesWithBakedMesh[i]);
}
void Acc(int index, float w)
{
if (index >= 0 && index < bones.Length && !(w <= 0f))
{
Transform transform = bones[index];
if (transform != null && targetBoneSet.Contains(transform))
{
wSum += w;
}
}
}
}
}
return list;
}
public List<Vector3> CollectHumanoidVerticesWorld(IReadOnlyList<HumanBodyBones> targetHumanBones, IReadOnlyList<BakedBodyMesh> bakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> boneMap, float weightThreshold = 0.15f, int sampleStep = 1)
{
List<Vector3> result = new List<Vector3>();
if (bakedBodyMeshes == null || boneMap == null || boneMap.Count == 0 || targetHumanBones == null)
{
throw new AutoMorpherException("Invalid Arguments for CollectHumanoidVerticesWorld", "[BodyPoseMatchCommonUtil] CollectHumanoidVerticesWorld\n - bakedBodyMeshes is null OR boneMap is null/empty OR targetHumanBones is null");
}
HashSet<Transform> hashSet = new HashSet<Transform>();
foreach (HumanBodyBones targetHumanBone in targetHumanBones)
{
if (!boneMap.TryGetValue(targetHumanBone, out var value) || value == null)
{
continue;
}
foreach (Transform item in value)
{
if (item != null)
{
hashSet.Add(item);
}
}
}
if (hashSet.Count == 0)
{
Debug.Log("[AvatarBodyMatchUtil] CollectBodyPartVerticesWorld: targetBoneSet is empty.");
return result;
}
return this.CollectWeightedVerticesWorld(bakedBodyMeshes, hashSet, weightThreshold, sampleStep);
}
public void BoneLengthAdjust(Transform proxyParent, Transform proxyChild, Transform targetParent, Transform targetChild, HashSet<Transform> proxyParentSet, bool autoDetectAxis = true, int forceAxisIndex = 1)
{
if (proxyParent == null || proxyChild == null || targetParent == null || targetChild == null)
{
Debug.LogWarning("[AvatarBodyMatchUtil] MatchBoneSegmentLength: bone null");
return;
}
float num = Vector3.Distance(proxyParent.position, proxyChild.position);
float num2 = Vector3.Distance(targetParent.position, targetChild.position);
if (num < 1E-06f || num2 < 1E-06f)
{
Debug.LogWarning($"[AvatarBodyMatchUtil] MatchBoneSegmentLength: too small length. proxy={num}, target={num2}");
return;
}
float num3 = num2 / num;
int num7;
if (autoDetectAxis)
{
Vector3 direction = proxyChild.position - proxyParent.position;
Vector3 vector = proxyParent.InverseTransformDirection(direction);
float num4 = Mathf.Abs(vector.x);
float num5 = Mathf.Abs(vector.y);
float num6 = Mathf.Abs(vector.z);
num7 = ((num5 >= num4 && num5 >= num6) ? 1 : ((!(num4 >= num6)) ? 2 : 0));
}
else
{
num7 = Mathf.Clamp(forceAxisIndex, 0, 2);
}
Vector3 localScale = proxyParent.localScale;
switch (num7)
{
case 0:
localScale.x *= num3;
break;
case 1:
localScale.y *= num3;
break;
case 2:
localScale.z *= num3;
break;
}
foreach (Transform item in proxyParentSet)
{
item.localScale = localScale;
}
}
public Transform CreateTempMarker(string markerObjectName, Transform parentTransform, IReadOnlyList<Transform> childTransforms, Vector3 markerWorldPosition, Quaternion markerWorldRotation, Vector3 markerLocalScale, out TempBoneMarker tempBoneMarker)
{
if (parentTransform == null)
{
throw new AutoMorpherException("Marker Parent Transform is Missing", "[BodyPoseMatch_CommonUtil] CreateTempMarker\n - parentTransform is null");
}
if (childTransforms == null || childTransforms.Count == 0)
{
throw new AutoMorpherException("Child Transforms are Missing", "[BodyPoseMatch_CommonUtil] CreateTempMarker\n - childTransforms is null or empty");
}
Transform transform = new GameObject(string.IsNullOrEmpty(markerObjectName) ? "scaleSupportBone" : markerObjectName).transform;
transform.SetParent(parentTransform, worldPositionStays: true);
transform.position = markerWorldPosition;
transform.rotation = markerWorldRotation;
transform.localScale = markerLocalScale;
tempBoneMarker = transform.gameObject.AddComponent<TempBoneMarker>();
tempBoneMarker.originalParent = parentTransform;
tempBoneMarker.additionalInfo = "";
tempBoneMarker.wrappedChildNames = new List<string>();
for (int i = 0; i < childTransforms.Count; i++)
{
Transform transform2 = childTransforms[i];
if (!(transform2 == null))
{
tempBoneMarker.wrappedChildNames.Add(transform2.name);
transform2.SetParent(transform, worldPositionStays: true);
}
}
return transform;
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 365154814e57582478896172f94bfcca

View File

@@ -0,0 +1,625 @@
// 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.BodyPoseMatch_Leg
using System.Collections.Generic;
using UnityEngine;
public class BodyPoseMatch_Leg
{
private readonly BodyPoseMatch_CommonUtil poseMatchCommonUtil;
public BodyPoseMatch_Leg()
{
this.poseMatchCommonUtil = new BodyPoseMatch_CommonUtil();
}
public void AlignBothUpperLegs(GameObject proxyObject, IReadOnlyList<BakedBodyMesh> proxyBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> proxyBoneMap, GameObject targetObject, IReadOnlyList<BakedBodyMesh> targetBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap)
{
if (proxyObject == null || targetObject == null)
{
throw new AutoMorpherException("Proxy or Target Object is Missing", "[BodyPoseMatch_Leg] AlignBothUpperLegs\n - proxyObject or targetObject is null");
}
this.AlignUpperLeg_BodyMatch(proxyObject, proxyBakedBodyMeshes, proxyBoneMap, targetObject, targetBakedBodyMeshes, targetBoneMap, isLeft: true);
this.AlignUpperLeg_BodyMatch(proxyObject, proxyBakedBodyMeshes, proxyBoneMap, targetObject, targetBakedBodyMeshes, targetBoneMap, isLeft: false);
}
public void AlignBothUpperLegs(Transform targetTransform, IReadOnlyList<BakedBodyMesh> targetBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap, Transform clothesTransform, Dictionary<HumanBodyBones, HashSet<Transform>> clothBoneMap, ProfileData profileData, Vector3 comprehensiveScale)
{
this.AlignUpperLeg_Profile(targetTransform, targetBakedBodyMeshes, targetBoneMap, clothesTransform, clothBoneMap, profileData, comprehensiveScale, isLeft: true);
this.AlignUpperLeg_Profile(targetTransform, targetBakedBodyMeshes, targetBoneMap, clothesTransform, clothBoneMap, profileData, comprehensiveScale, isLeft: false);
}
public void AlignUpperLeg_BodyMatch(GameObject proxyObject, IReadOnlyList<BakedBodyMesh> proxyBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> proxyBoneMap, GameObject targetObject, IReadOnlyList<BakedBodyMesh> targetBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap, bool isLeft)
{
if (proxyObject == null || targetObject == null)
{
throw new AutoMorpherException("Proxy or Target Object is Missing", "[BodyPoseMatch_Leg] AlignUpperLeg_BodyMatch\n - proxyObject or targetObject is null");
}
RegionStats regionStats = this.ComputeLegRegionStats(proxyObject.transform, proxyBakedBodyMeshes, proxyBoneMap, isLeft);
RegionStats regionStats2 = this.ComputeLegRegionStats(targetObject.transform, targetBakedBodyMeshes, targetBoneMap, isLeft);
if (regionStats.length < 0.0001f || regionStats2.length < 0.0001f)
{
Debug.LogWarning("[BodyPoseMatch_Leg] AlignUpperLeg_BodyMatch: leg PCA 통계가 비정상입니다.");
return;
}
HumanBodyBones key = (isLeft ? HumanBodyBones.LeftUpperLeg : HumanBodyBones.RightUpperLeg);
if (proxyBoneMap == null || !proxyBoneMap.TryGetValue(key, out var value) || value == null || value.Count == 0)
{
Debug.LogWarning("[BodyPoseMatch_Leg] AlignUpperLeg_BodyMatch: proxy UpperLeg 본을 찾지 못했습니다.");
}
else
{
this.AlignUpperLegCore(value, regionStats.center, regionStats2.center);
}
}
public void AlignUpperLeg_Profile(Transform targetTransform, IReadOnlyList<BakedBodyMesh> targetBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap, Transform clothesTransform, Dictionary<HumanBodyBones, HashSet<Transform>> clothBoneMap, ProfileData profileData, Vector3 comprehensiveScale, bool isLeft)
{
if (targetTransform == null)
{
throw new AutoMorpherException("Target Object is Missing", "[BodyPoseMatch_Leg] AlignUpperLeg_Profile\n - targetObject is null");
}
HumanBodyBones key = (isLeft ? HumanBodyBones.LeftUpperLeg : HumanBodyBones.RightUpperLeg);
BoneSpatialData boneSpatialData = (isLeft ? profileData.LeftUpperLegSpatialData : profileData.RightUpperLegSpatialData);
if (boneSpatialData == null || boneSpatialData.pcaData == null)
{
Debug.LogWarning("[BodyPoseMatch_Leg] AlignUpperLeg: " + (isLeft ? "Left" : "Right") + " spatial data missing.");
return;
}
Vector3 profilePcaCenterWorld = this.poseMatchCommonUtil.GetProfilePcaCenterWorld(clothBoneMap, boneSpatialData, comprehensiveScale);
RegionStats regionStats = this.ComputeLegRegionStats(targetTransform, targetBakedBodyMeshes, targetBoneMap, isLeft);
HashSet<Transform> value;
if (regionStats.length < 0.0001f)
{
Debug.LogWarning("[BodyPoseMatch_Leg] AlignUpperLeg: Target leg PCA 통계가 비정상입니다.");
}
else if (clothBoneMap == null || !clothBoneMap.TryGetValue(key, out value) || value == null || value.Count == 0)
{
Debug.LogWarning("[BodyPoseMatch_Leg] AlignUpperLeg: clothes UpperLeg 본을 찾지 못했습니다.");
}
else
{
this.AlignUpperLegCore(value, profilePcaCenterWorld, regionStats.center);
}
}
private void AlignUpperLegCore(IReadOnlyCollection<Transform> upperLegSet, Vector3 sourceLegCenterWorld, Vector3 targetLegCenterWorld)
{
if (upperLegSet == null || upperLegSet.Count == 0)
{
return;
}
Vector3 vector = targetLegCenterWorld - sourceLegCenterWorld;
vector.y = 0f;
foreach (Transform item in upperLegSet)
{
if (!(item == null))
{
item.position += vector;
}
}
}
public RegionStats ComputeLegRegionStats(Transform avatarTransform, IReadOnlyList<BakedBodyMesh> avatarBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> avatarBoneMap, bool isLeft)
{
HumanBodyBones[] targetHumanBones = ((!isLeft) ? new HumanBodyBones[2]
{
HumanBodyBones.RightUpperLeg,
HumanBodyBones.RightLowerLeg
} : new HumanBodyBones[2]
{
HumanBodyBones.LeftUpperLeg,
HumanBodyBones.LeftLowerLeg
});
List<Vector3> list = this.poseMatchCommonUtil.CollectHumanoidVerticesWorld(targetHumanBones, avatarBakedBodyMeshes, avatarBoneMap);
if (list == null || list.Count == 0)
{
Debug.LogWarning($"[BodyPoseMatch_Leg] ComputeLegRegionStats: leg vertices 0개. avatar={avatarTransform?.name}, isLeft={isLeft}");
return default(RegionStats);
}
RegionStats result = new PcaUtil().ComputeRegionStats(list);
Transform boneFromBoneMap = this.poseMatchCommonUtil.GetBoneFromBoneMap(avatarBoneMap, isLeft ? HumanBodyBones.LeftUpperLeg : HumanBodyBones.RightUpperLeg);
Transform boneFromBoneMap2 = this.poseMatchCommonUtil.GetBoneFromBoneMap(avatarBoneMap, isLeft ? HumanBodyBones.LeftLowerLeg : HumanBodyBones.RightLowerLeg);
if (boneFromBoneMap != null && boneFromBoneMap2 != null)
{
Vector3 normalized = (boneFromBoneMap2.position - boneFromBoneMap.position).normalized;
Vector3 vector = result.principalAxis.normalized;
if (Vector3.Dot(vector, normalized) < 0f)
{
vector = -vector;
}
result.principalAxis = vector;
}
return result;
}
public void ScalingBothLegsAndFoots(GameObject proxyObject, IReadOnlyList<BakedBodyMesh> proxyBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> proxyBoneMap, GameObject targetObject, IReadOnlyList<BakedBodyMesh> targetBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap, bool autoDetectAxis = true, int forceAxisIndex = 1)
{
this.ScalingLeg(proxyBoneMap, targetBoneMap, isLeft: true, autoDetectAxis, forceAxisIndex);
this.ScalingLeg(proxyBoneMap, targetBoneMap, isLeft: false, autoDetectAxis, forceAxisIndex);
if (proxyBakedBodyMeshes != null)
{
foreach (BakedBodyMesh proxyBakedBodyMesh in proxyBakedBodyMeshes)
{
proxyBakedBodyMesh?.ReBakeMesh();
}
}
this.ScalingFoot(proxyObject, proxyBakedBodyMeshes, proxyBoneMap, targetObject, targetBakedBodyMeshes, targetBoneMap, isLeft: true);
this.ScalingFoot(proxyObject, proxyBakedBodyMeshes, proxyBoneMap, targetObject, targetBakedBodyMeshes, targetBoneMap, isLeft: false);
}
public void ScalingBothLegsAndFoots(Transform targetTransform, IReadOnlyList<BakedBodyMesh> targetBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap, Transform clothTransform, Dictionary<HumanBodyBones, HashSet<Transform>> clothBoneMap, ProfileData profileData, Vector3 comprehensiveScale, bool autoDetectAxis = true, int forceAxisIndex = 1)
{
this.ScalingLeg(clothBoneMap, targetBoneMap, isLeft: true, autoDetectAxis, forceAxisIndex);
this.ScalingLeg(clothBoneMap, targetBoneMap, isLeft: false, autoDetectAxis, forceAxisIndex);
this.ScalingFoot(profileData, comprehensiveScale, clothBoneMap, targetTransform, targetBakedBodyMeshes, targetBoneMap, isLeft: true);
this.ScalingFoot(profileData, comprehensiveScale, clothBoneMap, targetTransform, targetBakedBodyMeshes, targetBoneMap, isLeft: false);
}
public void ScalingLeg(Dictionary<HumanBodyBones, HashSet<Transform>> proxyBoneMap, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap, bool isLeft, bool autoDetectAxis = true, int forceAxisIndex = 1)
{
HumanBodyBones humanBodyBones = (isLeft ? HumanBodyBones.LeftUpperLeg : HumanBodyBones.RightUpperLeg);
HumanBodyBones bone = (isLeft ? HumanBodyBones.LeftLowerLeg : HumanBodyBones.RightLowerLeg);
Transform boneFromBoneMap = this.poseMatchCommonUtil.GetBoneFromBoneMap(proxyBoneMap, humanBodyBones);
Transform boneFromBoneMap2 = this.poseMatchCommonUtil.GetBoneFromBoneMap(proxyBoneMap, bone);
Transform boneFromBoneMap3 = this.poseMatchCommonUtil.GetBoneFromBoneMap(targetBoneMap, humanBodyBones);
Transform boneFromBoneMap4 = this.poseMatchCommonUtil.GetBoneFromBoneMap(targetBoneMap, bone);
if (boneFromBoneMap == null || boneFromBoneMap2 == null || boneFromBoneMap3 == null || boneFromBoneMap4 == null)
{
Debug.LogWarning("[AvatarBodyMatchUtil] ScalingLeg: some leg bones are null");
return;
}
if (proxyBoneMap == null || !proxyBoneMap.TryGetValue(humanBodyBones, out var value) || value == null || value.Count == 0)
{
Debug.LogWarning("[AvatarBodyMatchUtil] ScalingLeg: proxy upperLeg bone set missing");
return;
}
this.poseMatchCommonUtil.BoneLengthAdjust(boneFromBoneMap, boneFromBoneMap2, boneFromBoneMap3, boneFromBoneMap4, value, autoDetectAxis, forceAxisIndex);
HumanBodyBones humanBodyBones2 = (isLeft ? HumanBodyBones.LeftFoot : HumanBodyBones.RightFoot);
Transform boneFromBoneMap5 = this.poseMatchCommonUtil.GetBoneFromBoneMap(proxyBoneMap, humanBodyBones2);
Transform boneFromBoneMap6 = this.poseMatchCommonUtil.GetBoneFromBoneMap(targetBoneMap, humanBodyBones2);
if (boneFromBoneMap5 == null || boneFromBoneMap6 == null)
{
Debug.LogWarning("[AvatarBodyMatchUtil] ScalingFoot: proxyFoot or targetFoot is null");
return;
}
float y = boneFromBoneMap5.position.y;
float num = boneFromBoneMap6.position.y - y;
if (!(Mathf.Abs(num) > 1E-06f))
{
return;
}
Vector3 vector = new Vector3(0f, num, 0f);
if (proxyBoneMap == null || !proxyBoneMap.TryGetValue(humanBodyBones2, out var value2) || value2 == null || value2.Count <= 0)
{
return;
}
foreach (Transform item in value2)
{
if (!(item == null))
{
item.position += vector;
}
}
}
private void ScalingFootCore(Transform proxyHip, Transform targetFoot, bool isLeft, HashSet<Transform> footBoneSet, float proxyToeF, float proxyHeelF, float proxySideMin, float proxySideMax, float proxySoleY, float targetToeF, float targetHeelF, float targetSideMin, float targetSideMax, float targetSoleY)
{
if (proxyHip == null || targetFoot == null)
{
Debug.LogWarning("[BodyPoseMatch_Leg] ScalingFootCore: proxyHip or targetFoot is null");
return;
}
if (footBoneSet == null || footBoneSet.Count == 0)
{
Debug.LogWarning("[BodyPoseMatch_Leg] ScalingFootCore: footBoneSet is null or empty");
return;
}
Dictionary<Transform, List<Transform>> dictionary = new Dictionary<Transform, List<Transform>>();
foreach (Transform item in footBoneSet)
{
if (!(item == null))
{
Transform parent = item.parent;
if (!dictionary.TryGetValue(parent, out var value))
{
value = new List<Transform>();
dictionary.Add(parent, value);
}
value.Add(item);
}
}
foreach (KeyValuePair<Transform, List<Transform>> item2 in dictionary)
{
Transform key = item2.Key;
List<Transform> value2 = item2.Value;
if (key == null || value2 == null || value2.Count == 0)
{
continue;
}
Transform transform = value2[0];
if (!(transform == null))
{
TempBoneMarker tempBoneMarker;
Transform transform2 = this.poseMatchCommonUtil.CreateTempMarker("scaleSupportBone", key, value2, transform.position, Quaternion.identity, transform.localScale, out tempBoneMarker);
if (!(transform2 == null))
{
this.ScaleAndAlignAlongAxis(proxyHip, proxyHip.forward, proxyHip.up, transform2, proxyToeF, proxyHeelF, targetFoot, targetToeF, targetHeelF);
this.ScaleAndAlignAlongAxis(proxyHip, proxyHip.right, proxyHip.up, transform2, isLeft ? proxySideMin : proxySideMax, isLeft ? proxySideMax : proxySideMin, targetFoot, isLeft ? targetSideMin : targetSideMax, isLeft ? targetSideMax : targetSideMin);
this.ScaleAndAlignAlongAxis(proxyHip, proxyHip.up, proxyHip.forward, transform2, 0f, proxySoleY, targetFoot, 0f, targetSoleY);
}
}
}
}
public void ScalingFoot(GameObject proxyObject, IReadOnlyList<BakedBodyMesh> proxyBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> proxyBoneMap, GameObject targetObject, IReadOnlyList<BakedBodyMesh> targetBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap, bool isLeft)
{
if (proxyObject == null || targetObject == null)
{
throw new AutoMorpherException("Proxy or Target Object is Missing", "[BodyPoseMatch_Leg] ScalingFoot\n - proxyObject or targetObject is null");
}
HumanBodyBones humanBodyBones = (isLeft ? HumanBodyBones.LeftFoot : HumanBodyBones.RightFoot);
Transform boneFromBoneMap = this.poseMatchCommonUtil.GetBoneFromBoneMap(proxyBoneMap, humanBodyBones);
Transform boneFromBoneMap2 = this.poseMatchCommonUtil.GetBoneFromBoneMap(targetBoneMap, humanBodyBones);
if (boneFromBoneMap == null || boneFromBoneMap2 == null)
{
Debug.LogWarning("[AvatarBodyMatchUtil] ScalingFoot: proxyFoot or targetFoot is null");
return;
}
if (!this.TryGetFootSpatialData(proxyObject.transform, proxyBakedBodyMeshes, proxyBoneMap, isLeft, out var _, out var footMinUp, out var heelF, out var toeF, out var sideMin, out var sideMax) || !this.TryGetFootSpatialData(targetObject.transform, targetBakedBodyMeshes, targetBoneMap, isLeft, out var _, out var footMinUp2, out var heelF2, out var toeF2, out var sideMin2, out var sideMax2))
{
Debug.LogWarning("[AvatarBodyMatchUtil] ScalingFoot: foot spatial data 계산 실패");
return;
}
Transform boneFromBoneMap3 = this.poseMatchCommonUtil.GetBoneFromBoneMap(proxyBoneMap, HumanBodyBones.Hips);
HashSet<Transform> value;
if (boneFromBoneMap3 == null)
{
Debug.LogWarning("[BodyPoseMatch_Leg] ScalingFoot: proxyHip is null");
}
else if (proxyBoneMap == null || !proxyBoneMap.TryGetValue(humanBodyBones, out value) || value == null || value.Count == 0)
{
Debug.LogWarning("[BodyPoseMatch_Leg] ScalingFoot: footBoneSet is missing");
}
else
{
this.ScalingFootCore(boneFromBoneMap3, boneFromBoneMap2, isLeft, value, toeF, heelF, sideMin, sideMax, footMinUp, toeF2, heelF2, sideMin2, sideMax2, footMinUp2);
}
}
public void ScalingFoot(ProfileData profileData, Vector3 comprehensiveScale, Dictionary<HumanBodyBones, HashSet<Transform>> clothBoneMap, Transform targetTransform, IReadOnlyList<BakedBodyMesh> targetBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap, bool isLeft)
{
if (targetTransform == null)
{
throw new AutoMorpherException("Target Transform is Missing", "[BodyPoseMatch_Leg] ScalingFoot\n - targetTransform is null");
}
HumanBodyBones humanBodyBones = (isLeft ? HumanBodyBones.LeftFoot : HumanBodyBones.RightFoot);
Transform boneFromBoneMap = this.poseMatchCommonUtil.GetBoneFromBoneMap(clothBoneMap, humanBodyBones);
Transform boneFromBoneMap2 = this.poseMatchCommonUtil.GetBoneFromBoneMap(targetBoneMap, humanBodyBones);
if (boneFromBoneMap == null || boneFromBoneMap2 == null)
{
Debug.LogWarning("[AvatarBodyMatchUtil] ScalingFoot: proxyFoot or targetFoot is null");
return;
}
if (!this.TryGetFootSpatialData(targetTransform.transform, targetBakedBodyMeshes, targetBoneMap, isLeft, out var _, out var footMinUp, out var heelF, out var toeF, out var sideMin, out var sideMax))
{
Debug.LogWarning("[AvatarBodyMatchUtil] ScalingFoot: foot spatial data 계산 실패");
return;
}
Transform boneFromBoneMap3 = this.poseMatchCommonUtil.GetBoneFromBoneMap(clothBoneMap, HumanBodyBones.Hips);
BoneSpatialData boneSpatialData = (isLeft ? profileData.LeftFootSpatialData : profileData.RightFootSpatialData);
if (boneSpatialData == null)
{
Debug.LogWarning("[AvatarBodyMatchUtil] AlignNeckCenterByPcaWithHipZ: Profile FootSpatialData Data is Not exist.");
return;
}
Transform boneFromBoneMap4 = this.poseMatchCommonUtil.GetBoneFromBoneMap(clothBoneMap, boneSpatialData.refBone);
if (boneFromBoneMap4 == null)
{
Debug.LogWarning("[BodyPoseMatch_Leg] ScalingFoot: clothRefBone is null");
return;
}
BodyPoseMatch_CommonUtil bodyPoseMatch_CommonUtil = new BodyPoseMatch_CommonUtil();
float proxyToeF = Vector3.Distance(boneFromBoneMap4.position, bodyPoseMatch_CommonUtil.GetProfileVolumeMaxWorld(clothBoneMap, boneSpatialData, 0, comprehensiveScale));
float proxyHeelF = 0f - Vector3.Distance(boneFromBoneMap4.position, bodyPoseMatch_CommonUtil.GetProfileVolumeMinWorld(clothBoneMap, boneSpatialData, 0, comprehensiveScale));
float proxySideMax = Vector3.Distance(boneFromBoneMap4.position, bodyPoseMatch_CommonUtil.GetProfileVolumeMaxWorld(clothBoneMap, boneSpatialData, 1, comprehensiveScale));
float proxySideMin = 0f - Vector3.Distance(boneFromBoneMap4.position, bodyPoseMatch_CommonUtil.GetProfileVolumeMinWorld(clothBoneMap, boneSpatialData, 1, comprehensiveScale));
float proxySoleY = 0f - Vector3.Distance(boneFromBoneMap4.position, bodyPoseMatch_CommonUtil.GetProfileVolumeMinWorld(clothBoneMap, boneSpatialData, 2, comprehensiveScale));
if (clothBoneMap == null || !clothBoneMap.TryGetValue(humanBodyBones, out var value) || value == null || value.Count == 0)
{
Debug.LogWarning("[BodyPoseMatch_Leg] ScalingFoot: cloth footBoneSet is missing");
}
else
{
this.ScalingFootCore(boneFromBoneMap3, boneFromBoneMap2, isLeft, value, proxyToeF, proxyHeelF, proxySideMin, proxySideMax, proxySoleY, toeF, heelF, sideMin, sideMax, footMinUp);
}
}
private void ScaleAndAlignAlongAxis(Transform baseTransform, Vector3 targetWorldAxis, Vector3 targetWorldUpAxis, Transform proxyFoot, float proxyMaxF, float proxyMinF, Transform targetFoot, float targetMaxF, float targetMinF)
{
float num = proxyMaxF - proxyMinF;
float num2 = targetMaxF - targetMinF;
if (Mathf.Abs(num) < 0.0001f || Mathf.Abs(num2) < 0.0001f)
{
Debug.LogWarning("[AdjustFootForwardScale] foot span too small.");
return;
}
float num3 = num2 / num;
if (!float.IsFinite(num3) || num3 <= 0f)
{
Debug.LogWarning($"[ScaleAndAlignAlongAxis] invalid scaleF: {num3}");
return;
}
Vector3 position = proxyFoot.position + targetWorldAxis * proxyMinF;
Vector3 position2 = targetFoot.position + targetWorldAxis * targetMinF;
GameObject gameObject = new GameObject("proxyAnchor");
gameObject.transform.SetParent(proxyFoot);
gameObject.transform.position = position;
GameObject gameObject2 = new GameObject("targetAnchor");
gameObject2.transform.SetParent(targetFoot);
gameObject2.transform.position = position2;
Transform parent = proxyFoot.parent;
Vector3 position3 = proxyFoot.position;
Transform transform = new GameObject("ScaleParnet").transform;
transform.SetParent(parent);
transform.position = position3;
transform.rotation = Quaternion.LookRotation(targetWorldAxis, targetWorldUpAxis);
proxyFoot.SetParent(transform, worldPositionStays: true);
proxyFoot.localPosition = Vector3.zero;
Vector3 localScale = transform.localScale;
localScale.z *= num3;
transform.localScale = localScale;
proxyFoot.SetParent(parent, worldPositionStays: true);
proxyFoot.position = position3;
float num4 = Vector3.Dot(gameObject2.transform.position - gameObject.transform.position, targetWorldAxis);
Vector3 vector = targetWorldAxis * num4;
proxyFoot.position += vector;
Object.DestroyImmediate(transform.gameObject);
Object.DestroyImmediate(gameObject);
Object.DestroyImmediate(gameObject2);
}
private bool TryGetFootSpatialData(Transform avatarTransform, IReadOnlyList<BakedBodyMesh> avatarBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> avatarBoneMap, bool isLeft, out float footMaxUp, out float footMinUp, out float heelF, out float toeF, out float sideMin, out float sideMax, float weightThreshold = 0.15f, int sampleStep = 1)
{
footMaxUp = float.NegativeInfinity;
footMinUp = float.PositiveInfinity;
heelF = float.PositiveInfinity;
toeF = float.NegativeInfinity;
sideMin = float.PositiveInfinity;
sideMax = float.NegativeInfinity;
if (avatarTransform == null || avatarBakedBodyMeshes == null || avatarBoneMap == null || avatarBoneMap.Count == 0)
{
return false;
}
HumanBodyBones key = (isLeft ? HumanBodyBones.LeftFoot : HumanBodyBones.RightFoot);
if (!avatarBoneMap.TryGetValue(key, out var value) || value == null || value.Count == 0)
{
Debug.LogWarning("[BodyPoseMatch_Leg] TryGetFootSpatialData\n - foot bone set is missing");
return false;
}
Vector3 up = Vector3.up;
Vector3 forward = Vector3.forward;
Vector3 right = Vector3.right;
HashSet<Transform> hashSet = new HashSet<Transform>();
Transform transform = null;
foreach (Transform item in value)
{
if (item == null)
{
continue;
}
if (transform == null)
{
transform = item;
}
Stack<Transform> stack = new Stack<Transform>();
stack.Push(item);
while (stack.Count > 0)
{
Transform transform2 = stack.Pop();
if (!(transform2 == null) && hashSet.Add(transform2))
{
for (int i = 0; i < transform2.childCount; i++)
{
stack.Push(transform2.GetChild(i));
}
}
}
}
if (transform == null || hashSet.Count == 0)
{
return false;
}
List<Vector3> list = this.poseMatchCommonUtil.CollectWeightedVerticesWorld(avatarBakedBodyMeshes, hashSet, weightThreshold, sampleStep);
if (list == null || list.Count == 0)
{
return false;
}
for (int j = 0; j < list.Count; j++)
{
Vector3 lhs = list[j] - transform.position;
float num = Vector3.Dot(lhs, up);
if (num < footMinUp)
{
footMinUp = num;
}
if (num > footMaxUp)
{
footMaxUp = num;
}
float num2 = Vector3.Dot(lhs, forward);
if (num2 < heelF)
{
heelF = num2;
}
if (num2 > toeF)
{
toeF = num2;
}
float num3 = Vector3.Dot(lhs, right);
if (num3 < sideMin)
{
sideMin = num3;
}
if (num3 > sideMax)
{
sideMax = num3;
}
}
return true;
}
public void DrawLegPcaDebug(GameObject avatarObject, IReadOnlyList<BakedBodyMesh> avatarBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> avatarBoneMap, bool isLeft, Color centerColor, Color axisColor, float axisScale = 1f, float duration = 1f)
{
if (!(avatarObject == null))
{
RegionStats regionStats = this.ComputeLegRegionStats(avatarObject.transform, avatarBakedBodyMeshes, avatarBoneMap, isLeft);
if (regionStats.length < 0.0001f)
{
Debug.LogWarning($"[AvatarBodyMatchUtil] DrawLegPcaDebug: PCA length too small (avatar={avatarObject.name}, isLeft={isLeft})");
return;
}
Vector3 center = regionStats.center;
Vector3 normalized = regionStats.principalAxis.normalized;
float num = 0.03f * axisScale;
Debug.DrawLine(center + Vector3.up * num, center - Vector3.up * num, centerColor, duration);
Debug.DrawLine(center + Vector3.right * num, center - Vector3.right * num, centerColor, duration);
Debug.DrawLine(center + Vector3.forward * num, center - Vector3.forward * num, centerColor, duration);
float num2 = regionStats.length * 0.5f * axisScale;
Vector3 start = center - normalized * num2;
Vector3 end = center + normalized * num2;
Debug.DrawLine(start, end, axisColor, duration);
Debug.Log($"[DrawLegPcaDebug] avatar={avatarObject.name}, isLeft={isLeft}, " + $"center={center}, axis={normalized}, len={regionStats.length}, avgRadius={regionStats.avgRadius}");
}
}
public void DrawFootSpatialDebug(GameObject avatarObject, IReadOnlyList<BakedBodyMesh> avatarBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> avatarBoneMap, bool isLeft, Color centerColor, Color axisColor, Color boxColor, float axisScale = 0.1f, float duration = 1f, float weightThreshold = 0.15f, int sampleStep = 1)
{
if (avatarObject == null)
{
return;
}
if (!this.TryGetFootSpatialData(avatarObject.transform, avatarBakedBodyMeshes, avatarBoneMap, isLeft, out var footMaxUp, out var footMinUp, out var heelF, out var toeF, out var sideMin, out var sideMax, weightThreshold, sampleStep))
{
Debug.LogWarning("[BodyPoseMatch_Leg] DrawFootSpatialDebug" + $"\n - Failed to compute Foot Spatial Data (avatar={avatarObject.name}, isLeft={isLeft})");
}
else
{
if (avatarBoneMap == null || avatarBoneMap.Count == 0)
{
return;
}
HumanBodyBones humanBodyBones = (isLeft ? HumanBodyBones.LeftFoot : HumanBodyBones.RightFoot);
if (!avatarBoneMap.TryGetValue(humanBodyBones, out var value) || value == null || value.Count == 0)
{
return;
}
Transform transform = null;
foreach (Transform item in value)
{
if (item != null)
{
transform = item;
break;
}
}
if (transform == null)
{
return;
}
Vector3 position = transform.position;
Transform boneFromBoneMap = this.poseMatchCommonUtil.GetBoneFromBoneMap(avatarBoneMap, HumanBodyBones.Hips);
Vector3 vector = ((boneFromBoneMap != null) ? boneFromBoneMap.forward : avatarObject.transform.forward);
vector.y = 0f;
if (vector.sqrMagnitude < 1E-06f)
{
vector = Vector3.forward;
}
vector.Normalize();
Vector3 vector2 = Vector3.Cross(Vector3.up, vector);
if (vector2.sqrMagnitude < 1E-06f)
{
vector2 = Vector3.right;
}
vector2.Normalize();
Vector3 vector3 = ((boneFromBoneMap != null) ? boneFromBoneMap.up : avatarObject.transform.up);
if (vector3.sqrMagnitude < 1E-06f)
{
vector3 = Vector3.up;
}
vector3.Normalize();
float num = Mathf.Max(0.0001f, axisScale * 0.5f);
DrawCross(position, vector3, vector2, centerColor, num, duration);
DrawCross(position, vector3, vector, centerColor, num, duration);
float len = Mathf.Max(0.0001f, axisScale * 2f);
DrawAxisLine(position, vector3, len, axisColor, duration);
DrawAxisLine(position, vector, len, axisColor, duration);
DrawAxisLine(position, vector2, len, axisColor, duration);
Vector3[] array = new Vector3[8];
int num2 = 0;
for (int i = 0; i < 2; i++)
{
float num3 = ((i == 0) ? footMinUp : footMaxUp);
for (int j = 0; j < 2; j++)
{
float num4 = ((j == 0) ? heelF : toeF);
for (int k = 0; k < 2; k++)
{
float num5 = ((k == 0) ? sideMin : sideMax);
array[num2++] = position + vector3 * num3 + vector * num4 + vector2 * num5;
}
}
}
DrawBoxEdges(array, boxColor, duration);
float size = Mathf.Max(5E-05f, num * 0.6f);
for (int l = 0; l < array.Length; l++)
{
DrawCross(array[l], vector, vector2, boxColor, size, duration);
}
Debug.Log($"[DrawFootSpatialDebug] avatar={avatarObject.name}, isLeft={isLeft}\n" + $" - footBone={humanBodyBones}, footRoot={transform.name}\n" + $" - up(min,max)=({footMinUp:F4},{footMaxUp:F4})\n" + $" - forward(heel,toe)=({heelF:F4},{toeF:F4})\n" + $" - side(min,max)=({sideMin:F4},{sideMax:F4})\n" + $" - forwardDir={vector}, rightDir={vector2}, upDir={vector3}");
}
static void DrawAxisLine(Vector3 start, Vector3 dir, float num6, Color color, float d)
{
if (!(dir.sqrMagnitude < 1E-10f))
{
dir.Normalize();
Debug.DrawLine(start, start + dir * num6, color, d);
}
}
static void DrawBoxEdges(Vector3[] c, Color color, float d)
{
DrawSegment(c[0], c[1], color, d);
DrawSegment(c[1], c[3], color, d);
DrawSegment(c[3], c[2], color, d);
DrawSegment(c[2], c[0], color, d);
DrawSegment(c[4], c[5], color, d);
DrawSegment(c[5], c[7], color, d);
DrawSegment(c[7], c[6], color, d);
DrawSegment(c[6], c[4], color, d);
DrawSegment(c[0], c[4], color, d);
DrawSegment(c[1], c[5], color, d);
DrawSegment(c[2], c[6], color, d);
DrawSegment(c[3], c[7], color, d);
}
static void DrawCross(Vector3 pos, Vector3 axisA, Vector3 axisB, Color color, float num6, float d)
{
if (axisA.sqrMagnitude < 1E-10f)
{
axisA = Vector3.up;
}
if (axisB.sqrMagnitude < 1E-10f)
{
axisB = Vector3.right;
}
axisA.Normalize();
axisB.Normalize();
Debug.DrawLine(pos - axisA * num6, pos + axisA * num6, color, d);
Debug.DrawLine(pos - axisB * num6, pos + axisB * num6, color, d);
}
static void DrawSegment(Vector3 p0, Vector3 p1, Color color, float d)
{
Debug.DrawLine(p0, p1, color, d);
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d5c24488eded1b844bc1790158497120

View File

@@ -0,0 +1,143 @@
// 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.BodyPoseMatch_Torso
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class BodyPoseMatch_Torso
{
private readonly BodyPoseMatch_CommonUtil poseMatchCommonUtil;
public BodyPoseMatch_Torso()
{
this.poseMatchCommonUtil = new BodyPoseMatch_CommonUtil();
}
public void AlignTorsoByNeck(IReadOnlyCollection<Transform> sourceHipSet, Vector3 sourceNeckCenterWorld, Vector3 targetNeckCenterWorld)
{
if (sourceHipSet == null || sourceHipSet.Count == 0)
{
throw new AutoMorpherException("Source Hip Set is Missing", "[BodyPoseMatch_Torso] AlignTorsoByNeck\n - sourceHipSet is null or empty");
}
Transform transform = sourceHipSet.FirstOrDefault((Transform t) => t != null);
if (transform == null)
{
throw new AutoMorpherException("Source Hip Transform is Missing", "[BodyPoseMatch_Torso] AlignTorsoByNeck\n - sourceHipSet has no valid Transform");
}
Vector3 lhs = targetNeckCenterWorld - sourceNeckCenterWorld;
Vector3 forward = transform.forward;
float num = Vector3.Dot(lhs, forward);
Vector3 vector = forward * num;
foreach (Transform item in sourceHipSet)
{
if (!(item == null))
{
item.position += vector;
}
}
}
public void AlignTorsoByNeck(GameObject proxyObject, IReadOnlyList<BakedBodyMesh> proxyBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> proxyBoneMap, GameObject targetObject, IReadOnlyList<BakedBodyMesh> targetBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap)
{
if (proxyObject == null || targetObject == null)
{
throw new AutoMorpherException("Proxy/Target Object is Missing", "[BodyPoseMatch_Torso] AlignTorsoByNeck\n - proxyObject or targetObject is null");
}
RegionStats regionStats = this.ComputeNeckRegionStats(proxyObject.transform, proxyBakedBodyMeshes, proxyBoneMap);
RegionStats regionStats2 = this.ComputeNeckRegionStats(targetObject.transform, targetBakedBodyMeshes, targetBoneMap);
if (regionStats.length < 0.0001f || regionStats2.length < 0.0001f)
{
Debug.LogWarning("[BodyPoseMatch_Torso] AlignTorsoByNeck: Neck PCA 통계가 비정상입니다.");
return;
}
if (proxyBoneMap == null || !proxyBoneMap.TryGetValue(HumanBodyBones.Hips, out var value) || value == null || value.Count == 0)
{
throw new AutoMorpherException("Proxy Hip Set is Missing", "[BodyPoseMatch_Torso] AlignTorsoByNeck\n - proxyBoneMap has no Hips bone set");
}
this.AlignTorsoByNeck(value, regionStats.center, regionStats2.center);
}
public void AlignTorsoByNeck(Transform targetTransform, IReadOnlyList<BakedBodyMesh> targetBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> targetBoneMap, Dictionary<HumanBodyBones, HashSet<Transform>> clothBoneMap, Transform clothesTransform, ProfileData profileData, Vector3 comprehensiveScale)
{
if (targetTransform == null)
{
throw new AutoMorpherException("Target Transform is Missing", "[BodyPoseMatch_Torso] AlignTorsoByNeck\n - targetTransform is null");
}
if (profileData == null || profileData.NeckSpatialData == null)
{
throw new AutoMorpherException("Profile Neck Data is Missing", "[BodyPoseMatch_Torso] AlignTorsoByNeck\n - profileData or profileData.NeckSpatialData is null");
}
RegionStats regionStats = this.ComputeNeckRegionStats(targetTransform, targetBakedBodyMeshes, targetBoneMap);
if (regionStats.length < 0.0001f)
{
Debug.LogWarning("[BodyPoseMatch_Torso] AlignTorsoByNeck: Neck PCA 통계가 비정상입니다.");
return;
}
if (clothBoneMap == null || !clothBoneMap.TryGetValue(HumanBodyBones.Hips, out var value) || value == null || value.Count == 0)
{
throw new AutoMorpherException("Cloth Hip Set is Missing", "[BodyPoseMatch_Torso] AlignTorsoByNeck\n - clothBoneMap has no Hips bone set");
}
Vector3 profilePcaCenterWorld = this.poseMatchCommonUtil.GetProfilePcaCenterWorld(clothBoneMap, profileData.NeckSpatialData, comprehensiveScale);
this.AlignTorsoByNeck(value, profilePcaCenterWorld, regionStats.center);
}
public RegionStats ComputeNeckRegionStats(Transform avatarTransform, IReadOnlyList<BakedBodyMesh> avatarBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> avatarBoneMap)
{
HumanBodyBones[] targetHumanBones = new HumanBodyBones[1] { HumanBodyBones.Neck };
List<Vector3> list = this.poseMatchCommonUtil.CollectHumanoidVerticesWorld(targetHumanBones, avatarBakedBodyMeshes, avatarBoneMap);
if (list == null || list.Count == 0)
{
Debug.LogWarning("[AvatarBodyMatchUtil] ComputeNeckRegionStats: neck vertices 0개. avatar=" + avatarTransform?.name);
return default(RegionStats);
}
RegionStats result = new PcaUtil().ComputeRegionStats(list);
Vector3 vector = avatarTransform.up;
Transform boneFromBoneMap = this.poseMatchCommonUtil.GetBoneFromBoneMap(avatarBoneMap, HumanBodyBones.Head);
Transform boneFromBoneMap2 = this.poseMatchCommonUtil.GetBoneFromBoneMap(avatarBoneMap, HumanBodyBones.UpperChest);
Transform boneFromBoneMap3 = this.poseMatchCommonUtil.GetBoneFromBoneMap(avatarBoneMap, HumanBodyBones.Chest);
Transform boneFromBoneMap4 = this.poseMatchCommonUtil.GetBoneFromBoneMap(avatarBoneMap, HumanBodyBones.Hips);
Transform transform = ((boneFromBoneMap2 != null) ? boneFromBoneMap2 : boneFromBoneMap3);
if (boneFromBoneMap != null && transform != null)
{
vector = boneFromBoneMap.position - transform.position;
}
else if (boneFromBoneMap != null && boneFromBoneMap4 != null)
{
vector = boneFromBoneMap.position - boneFromBoneMap4.position;
}
if (vector.sqrMagnitude > 1E-08f)
{
vector.Normalize();
}
if (Vector3.Dot(vector, avatarTransform.transform.up) < 0f)
{
vector = -vector;
}
result.principalAxis = vector;
return result;
}
public void DrawTorsoPcaDebug(GameObject avatarObject, IReadOnlyList<BakedBodyMesh> avatarBakedBodyMeshes, Dictionary<HumanBodyBones, HashSet<Transform>> avatarBoneMap, Color centerColor, Color axisColor, float axisScale = 1f, float duration = 0.1f)
{
if (!(avatarObject == null))
{
RegionStats regionStats = this.ComputeNeckRegionStats(avatarObject.transform, avatarBakedBodyMeshes, avatarBoneMap);
if (regionStats.length < 0.0001f)
{
Debug.LogWarning($"[AvatarBodyMatchUtil] DrawNeckPcaDebug: neck.length가 너무 작음. avatar={avatarObject.name}, length={regionStats.length}");
return;
}
Vector3 center = regionStats.center;
Vector3 normalized = regionStats.principalAxis.normalized;
float num = 0.02f * axisScale;
Debug.DrawLine(center + Vector3.up * num, center - Vector3.up * num, centerColor, duration);
Debug.DrawLine(center + Vector3.right * num, center - Vector3.right * num, centerColor, duration);
float num2 = regionStats.length * 0.5f * axisScale;
Vector3 end = center + normalized * num2;
Debug.DrawLine(center, end, axisColor, duration);
Debug.Log($"[AvatarBodyMatchUtil] DrawNeckPcaDebug: avatar={avatarObject.name}, center={center}, axis={normalized}, halfLen={num2}");
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 13807354cce38d84eb41a5a8d38d99ae

View File

@@ -0,0 +1,250 @@
// 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.BodyPoseToClothApplier
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class BodyPoseToClothApplier
{
private class BoneMapping
{
public Transform proxyBone;
public Transform clothBone;
public int depth;
public HumanBodyBones? humanBone;
}
public void ApplyBodyPoseToClothes(Transform bodyProxyRoot, Transform clothesRoot, Dictionary<Transform, BoneMatchUtil.BoneRootLocalData> clothToBodyMatched, Dictionary<Transform, Transform> sourceToProxy, bool copyPosition = true, bool copyRotation = false, bool copyScale = true)
{
if (bodyProxyRoot == null)
{
throw new AutoMorpherException("Body Proxy Root is Missing", "[BodyToClothPoseApplier] ApplyDeformedProxyPoseToCloth\n - bodyProxyRoot is null");
}
if (clothesRoot == null)
{
throw new AutoMorpherException("Clothes Root is Missing", "[BodyToClothPoseApplier] ApplyDeformedProxyPoseToCloth\n - clothesRoot is null");
}
if (clothToBodyMatched == null || clothToBodyMatched.Count == 0)
{
throw new AutoMorpherException("Cloth To Body Matched Map is Missing", "[BodyToClothPoseApplier] ApplyDeformedProxyPoseToCloth\n - clothToBodyMatched is null or empty");
}
if (sourceToProxy == null)
{
throw new AutoMorpherException("Source To Proxy Map is Missing", "[BodyToClothPoseApplier] ApplyDeformedProxyPoseToCloth\n - sourceToProxy is null");
}
clothesRoot.localScale = bodyProxyRoot.localScale;
Animator component = bodyProxyRoot.GetComponent<Animator>();
if (component == null)
{
throw new AutoMorpherException("Body Proxy Animator is Missing", "[BodyToClothPoseApplier] ApplyDeformedProxyPoseToCloth\n - bodyProxyRoot has no Animator");
}
Transform transform = component.transform;
Dictionary<Transform, int> dictionary = this.BuildDepthMap(transform);
Dictionary<Transform, Transform> dictionary2 = new Dictionary<Transform, Transform>();
List<BoneMapping> list = new List<BoneMapping>();
HashSet<Transform> hashSet = new HashSet<Transform>();
foreach (KeyValuePair<Transform, BoneMatchUtil.BoneRootLocalData> item in clothToBodyMatched)
{
Transform key = item.Key;
BoneMatchUtil.BoneRootLocalData value = item.Value;
if (key == null || value == null)
{
continue;
}
Transform t = value.t;
if (t == null || !sourceToProxy.TryGetValue(t, out var value2) || value2 == null)
{
continue;
}
HumanBodyBones hBone = value.hBone;
if (hashSet.Add(key))
{
int depth = 999;
if (dictionary != null && dictionary.TryGetValue(value2, out var value3))
{
depth = value3;
}
list.Add(new BoneMapping
{
proxyBone = value2,
clothBone = key,
depth = depth,
humanBone = ((hBone != HumanBodyBones.LastBone) ? new HumanBodyBones?(hBone) : ((HumanBodyBones?)null))
});
}
if (!dictionary2.ContainsKey(value2))
{
dictionary2.Add(value2, key);
}
}
this.MirrorBoneMarkers(transform, dictionary2, dictionary, list);
foreach (BoneMapping item2 in (from m in list
where m != null && m.proxyBone != null && m.clothBone != null
orderby m.depth
select m).ToList())
{
if (!(item2.proxyBone == null) && !(item2.clothBone == null))
{
if (copyPosition)
{
item2.clothBone.position = item2.proxyBone.position;
}
if (copyRotation)
{
item2.clothBone.rotation = item2.proxyBone.rotation;
}
if (copyScale)
{
item2.clothBone.localScale = item2.proxyBone.localScale;
}
}
}
}
private Dictionary<Transform, int> BuildDepthMap(Transform root)
{
Dictionary<Transform, int> dictionary = new Dictionary<Transform, int>();
if (root == null)
{
return dictionary;
}
Transform[] componentsInChildren = root.GetComponentsInChildren<Transform>(includeInactive: true);
foreach (Transform transform in componentsInChildren)
{
if (!(transform == null))
{
dictionary[transform] = this.GetDepthFromRoot(transform, root);
}
}
return dictionary;
}
private int GetDepthFromRoot(Transform t, Transform root)
{
int num = 0;
Transform transform = t;
while (transform != null && transform != root)
{
num++;
transform = transform.parent;
}
return num;
}
private void MirrorBoneMarkers(Transform proxyArmature, Dictionary<Transform, Transform> proxyToCloth, Dictionary<Transform, int> proxyDepthMap, List<BoneMapping> mappings)
{
if (proxyArmature == null || proxyToCloth == null || mappings == null)
{
return;
}
TempBoneMarker[] componentsInChildren = proxyArmature.GetComponentsInChildren<TempBoneMarker>(includeInactive: true);
if (componentsInChildren == null || componentsInChildren.Length == 0)
{
return;
}
HashSet<Transform> hashSet = new HashSet<Transform>();
for (int i = 0; i < mappings.Count; i++)
{
BoneMapping boneMapping = mappings[i];
if (boneMapping != null && boneMapping.proxyBone != null)
{
hashSet.Add(boneMapping.proxyBone);
}
}
foreach (TempBoneMarker item in (from bm in componentsInChildren
where bm != null && bm.transform != null
orderby (proxyDepthMap != null && proxyDepthMap.TryGetValue(bm.transform, out var value3)) ? value3 : int.MaxValue
select bm).ToList())
{
Transform transform = item.transform;
if (transform == null)
{
continue;
}
Transform originalParent = item.originalParent;
if (originalParent == null || !proxyToCloth.TryGetValue(originalParent, out var value) || value == null)
{
continue;
}
List<Transform> list = this.CollectDirectChilds(value);
Transform transform2 = this.FindMarkerInChild(value);
TempBoneMarker tempBoneMarker = null;
if (transform2 == null)
{
transform2 = new GameObject(transform.name).transform;
transform2.SetParent(value, worldPositionStays: true);
tempBoneMarker = transform2.gameObject.AddComponent<TempBoneMarker>();
}
else
{
tempBoneMarker = transform2.GetComponent<TempBoneMarker>();
}
transform2.position = transform.position;
transform2.rotation = transform.rotation;
transform2.localScale = transform.localScale;
tempBoneMarker.originalParent = value;
tempBoneMarker.additionalInfo = item.additionalInfo;
tempBoneMarker.wrappedChildNames = item.wrappedChildNames;
for (int num = 0; num < list.Count; num++)
{
Transform transform3 = list[num];
if (!(transform3 == null) && !(transform3 == transform2))
{
transform3.SetParent(transform2, worldPositionStays: true);
}
}
if (!proxyToCloth.ContainsKey(transform))
{
proxyToCloth.Add(transform, transform2);
}
if (hashSet.Add(transform))
{
int depth = 999;
if (proxyDepthMap != null && proxyDepthMap.TryGetValue(transform, out var value2))
{
depth = value2;
}
mappings.Add(new BoneMapping
{
proxyBone = transform,
clothBone = transform2,
depth = depth,
humanBone = null
});
}
}
}
private Transform FindMarkerInChild(Transform parent)
{
if (parent == null)
{
return null;
}
for (int i = 0; i < parent.childCount; i++)
{
Transform child = parent.GetChild(i);
if (!(child == null) && child.GetComponent<TempBoneMarker>() != null)
{
return child;
}
}
return null;
}
private List<Transform> CollectDirectChilds(Transform parentTransform)
{
int childCount = parentTransform.childCount;
List<Transform> list = new List<Transform>(childCount);
for (int i = 0; i < childCount; i++)
{
list.Add(parentTransform.GetChild(i));
}
return list;
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f39701ad78a777b48a7b931538b63608

View File

@@ -0,0 +1,168 @@
// 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.BoneAlignmentUtil
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class BoneAlignmentUtil
{
public void AlignClothBonesToAvatar(ClothInstance cloth, Animator targetAvatarAnimator)
{
if (cloth == null || targetAvatarAnimator == null)
{
Debug.LogWarning("[BoneAlignmentUtil] cloth 또는 targetAvatarAnimator 가 null.");
return;
}
foreach (KeyValuePair<HumanBodyBones, HashSet<Transform>> humanoidMatchedBone in cloth.humanoidMatchedBones)
{
HumanBodyBones key = humanoidMatchedBone.Key;
foreach (Transform item in humanoidMatchedBone.Value)
{
if (!(item == null))
{
Transform boneTransform = targetAvatarAnimator.GetBoneTransform(key);
if (!(boneTransform == null))
{
item.position = boneTransform.position;
item.localScale = Vector3.one;
item.name = boneTransform.name;
}
}
}
}
}
public void ReparentAccessoryBonesToAvatar(EdenAutoMorpherConfig config)
{
if (config.clothBoneTypeMap == null || config.targetAvatarObject == null)
{
return;
}
Animator component = config.targetAvatarObject.GetComponent<Animator>();
if (component == null || !component.isHuman)
{
return;
}
Dictionary<Transform, Transform> dictionary = new Dictionary<Transform, Transform>();
if (config.clothesHumanoidMatchedBones != null)
{
foreach (KeyValuePair<HumanBodyBones, HashSet<Transform>> clothesHumanoidMatchedBone in config.clothesHumanoidMatchedBones)
{
HumanBodyBones key = clothesHumanoidMatchedBone.Key;
foreach (Transform item2 in clothesHumanoidMatchedBone.Value)
{
Transform boneTransform = component.GetBoneTransform(key);
if (item2 != null && boneTransform != null)
{
dictionary[item2] = boneTransform;
}
}
}
}
foreach (KeyValuePair<Transform, ClothBoneType> item3 in config.clothBoneTypeMap)
{
if (item3.Value != ClothBoneType.Accessory)
{
continue;
}
Transform key2 = item3.Key;
if (key2 == null || !key2.IsChildOf(config.targetClothesObject.transform))
{
continue;
}
Transform parent = key2.parent;
Transform transform = null;
while (parent != null)
{
if (config.clothBoneTypeMap.TryGetValue(parent, out var value) && value == ClothBoneType.Body)
{
transform = parent;
break;
}
parent = parent.parent;
}
if (!(transform == null) && dictionary.TryGetValue(transform, out var value2))
{
key2.SetParent(value2, worldPositionStays: true);
}
}
foreach (KeyValuePair<Transform, Transform> item4 in dictionary)
{
Transform key3 = item4.Key;
Transform value3 = item4.Value;
if (key3 == null || value3 == null)
{
continue;
}
List<Transform> list = new List<Transform>();
foreach (Transform item5 in key3)
{
list.Add(item5);
}
foreach (Transform item6 in list)
{
if (!(item6 == null) && !config.clothBoneTypeMap.ContainsKey(item6))
{
item6.SetParent(value3, worldPositionStays: true);
}
}
}
}
public void CleanupTempBones(Transform root)
{
if (root == null)
{
return;
}
TempBoneMarker[] componentsInChildren = root.GetComponentsInChildren<TempBoneMarker>(includeInactive: true);
if (componentsInChildren == null || componentsInChildren.Length == 0)
{
return;
}
TempBoneMarker[] array = (from m in componentsInChildren
where m != null
orderby GetDepth(m.transform) descending
select m).ToArray();
foreach (TempBoneMarker tempBoneMarker in array)
{
if (tempBoneMarker == null)
{
continue;
}
Transform transform = tempBoneMarker.transform;
Transform transform2 = tempBoneMarker.originalParent;
if (transform2 == null)
{
transform2 = transform.parent;
}
if (transform2 != null)
{
while (transform.childCount > 0)
{
transform.GetChild(0).SetParent(transform2, worldPositionStays: true);
}
}
if (!Application.isPlaying)
{
Object.DestroyImmediate(transform.gameObject);
}
else
{
Object.Destroy(transform.gameObject);
}
}
static int GetDepth(Transform t)
{
int num2 = 0;
while (t != null)
{
num2++;
t = t.parent;
}
return num2;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d079bedd1d590d743a87a7526aac81d0

View File

@@ -0,0 +1,195 @@
// 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.BoneCorrespondenceUtil
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
public class BoneCorrespondenceUtil
{
private char[] nameDelims = new char[8] { ' ', '-', '_', ':', '.', '|', '\\', '/' };
public float ComputeDistanceScore(float d, float near, float mid, float far)
{
if (d < near)
{
return 120f;
}
if (d < mid)
{
return 90f;
}
if (d < far)
{
return 50f;
}
return 0f;
}
public float ComputeRotationScore(float ang, float RotTolDeg)
{
return Mathf.Clamp01(1f - ang / RotTolDeg);
}
public float ComputeNameScore(string bodyName, string bodyPath, string clothesName, string clothesPath)
{
string text = this.StripDigits(this.NormalizeName(bodyName));
string text2 = this.StripDigits(this.NormalizeName(clothesName));
string text3 = this.StripDigits(this.NormalizePath(bodyPath));
string text4 = this.StripDigits(this.NormalizePath(clothesPath));
if (!string.IsNullOrEmpty(text3) && text3 == text4)
{
return 80f;
}
if (!string.IsNullOrEmpty(text) && text == text2)
{
return 70f;
}
if (!string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(text2) && (text.Contains(text2) || text2.Contains(text)))
{
return 40f;
}
return this.SubsequenceCoverage(bodyName, clothesName) * 10f;
}
private float SubsequenceCoverage(string bodyRaw, string clothesRaw)
{
string text = this.StripDigits(this.NormalizeName(bodyRaw));
string text2 = this.StripDigits(this.NormalizeName(clothesRaw));
if (string.IsNullOrEmpty(text) || string.IsNullOrEmpty(text2))
{
return 0f;
}
return (float)this.SubNameMatchBest(text, text2) / (float)text.Length;
}
private int SubNameMatchBest(string a, string b, int minMatchCount = 3)
{
if (string.IsNullOrEmpty(a) || string.IsNullOrEmpty(b))
{
return 0;
}
if (a.Length < minMatchCount || b.Length < minMatchCount)
{
return 0;
}
int num = 0;
for (int i = 0; i <= a.Length - minMatchCount; i++)
{
int num2 = this.SubNameMatch(a, i, b, minMatchCount);
if (num2 > num)
{
num = num2;
}
}
return num;
}
private int SubNameMatch(string a, int startA, string b, int minMatchCount = 3)
{
int length = a.Length;
int length2 = b.Length;
int num = 0;
int num2 = 0;
int num3 = 0;
int num4 = 0;
for (int i = startA; i < length; i++)
{
for (int j = num3; j < length2; j++)
{
num3 = j + 1;
if (a[i] == b[j])
{
num4 = i + 1;
num2++;
if (num2 > num)
{
num = num2;
}
break;
}
if (num2 > num)
{
num = num2;
}
num2 = 0;
}
if (num3 >= length2)
{
break;
}
}
if (num2 > num)
{
num = num2;
}
if (num < minMatchCount)
{
return 0;
}
return num4 - startA;
}
public string GetHierarchyPath(Transform root, Transform t)
{
if (t == null)
{
return "";
}
Stack<string> stack = new Stack<string>();
Transform transform = t;
while (transform != null && transform != root)
{
stack.Push(transform.name);
transform = transform.parent;
}
return string.Join("/", stack);
}
public string NormalizeName(string s)
{
if (string.IsNullOrEmpty(s))
{
return "";
}
s = s.ToLowerInvariant();
s = s.Replace("left", "l").Replace("right", "r");
char[] array = this.nameDelims;
foreach (char c in array)
{
s = s.Replace(c.ToString(), "");
}
s = this.StripDigits(s);
return s;
}
public string NormalizePath(string p)
{
if (string.IsNullOrEmpty(p))
{
return "";
}
return string.Join("/", (from x in p.Split('/')
where !string.IsNullOrEmpty(x)
select x).Select(this.NormalizeName));
}
public string StripDigits(string s)
{
if (string.IsNullOrEmpty(s))
{
return "";
}
StringBuilder stringBuilder = new StringBuilder(s.Length);
foreach (char c in s)
{
if (!char.IsDigit(c))
{
stringBuilder.Append(c);
}
}
return stringBuilder.ToString();
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 1a08d4f82c8d94f4cadc7d8de2833278

View File

@@ -0,0 +1,610 @@
// 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 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.LastBone;
}
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<BoneRootLocalData> ConvertProfileBoneDataToRootLocalData(List<BoneData> boneDataList)
{
if (boneDataList == null || boneDataList.Count == 0)
{
throw new AutoMorpherException("Profile Bone Data is Missing", "[BoneMatchUtil] ConvertProfileBoneDataToRootLocalData\n - boneDataList is null or empty");
}
List<BoneRootLocalData> list = new List<BoneRootLocalData>(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<Transform> GetMeshBones(List<SkinnedMeshRenderer> meshRenderers)
{
HashSet<Transform> hashSet = new HashSet<Transform>();
if (meshRenderers != null)
{
foreach (SkinnedMeshRenderer meshRenderer in meshRenderers)
{
if (meshRenderer == null || meshRenderer.bones == null)
{
continue;
}
Transform[] bones = meshRenderer.bones;
foreach (Transform transform in bones)
{
if (transform != null)
{
hashSet.Add(transform);
}
}
}
}
return hashSet;
}
public List<BoneRootLocalData> GetRootLocalBones(Transform rootT, HashSet<Transform> boneList)
{
BoneCorrespondenceUtil correspondenceUtil = new BoneCorrespondenceUtil();
return (from t in boneList.Where((Transform t) => t != null).Distinct()
select new BoneRootLocalData
{
t = t,
name = t.name,
path = correspondenceUtil.GetHierarchyPath(rootT, t),
rootLocalPos = rootT.InverseTransformPoint(t.position),
rootLocalRot = Quaternion.Inverse(rootT.rotation) * t.rotation
}).ToList();
}
public List<BoneRootLocalData> GetBodyRootLocalBones(Transform bodyTransform, Animator bodyAnimator, List<SkinnedMeshRenderer> bodyMeshes)
{
if (bodyTransform == null)
{
throw new AutoMorpherException("Body Transform is Missing", "[BoneMatchUtil] GetBodyRootLocalBones\n - bodyTransform is null");
}
if (bodyAnimator == null)
{
throw new AutoMorpherException("Body Animator is Missing", "[BoneMatchUtil] GetBodyRootLocalBones\n - animator is null");
}
Dictionary<Transform, HumanBodyBones> humanoidBoneList = this.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<Transform> meshBones = this.GetMeshBones(bodyMeshes);
Dictionary<HumanBodyBones, HashSet<Transform>> dictionary = new MeshClassifier().MeshHumanoidBoneMatcher(bodyAnimator, bodyMeshes);
HashSet<Transform> hashSet = new HashSet<Transform>();
HashSet<Transform> hashSet2 = new HashSet<Transform>();
foreach (KeyValuePair<Transform, HumanBodyBones> item in humanoidBoneList)
{
if (item.Value != HumanBodyBones.LastBone && !(item.Key == null))
{
if (!dictionary.TryGetValue(item.Value, out var value) || value == null)
{
value = new HashSet<Transform>();
dictionary[item.Value] = value;
}
value.Add(item.Key);
}
}
foreach (KeyValuePair<HumanBodyBones, HashSet<Transform>> item2 in dictionary)
{
HumanBodyBones key = item2.Key;
if (key == HumanBodyBones.LastBone)
{
continue;
}
HashSet<Transform> value2 = item2.Value;
if (value2 == null || value2.Count == 0)
{
continue;
}
Transform transform = bodyAnimator.GetBoneTransform(key);
if (transform == null)
{
transform = value2.First();
}
if (transform == null)
{
continue;
}
hashSet.Add(transform);
foreach (Transform item3 in value2)
{
if (!(item3 == transform) && !(item3 == null))
{
hashSet2.Add(item3);
}
}
}
foreach (Transform item4 in meshBones)
{
if (!(item4 == null) && !hashSet2.Contains(item4))
{
hashSet.Add(item4);
}
}
List<BoneRootLocalData> rootLocalBones = this.GetRootLocalBones(bodyTransform, hashSet);
foreach (BoneRootLocalData item5 in rootLocalBones)
{
if (item5 != null && !(item5.t == null))
{
if (humanoidBoneList.TryGetValue(item5.t, out var value3))
{
item5.hBone = value3;
}
else
{
item5.hBone = HumanBodyBones.LastBone;
}
}
}
return rootLocalBones;
}
private Dictionary<Transform, HumanBodyBones> GetHumanoidBoneList(Animator bodyAnimator)
{
Dictionary<Transform, HumanBodyBones> dictionary = new Dictionary<Transform, HumanBodyBones>();
if (bodyAnimator == null || bodyAnimator.avatar == null || !bodyAnimator.avatar.isHuman)
{
return dictionary;
}
foreach (HumanBodyBones value in Enum.GetValues(typeof(HumanBodyBones)))
{
if (value != HumanBodyBones.LastBone)
{
Transform boneTransform = bodyAnimator.GetBoneTransform(value);
if (!(boneTransform == null))
{
dictionary.TryAdd(boneTransform, value);
}
}
}
return dictionary;
}
public void MatchClothesToBodyBones(List<BoneRootLocalData> bodyBones, List<BoneRootLocalData> clothesBones, out Dictionary<HumanBodyBones, HashSet<Transform>> clothHumanBones, out Dictionary<Transform, ClothBoneType> clothBoneTypeMap, out Dictionary<Transform, BoneRootLocalData> clothToBodyMatched)
{
clothHumanBones = new Dictionary<HumanBodyBones, HashSet<Transform>>();
clothBoneTypeMap = new Dictionary<Transform, ClothBoneType>();
clothToBodyMatched = new Dictionary<Transform, BoneRootLocalData>();
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 (this.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<Transform, BoneRootLocalData> dictionary = new Dictionary<Transform, BoneRootLocalData>();
foreach (IGrouping<BoneRootLocalData, (BoneRootLocalData, BoneRootLocalData, float, float, float, float, float)> item in from x in list group x by x.Item2)
{
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 (this.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 && tuple.Item1.t != null && tuple.Item2 != null)
{
dictionary[tuple.Item1.t] = tuple.Item2;
}
}
foreach (BoneRootLocalData clothesBone2 in clothesBones)
{
if (clothesBone2?.t == null)
{
continue;
}
if (dictionary.TryGetValue(clothesBone2.t, out var value))
{
clothBoneTypeMap[clothesBone2.t] = ClothBoneType.Body;
clothToBodyMatched[clothesBone2.t] = value;
HumanBodyBones hBone = value.hBone;
if (hBone != HumanBodyBones.LastBone)
{
if (!clothHumanBones.TryGetValue(hBone, out var value2))
{
value2 = new HashSet<Transform>();
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<Transform, Transform> BuildTransformMatchMap(List<BoneRootLocalData> sourceBones, List<BoneRootLocalData> destBones, bool resultReverse = false)
{
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<Transform, Transform> dictionary = new Dictionary<Transform, Transform>();
Dictionary<string, BoneRootLocalData> dictionary2 = new Dictionary<string, BoneRootLocalData>();
Dictionary<string, BoneRootLocalData> dictionary3 = new Dictionary<string, BoneRootLocalData>();
Dictionary<string, List<BoneRootLocalData>> dictionary4 = new Dictionary<string, List<BoneRootLocalData>>();
foreach (BoneRootLocalData destBone in destBones)
{
if (destBone == null || destBone.t == 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 ?? destBone.t.name;
if (!string.IsNullOrEmpty(text3))
{
if (!dictionary4.TryGetValue(text3, out var value))
{
value = (dictionary4[text3] = new List<BoneRootLocalData>());
}
value.Add(destBone);
}
}
HashSet<Transform> hashSet = new HashSet<Transform>();
foreach (BoneRootLocalData sourceBone in sourceBones)
{
if (sourceBone == null || sourceBone.t == null)
{
continue;
}
Transform transform = null;
string text4 = sourceBone.path ?? "";
if (text4.Length > 0 && dictionary2.TryGetValue(text4, out var value2) && value2 != null && value2.t != null && !hashSet.Contains(value2.t))
{
transform = value2.t;
}
if (transform == null && text4.Length > 0)
{
string text5 = boneCorrespondenceUtil.NormalizePath(text4);
if (text5.Length > 0 && dictionary3.TryGetValue(text5, out var value3) && value3 != null && value3.t != null && !hashSet.Contains(value3.t))
{
transform = value3.t;
}
}
if (transform == null)
{
string text6 = sourceBone.name ?? sourceBone.t.name;
if (!string.IsNullOrEmpty(text6) && dictionary4.TryGetValue(text6, out var value4))
{
float num = float.PositiveInfinity;
Transform transform2 = null;
for (int i = 0; i < value4.Count; i++)
{
BoneRootLocalData boneRootLocalData = value4[i];
if (boneRootLocalData != null && !(boneRootLocalData.t == null) && !hashSet.Contains(boneRootLocalData.t))
{
float num2 = Vector3.SqrMagnitude(boneRootLocalData.rootLocalPos - sourceBone.rootLocalPos);
if (num2 < num)
{
num = num2;
transform2 = boneRootLocalData.t;
}
}
}
transform = transform2;
}
}
if (transform != null)
{
if (resultReverse)
{
dictionary[transform] = sourceBone.t;
}
else
{
dictionary[sourceBone.t] = transform;
}
hashSet.Add(transform);
}
}
return dictionary;
}
public void RemapSourceClothMatchToTargetCloth(Transform sourceClothRoot, Transform targetClothRoot, Dictionary<HumanBodyBones, HashSet<Transform>> sourceClothHumanBones, Dictionary<Transform, ClothBoneType> sourceClothBoneTypeMap, out Dictionary<HumanBodyBones, HashSet<Transform>> targetClothHumanBones, out Dictionary<Transform, ClothBoneType> targetClothBoneTypeMap)
{
targetClothHumanBones = new Dictionary<HumanBodyBones, HashSet<Transform>>();
targetClothBoneTypeMap = new Dictionary<Transform, ClothBoneType>();
if (sourceClothRoot == null || targetClothRoot == 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<Transform> hashSet = new HashSet<Transform>();
foreach (KeyValuePair<Transform, ClothBoneType> item in sourceClothBoneTypeMap)
{
if (item.Key != null)
{
hashSet.Add(item.Key);
}
}
foreach (KeyValuePair<HumanBodyBones, HashSet<Transform>> sourceClothHumanBone in sourceClothHumanBones)
{
HashSet<Transform> value = sourceClothHumanBone.Value;
if (value == null || value.Count == 0)
{
continue;
}
foreach (Transform item2 in value)
{
if (item2 != 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<Transform> meshBones = this.GetMeshBones(targetClothRoot.GetComponentsInChildren<SkinnedMeshRenderer>(includeInactive: 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<BoneRootLocalData> rootLocalBones = this.GetRootLocalBones(sourceClothRoot, hashSet);
List<BoneRootLocalData> rootLocalBones2 = this.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<Transform, Transform> dictionary = this.BuildTransformMatchMap(rootLocalBones, rootLocalBones2);
foreach (KeyValuePair<Transform, ClothBoneType> item3 in sourceClothBoneTypeMap)
{
Transform key = item3.Key;
ClothBoneType value2 = item3.Value;
if (key == null || !dictionary.TryGetValue(key, out var value3) || value3 == 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<HumanBodyBones, HashSet<Transform>> sourceClothHumanBone2 in sourceClothHumanBones)
{
HumanBodyBones key2 = sourceClothHumanBone2.Key;
HashSet<Transform> value5 = sourceClothHumanBone2.Value;
if (value5 == null || value5.Count == 0)
{
continue;
}
foreach (Transform item4 in value5)
{
if (!(item4 == null) && dictionary.TryGetValue(item4, out var value6) && !(value6 == null))
{
if (!targetClothHumanBones.TryGetValue(key2, out var value7))
{
value7 = new HashSet<Transform>();
targetClothHumanBones[key2] = value7;
}
value7.Add(value6);
}
}
}
}
public void BuildSourceToProxyBoneMap(Animator sourceAvatar, Animator proxyAvatar, out Dictionary<Transform, Transform> sourceToProxy)
{
sourceToProxy = new Dictionary<Transform, Transform>();
if (sourceAvatar == null)
{
throw new AutoMorpherException("Source Avatar is Missing", "[AvatarBodyMatchUtil] BuildSourceToProxyBoneMap\n - sourceAvatar is null");
}
if (proxyAvatar == null)
{
throw new AutoMorpherException("Proxy Avatar is Missing", "[AvatarBodyMatchUtil] BuildSourceToProxyBoneMap\n - proxyAvatar is null");
}
Transform transform = sourceAvatar.transform;
Transform transform2 = proxyAvatar.transform;
HashSet<Transform> meshBones = this.GetMeshBones(transform2.GetComponentsInChildren<SkinnedMeshRenderer>(includeInactive: 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<Transform> meshBones2 = this.GetMeshBones(transform.GetComponentsInChildren<SkinnedMeshRenderer>(includeInactive: 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<BoneRootLocalData> rootLocalBones = this.GetRootLocalBones(transform2, meshBones);
List<BoneRootLocalData> rootLocalBones2 = this.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 = this.BuildTransformMatchMap(rootLocalBones, rootLocalBones2, resultReverse: true);
if (sourceToProxy == null)
{
throw new AutoMorpherException("Source To Proxy Map Build Failed", "[AvatarBodyMatchUtil] BuildSourceToProxyBoneMap\n - BuildTransformMatchMap returned null");
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 1b3f5d2f72b363c4a89a5c46103505c5

View File

@@ -0,0 +1,20 @@
// 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.BvhNode
using UnityEngine;
public struct BvhNode
{
public Bounds bounds;
public int leftChild;
public int rightChild;
public int start;
public int count;
public bool isLeaf;
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 8cff8387b82491d47a5ad0ba7d35a706

View File

@@ -0,0 +1,18 @@
// 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.BvhTriangle
using UnityEngine;
public struct BvhTriangle
{
public Vector3 a;
public Vector3 b;
public Vector3 c;
public Vector3 normal;
public HumanBodyBones mainHumanBone;
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 32009a1b0b1882e4f87cdff91a494b17

View File

@@ -0,0 +1,766 @@
// 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.BvhTriangleMesh
using System.Collections.Generic;
using UnityEngine;
public class BvhTriangleMesh
{
public struct ClosestHit
{
public int triangleIndex;
public Vector3 closestPoint;
public Vector3 normal;
public float sqrDistance;
public HumanBodyBones mainHumanBone;
}
private TriangleUtil triangleUtil;
private HumanBodyBones[] humanBones = new HumanBodyBones[34]
{
HumanBodyBones.Hips,
HumanBodyBones.Spine,
HumanBodyBones.Chest,
HumanBodyBones.UpperChest,
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.LeftToes,
HumanBodyBones.RightUpperLeg,
HumanBodyBones.RightLowerLeg,
HumanBodyBones.RightFoot,
HumanBodyBones.RightToes,
HumanBodyBones.Head,
HumanBodyBones.LeftEye,
HumanBodyBones.RightEye
};
public BvhTriangle[] triangles;
public BvhNode[] nodes;
public int[] triIndices;
private const int LeafMaxTriangles = 4;
public BvhTriangleMesh()
{
this.triangleUtil = new TriangleUtil();
}
private HumanBodyBones[] BuildVertexMainHumanBone(SkinnedMeshRenderer smr, Animator animator, HumanBodyBones[] bodyBones)
{
Mesh sharedMesh = smr.sharedMesh;
BoneWeight[] boneWeights = sharedMesh.boneWeights;
int[] boneToBodyIndex = this.BuildBoneToBodyIndexMap(smr, animator, bodyBones);
HumanBodyBones[] array = new HumanBodyBones[sharedMesh.vertexCount];
for (int i = 0; i < sharedMesh.vertexCount; i++)
{
BoneWeight boneWeight = boneWeights[i];
int bestBodyIdx = -1;
float bestWeight = 0f;
Try(boneWeight.boneIndex0, boneWeight.weight0);
Try(boneWeight.boneIndex1, boneWeight.weight1);
Try(boneWeight.boneIndex2, boneWeight.weight2);
Try(boneWeight.boneIndex3, boneWeight.weight3);
array[i] = ((bestBodyIdx >= 0) ? bodyBones[bestBodyIdx] : HumanBodyBones.LastBone);
void Try(int boneIdx, float w)
{
if (!(w <= 0f) && boneIdx >= 0 && boneIdx < boneToBodyIndex.Length)
{
int num = boneToBodyIndex[boneIdx];
if (num >= 0 && w > bestWeight)
{
bestWeight = w;
bestBodyIdx = num;
}
}
}
}
return array;
}
public BvhTriangleMesh BuildFromSkinnedMeshes(IReadOnlyList<SkinnedMeshRenderer> renderers, Animator animator)
{
if (renderers == null || renderers.Count == 0)
{
return null;
}
BvhTriangleMesh bvhTriangleMesh = new BvhTriangleMesh();
int num = 0;
foreach (SkinnedMeshRenderer renderer in renderers)
{
if (!(renderer == null) && !(renderer.sharedMesh == null))
{
num += renderer.sharedMesh.triangles.Length / 3;
}
}
if (num == 0)
{
return null;
}
bvhTriangleMesh.triangles = new BvhTriangle[num];
int num2 = 0;
Mesh mesh = new Mesh();
foreach (SkinnedMeshRenderer renderer2 in renderers)
{
if (renderer2 == null || renderer2.sharedMesh == null)
{
continue;
}
mesh.Clear();
renderer2.BakeMesh(mesh);
Vector3[] vertices = mesh.vertices;
int[] array = renderer2.sharedMesh.triangles;
BoneWeight[] boneWeights = renderer2.sharedMesh.boneWeights;
int[] boneToBodyIndex = this.BuildBoneToBodyIndexMap(renderer2, animator, this.humanBones);
int num3 = array.Length / 3;
Transform transform = renderer2.transform;
Vector3 lossyScale = transform.lossyScale;
Vector3 vector = new Vector3(1f / Mathf.Max(lossyScale.x, 1E-08f), 1f / Mathf.Max(lossyScale.y, 1E-08f), 1f / Mathf.Max(lossyScale.z, 1E-08f));
Matrix4x4 matrix4x = transform.localToWorldMatrix * Matrix4x4.Scale(vector);
for (int i = 0; i < num3; i++)
{
int num4 = array[i * 3];
int num5 = array[i * 3 + 1];
int num6 = array[i * 3 + 2];
Vector3 vector2 = matrix4x.MultiplyPoint3x4(vertices[num4]);
Vector3 vector3 = matrix4x.MultiplyPoint3x4(vertices[num5]);
Vector3 vector4 = matrix4x.MultiplyPoint3x4(vertices[num6]);
Vector3 normal = Vector3.Cross(vector3 - vector2, vector4 - vector2);
float magnitude = normal.magnitude;
if (magnitude > 1E-08f)
{
normal /= magnitude;
}
else
{
normal = Vector3.up;
}
int num7 = this.ComputeTriangleMainHumanBoneIndex(num4, num5, num6, boneWeights, boneToBodyIndex, this.humanBones.Length);
HumanBodyBones mainHumanBone = ((num7 >= 0) ? this.humanBones[num7] : HumanBodyBones.LastBone);
bvhTriangleMesh.triangles[num2++] = new BvhTriangle
{
a = vector2,
b = vector3,
c = vector4,
normal = normal,
mainHumanBone = mainHumanBone
};
mesh.Clear();
}
}
int num8 = num;
int[] array2 = new int[num8];
for (int j = 0; j < num8; j++)
{
array2[j] = j;
}
bvhTriangleMesh.triIndices = array2;
List<BvhNode> list = new List<BvhNode>();
this.BuildRecursive(bvhTriangleMesh.triangles, array2, 0, num8, list);
bvhTriangleMesh.nodes = list.ToArray();
return bvhTriangleMesh;
}
private int[] BuildBoneToBodyIndexMap(SkinnedMeshRenderer smr, Animator animator, HumanBodyBones[] bodyBones)
{
Transform[] bones = smr.bones;
int[] array = new int[bones.Length];
for (int i = 0; i < array.Length; i++)
{
array[i] = -1;
}
if (animator == null || bodyBones == null || bones == null)
{
return array;
}
Dictionary<Transform, int> dictionary = new Dictionary<Transform, int>();
for (int j = 0; j < bones.Length; j++)
{
if (!(bones[j] == null) && !dictionary.ContainsKey(bones[j]))
{
dictionary.Add(bones[j], j);
}
}
Dictionary<HumanBodyBones, HashSet<Transform>> dictionary2 = new MeshClassifier().MeshHumanoidBoneMatcher(animator, new SkinnedMeshRenderer[1] { smr });
for (int k = 0; k < bodyBones.Length; k++)
{
HumanBodyBones key = bodyBones[k];
if (!dictionary2.TryGetValue(key, out var value) || value == null)
{
continue;
}
foreach (Transform item in value)
{
if (!(item == null) && dictionary.TryGetValue(item, out var value2))
{
array[value2] = k;
}
}
}
for (int l = 0; l < bones.Length; l++)
{
if (array[l] != -1)
{
continue;
}
Transform transform = bones[l];
if (transform == null)
{
continue;
}
Transform parent = transform.parent;
if (!(parent == null) && dictionary.TryGetValue(parent, out var value3))
{
int num = array[value3];
if (num != -1)
{
array[l] = num;
}
}
}
return array;
}
private int ComputeTriangleMainHumanBoneIndex(int vi0, int vi1, int vi2, BoneWeight[] weights, int[] boneToBodyIndex, int bodyBonesCount)
{
if (weights == null || weights.Length == 0 || boneToBodyIndex == null || boneToBodyIndex.Length == 0)
{
return -1;
}
float[] scores = new float[bodyBonesCount];
Accumulate(vi0);
Accumulate(vi1);
Accumulate(vi2);
int result = -1;
float num = 0f;
for (int i = 0; i < scores.Length; i++)
{
if (scores[i] > num)
{
num = scores[i];
result = i;
}
}
return result;
void Accumulate(int v)
{
if (v >= 0 && v < weights.Length)
{
BoneWeight boneWeight = weights[v];
Add(boneWeight.boneIndex0, boneWeight.weight0);
Add(boneWeight.boneIndex1, boneWeight.weight1);
Add(boneWeight.boneIndex2, boneWeight.weight2);
Add(boneWeight.boneIndex3, boneWeight.weight3);
}
}
void Add(int boneIdx, float w)
{
if (!(w <= 0f) && boneIdx >= 0 && boneIdx < boneToBodyIndex.Length)
{
int num2 = boneToBodyIndex[boneIdx];
if (num2 >= 0)
{
scores[num2] += w;
}
}
}
}
public BvhTriangleMesh BuildFromSkinnedMeshes(IList<SkinnedMeshRenderer> renderers)
{
if (renderers == null || renderers.Count == 0)
{
return null;
}
BvhTriangleMesh bvhTriangleMesh = new BvhTriangleMesh();
int num = 0;
foreach (SkinnedMeshRenderer renderer in renderers)
{
if (!(renderer == null) && !(renderer.sharedMesh == null))
{
num += renderer.sharedMesh.triangles.Length / 3;
}
}
if (num == 0)
{
return null;
}
bvhTriangleMesh.triangles = new BvhTriangle[num];
int num2 = 0;
foreach (SkinnedMeshRenderer renderer2 in renderers)
{
if (renderer2 == null || renderer2.sharedMesh == null)
{
continue;
}
Mesh sharedMesh = renderer2.sharedMesh;
Vector3[] vertices = sharedMesh.vertices;
int[] array = sharedMesh.triangles;
int num3 = array.Length / 3;
for (int i = 0; i < num3; i++)
{
int num4 = array[i * 3];
int num5 = array[i * 3 + 1];
int num6 = array[i * 3 + 2];
Vector3 vector = renderer2.transform.TransformPoint(vertices[num4]);
Vector3 vector2 = renderer2.transform.TransformPoint(vertices[num5]);
Vector3 vector3 = renderer2.transform.TransformPoint(vertices[num6]);
Vector3 normal = Vector3.Cross(vector2 - vector, vector3 - vector);
float magnitude = normal.magnitude;
if (magnitude > 1E-08f)
{
normal /= magnitude;
}
else
{
normal = Vector3.up;
}
bvhTriangleMesh.triangles[num2++] = new BvhTriangle
{
a = vector,
b = vector2,
c = vector3,
normal = normal
};
}
}
int num7 = num;
int[] array2 = new int[num7];
for (int j = 0; j < num7; j++)
{
array2[j] = j;
}
bvhTriangleMesh.triIndices = array2;
List<BvhNode> list = new List<BvhNode>();
this.BuildRecursive(bvhTriangleMesh.triangles, array2, 0, num7, list);
bvhTriangleMesh.nodes = list.ToArray();
return bvhTriangleMesh;
}
public BvhTriangleMesh BuildFromMesh(Mesh mesh, Transform transform)
{
BvhTriangleMesh bvhTriangleMesh = new BvhTriangleMesh();
Vector3[] vertices = mesh.vertices;
int[] array = mesh.triangles;
int num = array.Length / 3;
bvhTriangleMesh.triangles = new BvhTriangle[num];
for (int i = 0; i < num; i++)
{
int num2 = array[i * 3];
int num3 = array[i * 3 + 1];
int num4 = array[i * 3 + 2];
Vector3 vector = transform.TransformPoint(vertices[num2]);
Vector3 vector2 = transform.TransformPoint(vertices[num3]);
Vector3 vector3 = transform.TransformPoint(vertices[num4]);
Vector3 normal = Vector3.Cross(vector2 - vector, vector3 - vector);
float magnitude = normal.magnitude;
if (magnitude > 1E-08f)
{
normal /= magnitude;
}
else
{
normal = Vector3.up;
}
bvhTriangleMesh.triangles[i] = new BvhTriangle
{
a = vector,
b = vector2,
c = vector3,
normal = normal
};
}
int[] array2 = new int[num];
for (int j = 0; j < num; j++)
{
array2[j] = j;
}
bvhTriangleMesh.triIndices = array2;
List<BvhNode> list = new List<BvhNode>();
this.BuildRecursive(bvhTriangleMesh.triangles, array2, 0, num, list);
bvhTriangleMesh.nodes = list.ToArray();
return bvhTriangleMesh;
}
private int BuildRecursive(BvhTriangle[] tris, int[] triIndices, int start, int count, List<BvhNode> outNodes)
{
int count2 = outNodes.Count;
BvhNode bvhNode = default(BvhNode);
Bounds bounds = default(Bounds);
bool flag = true;
for (int i = start; i < start + count; i++)
{
BvhTriangle bvhTriangle = tris[triIndices[i]];
if (flag)
{
bounds = new Bounds(bvhTriangle.a, Vector3.zero);
bounds.Encapsulate(bvhTriangle.b);
bounds.Encapsulate(bvhTriangle.c);
flag = false;
}
else
{
bounds.Encapsulate(bvhTriangle.a);
bounds.Encapsulate(bvhTriangle.b);
bounds.Encapsulate(bvhTriangle.c);
}
}
bvhNode.bounds = bounds;
if (count <= 4)
{
bvhNode.isLeaf = true;
bvhNode.start = start;
bvhNode.count = count;
bvhNode.leftChild = -1;
bvhNode.rightChild = -1;
outNodes.Add(bvhNode);
return count2;
}
Vector3 size = bounds.size;
int num = 0;
if (size.y > size.x && size.y > size.z)
{
num = 1;
}
else if (size.z > size.x && size.z > size.y)
{
num = 2;
}
float num2 = 0f;
for (int j = start; j < start + count; j++)
{
BvhTriangle bvhTriangle2 = tris[triIndices[j]];
num2 += ((bvhTriangle2.a + bvhTriangle2.b + bvhTriangle2.c) / 3f)[num];
}
num2 /= (float)count;
int num3 = this.Partition(tris, triIndices, start, count, num, num2);
if (num3 == start || num3 == start + count)
{
num3 = start + count / 2;
}
bvhNode.isLeaf = false;
bvhNode.start = -1;
bvhNode.count = 0;
outNodes.Add(bvhNode);
int leftChild = this.BuildRecursive(tris, triIndices, start, num3 - start, outNodes);
int rightChild = this.BuildRecursive(tris, triIndices, num3, start + count - num3, outNodes);
bvhNode.leftChild = leftChild;
bvhNode.rightChild = rightChild;
outNodes[count2] = bvhNode;
return count2;
}
private int Partition(BvhTriangle[] tris, int[] triIndices, int start, int count, int axis, float splitPos)
{
int num = start;
int num2 = start + count - 1;
while (num <= num2)
{
BvhTriangle bvhTriangle = tris[triIndices[num]];
BvhTriangle bvhTriangle2 = tris[triIndices[num2]];
float num3 = (bvhTriangle.a[axis] + bvhTriangle.b[axis] + bvhTriangle.c[axis]) / 3f;
_ = (bvhTriangle2.a[axis] + bvhTriangle2.b[axis] + bvhTriangle2.c[axis]) / 3f;
if (num3 < splitPos)
{
num++;
continue;
}
int num4 = triIndices[num];
triIndices[num] = triIndices[num2];
triIndices[num2] = num4;
num2--;
}
return num;
}
public ClosestHit QueryClosest(Vector3 point)
{
ClosestHit best = new ClosestHit
{
triangleIndex = -1,
sqrDistance = float.MaxValue
};
if (this.nodes == null || this.nodes.Length == 0)
{
return best;
}
this.QueryClosestRecursive(0, point, ref best);
return best;
}
public ClosestHit QueryClosest(Vector3 point, HashSet<HumanBodyBones> allowedBones)
{
ClosestHit best = new ClosestHit
{
triangleIndex = -1,
sqrDistance = float.MaxValue
};
if (this.nodes == null || this.nodes.Length == 0)
{
return best;
}
if (allowedBones == null || allowedBones.Count == 0)
{
this.QueryClosestRecursive(0, point, ref best);
}
else
{
this.QueryClosestRecursiveFiltered(0, point, ref best, allowedBones);
}
return best;
}
private void QueryClosestRecursiveFiltered(int nodeIndex, Vector3 p, ref ClosestHit best, HashSet<HumanBodyBones> allowedBones)
{
BvhNode bvhNode = this.nodes[nodeIndex];
if (this.DistanceSqPointAABB(p, bvhNode.bounds) > best.sqrDistance)
{
return;
}
if (bvhNode.isLeaf)
{
int num = bvhNode.start + bvhNode.count;
for (int i = bvhNode.start; i < num; i++)
{
int num2 = this.triIndices[i];
BvhTriangle bvhTriangle = this.triangles[num2];
if (allowedBones.Contains(bvhTriangle.mainHumanBone))
{
Vector3 vector = this.triangleUtil.ClosestPointOnTriangle(p, bvhTriangle.a, bvhTriangle.b, bvhTriangle.c);
float sqrMagnitude = (p - vector).sqrMagnitude;
if (sqrMagnitude < best.sqrDistance)
{
best.sqrDistance = sqrMagnitude;
best.triangleIndex = num2;
best.closestPoint = vector;
best.normal = bvhTriangle.normal;
best.mainHumanBone = bvhTriangle.mainHumanBone;
}
}
}
}
else
{
int leftChild = bvhNode.leftChild;
int rightChild = bvhNode.rightChild;
float num3 = this.DistanceSqPointAABB(p, this.nodes[leftChild].bounds);
float num4 = this.DistanceSqPointAABB(p, this.nodes[rightChild].bounds);
if (num3 < num4)
{
this.QueryClosestRecursiveFiltered(leftChild, p, ref best, allowedBones);
this.QueryClosestRecursiveFiltered(rightChild, p, ref best, allowedBones);
}
else
{
this.QueryClosestRecursiveFiltered(rightChild, p, ref best, allowedBones);
this.QueryClosestRecursiveFiltered(leftChild, p, ref best, allowedBones);
}
}
}
private void QueryClosestRecursive(int nodeIndex, Vector3 p, ref ClosestHit best)
{
BvhNode bvhNode = this.nodes[nodeIndex];
if (this.DistanceSqPointAABB(p, bvhNode.bounds) > best.sqrDistance)
{
return;
}
if (bvhNode.isLeaf)
{
int num = bvhNode.start + bvhNode.count;
for (int i = bvhNode.start; i < num; i++)
{
int num2 = this.triIndices[i];
BvhTriangle bvhTriangle = this.triangles[num2];
Vector3 vector = this.triangleUtil.ClosestPointOnTriangle(p, bvhTriangle.a, bvhTriangle.b, bvhTriangle.c);
float sqrMagnitude = (p - vector).sqrMagnitude;
if (sqrMagnitude < best.sqrDistance)
{
best.sqrDistance = sqrMagnitude;
best.triangleIndex = num2;
best.closestPoint = vector;
best.normal = bvhTriangle.normal;
best.mainHumanBone = bvhTriangle.mainHumanBone;
}
}
}
else
{
int leftChild = bvhNode.leftChild;
int rightChild = bvhNode.rightChild;
float num3 = this.DistanceSqPointAABB(p, this.nodes[leftChild].bounds);
float num4 = this.DistanceSqPointAABB(p, this.nodes[rightChild].bounds);
if (num3 < num4)
{
this.QueryClosestRecursive(leftChild, p, ref best);
this.QueryClosestRecursive(rightChild, p, ref best);
}
else
{
this.QueryClosestRecursive(rightChild, p, ref best);
this.QueryClosestRecursive(leftChild, p, ref best);
}
}
}
private float DistanceSqPointAABB(Vector3 p, Bounds b)
{
float num = Mathf.Max(b.min.x - p.x, 0f, p.x - b.max.x);
float num2 = Mathf.Max(b.min.y - p.y, 0f, p.y - b.max.y);
float num3 = Mathf.Max(b.min.z - p.z, 0f, p.z - b.max.z);
return num * num + num2 * num2 + num3 * num3;
}
public int QueryClosestN(Vector3 point, int maxCount, float maxDistance, List<ClosestHit> results)
{
results.Clear();
if (this.nodes == null || this.nodes.Length == 0 || maxCount <= 0)
{
return 0;
}
float num = maxDistance * maxDistance;
float currentMaxSq = num;
this.QueryClosestNRecursive(0, point, maxCount, num, results, ref currentMaxSq);
return results.Count;
}
private void QueryClosestNRecursive(int nodeIndex, Vector3 p, int maxCount, float maxDistanceSq, List<ClosestHit> bestHits, ref float currentMaxSq)
{
BvhNode bvhNode = this.nodes[nodeIndex];
if (this.DistanceSqPointAABB(p, bvhNode.bounds) > currentMaxSq)
{
return;
}
if (bvhNode.isLeaf)
{
int num = bvhNode.start + bvhNode.count;
for (int i = bvhNode.start; i < num; i++)
{
int num2 = this.triIndices[i];
BvhTriangle bvhTriangle = this.triangles[num2];
Vector3 vector = this.triangleUtil.ClosestPointOnTriangle(p, bvhTriangle.a, bvhTriangle.b, bvhTriangle.c);
float sqrMagnitude = (p - vector).sqrMagnitude;
if (sqrMagnitude > maxDistanceSq)
{
continue;
}
if (bestHits.Count < maxCount)
{
bestHits.Add(new ClosestHit
{
triangleIndex = num2,
closestPoint = vector,
normal = bvhTriangle.normal,
sqrDistance = sqrMagnitude,
mainHumanBone = bvhTriangle.mainHumanBone
});
if (bestHits.Count == maxCount)
{
currentMaxSq = this.GetMaxSqrDistance(bestHits, maxDistanceSq);
}
}
else
{
if (sqrMagnitude >= currentMaxSq)
{
continue;
}
int index = 0;
float sqrDistance = bestHits[0].sqrDistance;
for (int j = 1; j < bestHits.Count; j++)
{
if (bestHits[j].sqrDistance > sqrDistance)
{
sqrDistance = bestHits[j].sqrDistance;
index = j;
}
}
bestHits[index] = new ClosestHit
{
triangleIndex = num2,
closestPoint = vector,
normal = bvhTriangle.normal,
sqrDistance = sqrMagnitude
};
currentMaxSq = this.GetMaxSqrDistance(bestHits, maxDistanceSq);
}
}
}
else
{
int leftChild = bvhNode.leftChild;
int rightChild = bvhNode.rightChild;
float num3 = this.DistanceSqPointAABB(p, this.nodes[leftChild].bounds);
float num4 = this.DistanceSqPointAABB(p, this.nodes[rightChild].bounds);
if (num3 < num4)
{
this.QueryClosestNRecursive(leftChild, p, maxCount, maxDistanceSq, bestHits, ref currentMaxSq);
this.QueryClosestNRecursive(rightChild, p, maxCount, maxDistanceSq, bestHits, ref currentMaxSq);
}
else
{
this.QueryClosestNRecursive(rightChild, p, maxCount, maxDistanceSq, bestHits, ref currentMaxSq);
this.QueryClosestNRecursive(leftChild, p, maxCount, maxDistanceSq, bestHits, ref currentMaxSq);
}
}
}
private float GetMaxSqrDistance(List<ClosestHit> bestHits, float maxDistanceSq)
{
if (bestHits.Count == 0)
{
return maxDistanceSq;
}
float sqrDistance = bestHits[0].sqrDistance;
for (int i = 1; i < bestHits.Count; i++)
{
if (bestHits[i].sqrDistance > sqrDistance)
{
sqrDistance = bestHits[i].sqrDistance;
}
}
return Mathf.Min(sqrDistance, maxDistanceSq);
}
public Vector3 ComputeMoveVectorToSurface(Vector3 p, float targetGap = 0f)
{
ClosestHit closestHit = this.QueryClosest(p);
if (closestHit.triangleIndex < 0)
{
return Vector3.zero;
}
Vector3 result = closestHit.closestPoint - p;
if (targetGap > 0f)
{
result += closestHit.normal.normalized * targetGap;
}
return result;
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 26359c45f906f7346836cb8290c0ae62

View File

@@ -0,0 +1,9 @@
// 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.ClothBoneType
public enum ClothBoneType
{
Body,
Accessory
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 5f2e2dc7719ac914497c5f6f71c28f66

View File

@@ -0,0 +1,301 @@
// 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.ClothHumanoidMaskUtil
using System.Collections.Generic;
using UnityEngine;
public class ClothHumanoidMaskUtil
{
public void BuildExcludedVertexMaskForHandsAndHead(ClothInstance clothInstance, bool excludeHandRoot = false, bool excludeThumbRoot = false)
{
if (clothInstance == null || clothInstance.smr == null)
{
Debug.LogWarning("[ClothHumanoidMaskUtil] clothInstance / smr 가 null");
return;
}
SkinnedMeshRenderer smr = clothInstance.smr;
Mesh mesh = clothInstance.editableMesh ?? smr.sharedMesh;
if (mesh == null)
{
Debug.LogWarning("[ClothHumanoidMaskUtil] mesh 가 null");
return;
}
BoneWeight[] boneWeights = mesh.boneWeights;
Transform[] bones = smr.bones;
if (boneWeights == null || boneWeights.Length == 0 || bones == null || bones.Length == 0)
{
Debug.LogWarning("[ClothHumanoidMaskUtil] boneWeights 또는 bones 비어있음");
return;
}
if (clothInstance.humanoidMatchedBones == null || clothInstance.humanoidMatchedBones.Count == 0)
{
Debug.LogWarning("[ClothHumanoidMaskUtil] humanoidMatchedBones 가 비어있음 (BodyToClothPoseApplier에서 매칭 안 되었을 가능성)");
return;
}
int num = mesh.vertexCount;
if (boneWeights.Length != num)
{
num = Mathf.Min(num, boneWeights.Length);
}
HashSet<Transform> excludedBones = new HashSet<Transform>();
Dictionary<HumanBodyBones, HashSet<Transform>> humanoidMatchedBones = clothInstance.humanoidMatchedBones;
if (humanoidMatchedBones.TryGetValue(HumanBodyBones.Head, out var value) && value != null)
{
foreach (Transform item in value)
{
if (!(item == null))
{
AddHierarchy(item, includeRoot: true);
}
}
}
if (humanoidMatchedBones.TryGetValue(HumanBodyBones.LeftHand, out var value2) && value2 != null)
{
foreach (Transform item2 in value2)
{
if (!(item2 == null))
{
AddHierarchy(item2, excludeHandRoot);
}
}
}
if (humanoidMatchedBones.TryGetValue(HumanBodyBones.RightHand, out var value3) && value3 != null)
{
foreach (Transform item3 in value3)
{
if (!(item3 == null))
{
AddHierarchy(item3, excludeHandRoot);
}
}
}
if (humanoidMatchedBones.TryGetValue(HumanBodyBones.LeftThumbProximal, out var value4) && value4 != null)
{
foreach (Transform item4 in value4)
{
if (!(item4 == null))
{
if (excludeThumbRoot)
{
excludedBones.Add(item4);
}
else
{
excludedBones.Remove(item4);
}
}
}
}
if (humanoidMatchedBones.TryGetValue(HumanBodyBones.RightThumbProximal, out var value5) && value5 != null)
{
foreach (Transform item5 in value5)
{
if (!(item5 == null))
{
if (excludeThumbRoot)
{
excludedBones.Add(item5);
}
else
{
excludedBones.Remove(item5);
}
}
}
}
bool[] boneIndexExcluded = new bool[bones.Length];
for (int i = 0; i < bones.Length; i++)
{
Transform transform = bones[i];
if (transform != null && excludedBones.Contains(transform))
{
boneIndexExcluded[i] = true;
}
}
bool[] array = new bool[num];
for (int j = 0; j < num; j++)
{
BoneWeight boneWeight = boneWeights[j];
float excludedWeightSum = 0f;
AddExcludedWeight(boneWeight.weight0, boneWeight.boneIndex0);
AddExcludedWeight(boneWeight.weight1, boneWeight.boneIndex1);
AddExcludedWeight(boneWeight.weight2, boneWeight.boneIndex2);
AddExcludedWeight(boneWeight.weight3, boneWeight.boneIndex3);
array[j] = excludedWeightSum >= 0.8f;
void AddExcludedWeight(float w, int bi)
{
if (!(w <= 0f) && bi >= 0 && bi < boneIndexExcluded.Length && boneIndexExcluded[bi])
{
excludedWeightSum += w;
}
}
}
clothInstance.excludedVertices = array;
this.BuildLegVertexMasks(clothInstance);
void AddHierarchy(Transform root, bool includeRoot)
{
if (!(root == null))
{
Stack<Transform> stack = new Stack<Transform>();
if (includeRoot)
{
stack.Push(root);
}
else
{
for (int k = 0; k < root.childCount; k++)
{
stack.Push(root.GetChild(k));
}
}
while (stack.Count > 0)
{
Transform transform2 = stack.Pop();
if (!(transform2 == null) && excludedBones.Add(transform2))
{
for (int l = 0; l < transform2.childCount; l++)
{
stack.Push(transform2.GetChild(l));
}
}
}
}
}
}
public void BuildLegVertexMasks(ClothInstance clothInstance)
{
if (clothInstance == null || clothInstance.smr == null)
{
Debug.LogWarning("[ClothHumanoidMaskUtil] clothInstance / smr 가 null");
return;
}
SkinnedMeshRenderer smr = clothInstance.smr;
Mesh mesh = clothInstance.editableMesh ?? smr.sharedMesh;
if (mesh == null)
{
Debug.LogWarning("[ClothHumanoidMaskUtil] mesh 가 null");
return;
}
BoneWeight[] boneWeights = mesh.boneWeights;
Transform[] bones = smr.bones;
if (boneWeights == null || boneWeights.Length == 0 || bones == null || bones.Length == 0)
{
Debug.LogWarning("[ClothHumanoidMaskUtil] boneWeights 또는 bones 비어있음");
return;
}
if (clothInstance.humanoidMatchedBones == null || clothInstance.humanoidMatchedBones.Count == 0)
{
Debug.LogWarning("[ClothHumanoidMaskUtil] humanoidMatchedBones 가 비어있음 (BodyToClothPoseApplier에서 매칭 필요)");
return;
}
int num = mesh.vertexCount;
if (boneWeights.Length != num)
{
num = Mathf.Min(num, boneWeights.Length);
}
Dictionary<HumanBodyBones, HashSet<Transform>> humanoidMatchedBones = clothInstance.humanoidMatchedBones;
HashSet<Transform> hashSet = new HashSet<Transform>();
HashSet<Transform> hashSet2 = new HashSet<Transform>();
if (humanoidMatchedBones.TryGetValue(HumanBodyBones.LeftUpperLeg, out var value) && value != null)
{
foreach (Transform item in value)
{
if (!(item == null))
{
CollectHierarchy(item, hashSet);
}
}
}
if (humanoidMatchedBones.TryGetValue(HumanBodyBones.RightUpperLeg, out var value2) && value2 != null)
{
foreach (Transform item2 in value2)
{
if (!(item2 == null))
{
CollectHierarchy(item2, hashSet2);
}
}
}
bool[] boneIsLeftLeg = new bool[bones.Length];
bool[] boneIsRightLeg = new bool[bones.Length];
for (int i = 0; i < bones.Length; i++)
{
Transform transform = bones[i];
if (!(transform == null))
{
if (hashSet.Contains(transform))
{
boneIsLeftLeg[i] = true;
}
if (hashSet2.Contains(transform))
{
boneIsRightLeg[i] = true;
}
}
}
bool[] array = new bool[num];
bool[] array2 = new bool[num];
for (int j = 0; j < num; j++)
{
BoneWeight boneWeight = boneWeights[j];
float leftWeight = 0f;
float rightWeight = 0f;
Check(boneWeight.boneIndex0, boneWeight.weight0);
Check(boneWeight.boneIndex1, boneWeight.weight1);
Check(boneWeight.boneIndex2, boneWeight.weight2);
Check(boneWeight.boneIndex3, boneWeight.weight3);
if (leftWeight > 0.8f)
{
array[j] = true;
array2[j] = false;
}
else if (rightWeight > 0.8f)
{
array[j] = false;
array2[j] = true;
}
else
{
array[j] = false;
array2[j] = false;
}
void Check(int bi, float w)
{
if (bi >= 0 && bi < bones.Length && !(w <= 0f))
{
if (boneIsLeftLeg[bi])
{
leftWeight += w;
}
if (boneIsRightLeg[bi])
{
rightWeight += w;
}
}
}
}
clothInstance.isLeftLegVertex = array;
clothInstance.isRightLegVertex = array2;
static void CollectHierarchy(Transform root, HashSet<Transform> set)
{
if (!(root == null))
{
Stack<Transform> stack = new Stack<Transform>();
stack.Push(root);
while (stack.Count > 0)
{
Transform transform2 = stack.Pop();
if (!(transform2 == null) && set.Add(transform2))
{
for (int k = 0; k < transform2.childCount; k++)
{
stack.Push(transform2.GetChild(k));
}
}
}
}
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 47dc065d4616e574a92830eba48a0269

View File

@@ -0,0 +1,539 @@
// 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.ClothInstance
using System;
using System.Collections.Generic;
using Eden.AutoMorpher;
using UnityEngine;
[Serializable]
public class ClothInstance
{
public SkinnedMeshRenderer smr;
public Mesh editableMesh;
public Mesh bakedMesh;
public Matrix4x4 worldNoScale;
public Vector3[] worldVertices;
public Vector3[] minDistanceVector;
public float[] minDistance;
public Vector3[] deltas;
public Vector3[] deltasLocal;
public List<int>[] vertexAdjacency;
public List<List<int>> equivalentVertices;
public bool[] isInsideVertex;
public bool[] excludedVertices;
public bool[] isLeftLegVertex;
public bool[] isRightLegVertex;
public Vector3[] bakedWorldNormals;
public Vector4[] bakedWorldTangents;
public Dictionary<HumanBodyBones, HashSet<Transform>> humanoidMatchedBones;
public ClothInstance(SkinnedMeshRenderer clotheSMR, bool duplicateMesh = true)
{
smr = clotheSMR;
if (duplicateMesh)
{
string name = smr.sharedMesh.name;
editableMesh = UnityEngine.Object.Instantiate(clotheSMR.sharedMesh);
editableMesh.name = name + "_EditableMesh";
smr.sharedMesh = editableMesh;
}
else
{
editableMesh = smr.sharedMesh;
}
UpdateWorldVertices();
int vertexCount = editableMesh.vertexCount;
minDistanceVector = new Vector3[vertexCount];
deltas = new Vector3[vertexCount];
minDistance = new float[vertexCount];
isInsideVertex = new bool[vertexCount];
excludedVertices = new bool[vertexCount];
isLeftLegVertex = new bool[vertexCount];
isRightLegVertex = new bool[vertexCount];
humanoidMatchedBones = new Dictionary<HumanBodyBones, HashSet<Transform>>();
vertexAdjacency = BuildVertexAdjacency(editableMesh);
BuildEquivalentVerticesFromWorld();
}
public void UpdateWorldVertices()
{
if (bakedMesh == null)
{
bakedMesh = new Mesh();
}
else
{
bakedMesh.Clear();
}
smr.BakeMesh(bakedMesh);
int vertexCount = editableMesh.vertexCount;
Vector3 lossyScale = smr.transform.lossyScale;
Vector3 vector = new Vector3(1f / Mathf.Max(lossyScale.x, 1E-08f), 1f / Mathf.Max(lossyScale.y, 1E-08f), 1f / Mathf.Max(lossyScale.z, 1E-08f));
worldNoScale = smr.transform.localToWorldMatrix * Matrix4x4.Scale(vector);
worldVertices = new Vector3[vertexCount];
deltasLocal = new Vector3[vertexCount];
for (int i = 0; i < vertexCount; i++)
{
worldVertices[i] = worldNoScale.MultiplyPoint3x4(bakedMesh.vertices[i]);
deltasLocal[i] = Vector3.zero;
}
Vector3[] normals = bakedMesh.normals;
Vector4[] tangents = bakedMesh.tangents;
bakedWorldNormals = new Vector3[vertexCount];
if (tangents != null && tangents.Length == vertexCount)
{
bakedWorldTangents = new Vector4[vertexCount];
}
else
{
bakedWorldTangents = null;
}
for (int j = 0; j < vertexCount; j++)
{
bakedWorldNormals[j] = smr.transform.TransformDirection(normals[j]).normalized;
if (bakedWorldTangents != null)
{
Vector3 normalized = smr.transform.TransformDirection(new Vector3(tangents[j].x, tangents[j].y, tangents[j].z)).normalized;
bakedWorldTangents[j] = new Vector4(normalized.x, normalized.y, normalized.z, tangents[j].w);
}
}
}
public List<int>[] BuildVertexAdjacency(Mesh mesh, float seamThreshold = 0.0001f, float proximityThreshold = 0f)
{
if (mesh == null)
{
throw new AutoMorpherException("Mesh is Missing", "[VertexAdjacencyUtil] BuildVertexAdjacency\n - mesh is null");
}
int vertexCount = mesh.vertexCount;
int[] triangles = mesh.triangles;
Vector3[] vertices = mesh.vertices;
List<int>[] array = new List<int>[vertexCount];
for (int i = 0; i < vertexCount; i++)
{
array[i] = new List<int>();
}
int num = triangles.Length / 3;
for (int j = 0; j < num; j++)
{
int num2 = triangles[j * 3];
int num3 = triangles[j * 3 + 1];
int num4 = triangles[j * 3 + 2];
AddNeighbor(array, num2, num3);
AddNeighbor(array, num3, num2);
AddNeighbor(array, num3, num4);
AddNeighbor(array, num4, num3);
AddNeighbor(array, num4, num2);
AddNeighbor(array, num2, num4);
}
if (seamThreshold > 0f)
{
float num5 = seamThreshold * 2f;
float num6 = seamThreshold * seamThreshold;
Dictionary<Vector3Int, List<int>> dictionary = new Dictionary<Vector3Int, List<int>>();
for (int k = 0; k < vertexCount; k++)
{
Vector3 vector = vertices[k];
Vector3Int key = new Vector3Int(Mathf.FloorToInt(vector.x / num5), Mathf.FloorToInt(vector.y / num5), Mathf.FloorToInt(vector.z / num5));
if (!dictionary.TryGetValue(key, out var value))
{
value = (dictionary[key] = new List<int>());
}
value.Add(k);
}
foreach (KeyValuePair<Vector3Int, List<int>> item in dictionary)
{
Vector3Int key2 = item.Key;
List<int> value2 = item.Value;
for (int l = -1; l <= 1; l++)
{
for (int m = -1; m <= 1; m++)
{
for (int n = -1; n <= 1; n++)
{
if (l < 0 || (l == 0 && m < 0) || (l == 0 && m == 0 && n < 0))
{
continue;
}
Vector3Int vector3Int = new Vector3Int(key2.x + l, key2.y + m, key2.z + n);
if (!dictionary.TryGetValue(vector3Int, out var value3))
{
continue;
}
if (vector3Int == key2)
{
for (int num7 = 0; num7 < value2.Count; num7++)
{
int num8 = value2[num7];
Vector3 vector2 = vertices[num8];
for (int num9 = num7 + 1; num9 < value2.Count; num9++)
{
int num10 = value2[num9];
if ((vertices[num10] - vector2).sqrMagnitude <= num6)
{
AddNeighbor(array, num8, num10);
AddNeighbor(array, num10, num8);
}
}
}
continue;
}
for (int num11 = 0; num11 < value2.Count; num11++)
{
int num12 = value2[num11];
Vector3 vector3 = vertices[num12];
for (int num13 = 0; num13 < value3.Count; num13++)
{
int num14 = value3[num13];
if ((vertices[num14] - vector3).sqrMagnitude <= num6)
{
AddNeighbor(array, num12, num14);
AddNeighbor(array, num14, num12);
}
}
}
}
}
}
}
}
if (proximityThreshold > 0f)
{
float num15 = proximityThreshold * 2f;
float num16 = proximityThreshold * proximityThreshold;
Dictionary<Vector3Int, List<int>> dictionary2 = new Dictionary<Vector3Int, List<int>>();
for (int num17 = 0; num17 < vertexCount; num17++)
{
Vector3 vector4 = vertices[num17];
Vector3Int key3 = new Vector3Int(Mathf.FloorToInt(vector4.x / num15), Mathf.FloorToInt(vector4.y / num15), Mathf.FloorToInt(vector4.z / num15));
if (!dictionary2.TryGetValue(key3, out var value4))
{
value4 = (dictionary2[key3] = new List<int>());
}
value4.Add(num17);
}
foreach (KeyValuePair<Vector3Int, List<int>> item2 in dictionary2)
{
Vector3Int key4 = item2.Key;
List<int> value5 = item2.Value;
for (int num18 = -1; num18 <= 1; num18++)
{
for (int num19 = -1; num19 <= 1; num19++)
{
for (int num20 = -1; num20 <= 1; num20++)
{
if (num18 < 0 || (num18 == 0 && num19 < 0) || (num18 == 0 && num19 == 0 && num20 < 0))
{
continue;
}
Vector3Int vector3Int2 = new Vector3Int(key4.x + num18, key4.y + num19, key4.z + num20);
if (!dictionary2.TryGetValue(vector3Int2, out var value6))
{
continue;
}
if (vector3Int2 == key4)
{
for (int num21 = 0; num21 < value5.Count; num21++)
{
int num22 = value5[num21];
Vector3 vector5 = vertices[num22];
for (int num23 = num21 + 1; num23 < value5.Count; num23++)
{
int num24 = value5[num23];
if ((vertices[num24] - vector5).sqrMagnitude <= num16)
{
AddNeighbor(array, num22, num24);
AddNeighbor(array, num24, num22);
}
}
}
continue;
}
for (int num25 = 0; num25 < value5.Count; num25++)
{
int num26 = value5[num25];
Vector3 vector6 = vertices[num26];
for (int num27 = 0; num27 < value6.Count; num27++)
{
int num28 = value6[num27];
if ((vertices[num28] - vector6).sqrMagnitude <= num16)
{
AddNeighbor(array, num26, num28);
AddNeighbor(array, num28, num26);
}
}
}
}
}
}
}
}
return array;
static void AddNeighbor(List<int>[] adj, int from, int to)
{
List<int> list3 = adj[from];
if (!list3.Contains(to))
{
list3.Add(to);
}
}
}
public void ApplyWorldVerticesToMesh()
{
if (editableMesh == null || smr == null || worldVertices == null)
{
return;
}
Mesh mesh = editableMesh;
int vertexCount = mesh.vertexCount;
Vector3[] vertices = mesh.vertices;
SkinningUtil skinningUtil = new SkinningUtil();
Vector3[] array = null;
int blendShapeCount = mesh.blendShapeCount;
if (blendShapeCount > 0)
{
array = new Vector3[vertexCount];
Vector3[] array2 = new Vector3[vertexCount];
Vector3[] deltaNormals = new Vector3[vertexCount];
Vector3[] deltaTangents = new Vector3[vertexCount];
for (int i = 0; i < blendShapeCount; i++)
{
float blendShapeWeight = smr.GetBlendShapeWeight(i);
if (Mathf.Approximately(blendShapeWeight, 0f))
{
continue;
}
int frameIndex = mesh.GetBlendShapeFrameCount(i) - 1;
float blendShapeFrameWeight = mesh.GetBlendShapeFrameWeight(i, frameIndex);
mesh.GetBlendShapeFrameVertices(i, frameIndex, array2, deltaNormals, deltaTangents);
float num = ((blendShapeFrameWeight != 0f) ? (blendShapeWeight / blendShapeFrameWeight) : 0f);
if (!Mathf.Approximately(num, 0f))
{
for (int j = 0; j < vertexCount; j++)
{
array[j] += array2[j] * num;
}
}
}
}
for (int k = 0; k < vertexCount; k++)
{
Vector3 vector = skinningUtil.WorldPosToBindPos_Full(smr, mesh, k, worldVertices[k]);
if (array != null)
{
vector -= array[k];
}
vertices[k] = vector;
}
mesh.vertices = vertices;
Vector3[] array3 = null;
Vector3[] array4 = null;
if (blendShapeCount > 0)
{
array3 = new Vector3[vertexCount];
array4 = new Vector3[vertexCount];
Vector3[] deltaVertices = new Vector3[vertexCount];
Vector3[] array5 = new Vector3[vertexCount];
Vector3[] array6 = new Vector3[vertexCount];
for (int l = 0; l < blendShapeCount; l++)
{
float blendShapeWeight2 = smr.GetBlendShapeWeight(l);
if (Mathf.Approximately(blendShapeWeight2, 0f))
{
continue;
}
int frameIndex2 = mesh.GetBlendShapeFrameCount(l) - 1;
float blendShapeFrameWeight2 = mesh.GetBlendShapeFrameWeight(l, frameIndex2);
mesh.GetBlendShapeFrameVertices(l, frameIndex2, deltaVertices, array5, array6);
float num2 = ((blendShapeFrameWeight2 != 0f) ? (blendShapeWeight2 / blendShapeFrameWeight2) : 0f);
if (!Mathf.Approximately(num2, 0f))
{
for (int m = 0; m < vertexCount; m++)
{
array3[m] += array5[m] * num2;
array4[m] += array6[m] * num2;
}
}
}
}
if (bakedWorldNormals == null || bakedWorldNormals.Length != vertexCount)
{
return;
}
Vector3[] array7 = new Vector3[vertexCount];
bool flag = bakedWorldTangents != null && bakedWorldTangents.Length == vertexCount;
Vector4[] array8 = (flag ? new Vector4[vertexCount] : null);
for (int n = 0; n < vertexCount; n++)
{
Vector3 vector2 = skinningUtil.WorldDirToBindDir_Full(smr, mesh, n, bakedWorldNormals[n]);
if (array3 != null)
{
vector2 -= array3[n];
}
array7[n] = vector2.normalized;
if (flag)
{
Vector3 vector3 = skinningUtil.WorldDirToBindDir_Full(targetWorldDir: new Vector3(bakedWorldTangents[n].x, bakedWorldTangents[n].y, bakedWorldTangents[n].z), smr: smr, bindMesh: mesh, vertexIndex: n);
if (array4 != null)
{
vector3 -= array4[n];
}
vector3 = vector3.normalized;
array8[n] = new Vector4(vector3.x, vector3.y, vector3.z, bakedWorldTangents[n].w);
}
}
mesh.normals = array7;
if (array8 != null)
{
mesh.tangents = array8;
}
}
public void BuildEquivalentVerticesFromWorld(float maxDistance = 1E-05f)
{
if (worldVertices == null || worldVertices.Length == 0)
{
Debug.LogWarning("[ClothInstance] BuildEquivalentVerticesFromWorld: worldVertices is null or empty. Call UpdateWorldVertices() first.");
return;
}
int num = worldVertices.Length;
if (equivalentVertices == null)
{
equivalentVertices = new List<List<int>>();
}
else
{
equivalentVertices.Clear();
}
float num2 = maxDistance * maxDistance;
Dictionary<Vector3Int, List<int>> dictionary = new Dictionary<Vector3Int, List<int>>();
for (int i = 0; i < num; i++)
{
Vector3 vector = worldVertices[i];
Vector3Int key = new Vector3Int(Mathf.FloorToInt(vector.x / maxDistance), Mathf.FloorToInt(vector.y / maxDistance), Mathf.FloorToInt(vector.z / maxDistance));
if (!dictionary.TryGetValue(key, out var value))
{
value = (dictionary[key] = new List<int>());
}
value.Add(i);
}
foreach (KeyValuePair<Vector3Int, List<int>> item in dictionary)
{
List<int> value2 = item.Value;
int count = value2.Count;
if (count < 2)
{
continue;
}
int[] parent = new int[count];
for (int j = 0; j < count; j++)
{
parent[j] = j;
}
for (int k = 0; k < count; k++)
{
int num3 = value2[k];
Vector3 vector2 = worldVertices[num3];
for (int l = k + 1; l < count; l++)
{
int num4 = value2[l];
Vector3 vector3 = worldVertices[num4];
if ((vector2 - vector3).sqrMagnitude <= num2)
{
Union(k, l);
}
}
}
Dictionary<int, List<int>> dictionary2 = new Dictionary<int, List<int>>();
for (int m = 0; m < count; m++)
{
int key2 = Find(m);
if (!dictionary2.TryGetValue(key2, out var value3))
{
value3 = (dictionary2[key2] = new List<int>());
}
value3.Add(value2[m]);
}
foreach (List<int> value4 in dictionary2.Values)
{
if (value4.Count >= 2)
{
equivalentVertices.Add(value4);
}
}
int Find(int x)
{
if (parent[x] != x)
{
parent[x] = Find(parent[x]);
}
return parent[x];
}
void Union(int a, int b)
{
int num5 = Find(a);
int num6 = Find(b);
if (num5 != num6)
{
parent[num6] = num5;
}
}
}
}
~ClothInstance()
{
Dispose();
}
public void Dispose()
{
if (bakedMesh != null)
{
UnityEngine.Object.DestroyImmediate(bakedMesh);
bakedMesh = null;
}
worldVertices = null;
minDistanceVector = null;
minDistance = null;
deltas = null;
deltasLocal = null;
isInsideVertex = null;
excludedVertices = null;
isLeftLegVertex = null;
isRightLegVertex = null;
vertexAdjacency = null;
if (equivalentVertices != null)
{
for (int i = 0; i < equivalentVertices.Count; i++)
{
equivalentVertices[i]?.Clear();
}
equivalentVertices.Clear();
equivalentVertices = null;
}
humanoidMatchedBones = null;
smr = null;
editableMesh = null;
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 40c5e34f6a4ef45489dc16cd660022ca

View File

@@ -0,0 +1,306 @@
// 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.ClothInstanceTotal
using System.Collections.Generic;
using UnityEngine;
public class ClothInstanceTotal
{
private readonly List<ClothInstance> clothInstances;
public int TotalVertexCount { get; private set; }
public Vector3[] GlobalPositions { get; private set; }
public Vector3[] GlobalDeltas { get; private set; }
public List<int>[] GlobalAdjacencyTopology { get; private set; }
public List<int>[] GlobalAdjacencyDistance { get; private set; }
public List<int>[] GlobalAdjacencyMerged { get; private set; }
public int[] VertexOffsets { get; private set; }
public ClothInstanceTotal(List<ClothInstance> clothInstances, float distanceBuildRadius, int maxNeighborsPerVertex = 0)
{
if (clothInstances == null || clothInstances.Count == 0)
{
throw new AutoMorpherException("Cloth Instances are Missing", "[ClothInstanceTotal] ClothInstanceTotal\n - clothInstances is null or empty");
}
if (distanceBuildRadius <= 0f)
{
throw new AutoMorpherException("Distance Build Radius is Invalid", "[ClothInstanceTotal] ClothInstanceTotal\n - distanceBuildRadius must be > 0");
}
this.clothInstances = clothInstances;
this.BuildTopologyCache();
this.BuildDistanceAdjacencyCandidates(distanceBuildRadius, maxNeighborsPerVertex);
this.BuildMergedAdjacency();
}
public void SetGlobalDeltas(Vector3[] globalDeltas)
{
if (globalDeltas == null || globalDeltas.Length != this.TotalVertexCount)
{
throw new AutoMorpherException("Global Deltas are Invalid", "[ClothInstanceTotal] SetGlobalDeltas\n - globalDeltas is null or length mismatch");
}
this.GlobalDeltas = globalDeltas;
}
public void UpdateGlobalBuffersFromClothInstances()
{
this.ValidateGlobalBufferReady("[ClothInstanceTotal] UpdateGlobalBuffersFromClothInstances");
for (int i = 0; i < this.clothInstances.Count; i++)
{
ClothInstance clothInstance = this.clothInstances[i];
if (clothInstance != null)
{
if (clothInstance.worldVertices == null || clothInstance.deltasLocal == null)
{
throw new AutoMorpherException("Cloth Instance Data is Missing", "[ClothInstanceTotal] UpdateGlobalBuffersFromClothInstances\n - worldVertices or deltasLocal is null");
}
int num = this.VertexOffsets[i];
int num2 = clothInstance.worldVertices.Length;
if (num2 != clothInstance.deltasLocal.Length)
{
throw new AutoMorpherException("Cloth Instance Array Length Mismatch", "[ClothInstanceTotal] UpdateGlobalBuffersFromClothInstances\n - worldVertices.Length != deltasLocal.Length");
}
for (int j = 0; j < num2; j++)
{
this.GlobalPositions[num + j] = clothInstance.worldVertices[j];
this.GlobalDeltas[num + j] = clothInstance.deltasLocal[j];
}
}
}
}
public void ApplyGlobalDeltasToClothInstances()
{
this.ValidateGlobalBufferReady("[ClothInstanceTotal] ApplyGlobalDeltasToClothInstances");
for (int i = 0; i < this.clothInstances.Count; i++)
{
ClothInstance clothInstance = this.clothInstances[i];
if (clothInstance != null)
{
if (clothInstance.deltasLocal == null)
{
throw new AutoMorpherException("Cloth Deltas are Missing", "[ClothInstanceTotal] ApplyGlobalDeltasToClothInstances\n - deltasLocal is null");
}
int num = this.VertexOffsets[i];
int num2 = clothInstance.deltasLocal.Length;
for (int j = 0; j < num2; j++)
{
clothInstance.deltasLocal[j] = this.GlobalDeltas[num + j];
}
}
}
}
private void ValidateGlobalBufferReady(string functionContext)
{
if (this.clothInstances == null || this.clothInstances.Count == 0)
{
throw new AutoMorpherException("Cloth Instances are Missing", functionContext + "\n - clothInstances is null or empty");
}
if (this.TotalVertexCount <= 0 || this.GlobalPositions == null || this.GlobalDeltas == null || this.VertexOffsets == null || this.GlobalAdjacencyMerged == null)
{
throw new AutoMorpherException("Cloth Instance Total Cache is Not Ready", functionContext + "\n - total/global buffers/merged adjacency are not initialized");
}
}
private void BuildTopologyCache()
{
this.TotalVertexCount = this.CalculateTotalVertexCount(this.clothInstances);
if (this.TotalVertexCount <= 0)
{
throw new AutoMorpherException("Total Vertex Count is Zero", "[ClothInstanceTotal] BuildTopologyCache\n - TotalVertexCount <= 0");
}
this.GlobalPositions = new Vector3[this.TotalVertexCount];
this.GlobalDeltas = new Vector3[this.TotalVertexCount];
this.GlobalAdjacencyTopology = new List<int>[this.TotalVertexCount];
this.VertexOffsets = new int[this.clothInstances.Count];
int num = 0;
for (int i = 0; i < this.clothInstances.Count; i++)
{
ClothInstance clothInstance = this.clothInstances[i];
this.VertexOffsets[i] = num;
if (clothInstance == null)
{
continue;
}
if (clothInstance.worldVertices == null || clothInstance.deltasLocal == null || clothInstance.vertexAdjacency == null)
{
throw new AutoMorpherException("Cloth Instance Data is Missing", "[ClothInstanceTotal] BuildTopologyCache\n - worldVertices/deltasLocal/vertexAdjacency is null");
}
int num2 = clothInstance.worldVertices.Length;
if (num2 != clothInstance.deltasLocal.Length || num2 != clothInstance.vertexAdjacency.Length)
{
throw new AutoMorpherException("Cloth Instance Array Length Mismatch", "[ClothInstanceTotal] BuildTopologyCache\n - worldVertices/deltasLocal/vertexAdjacency lengths differ");
}
for (int j = 0; j < num2; j++)
{
this.GlobalPositions[num + j] = clothInstance.worldVertices[j];
this.GlobalDeltas[num + j] = clothInstance.deltasLocal[j];
int capacity = clothInstance.vertexAdjacency[j]?.Count ?? 0;
this.GlobalAdjacencyTopology[num + j] = new List<int>(capacity);
}
for (int k = 0; k < num2; k++)
{
List<int> list = clothInstance.vertexAdjacency[k];
if (list == null)
{
continue;
}
int num3 = num + k;
List<int> list2 = this.GlobalAdjacencyTopology[num3];
for (int l = 0; l < list.Count; l++)
{
int num4 = list[l];
if ((uint)num4 >= (uint)num2)
{
throw new AutoMorpherException("Vertex Adjacency Index is Out of Range", "[ClothInstanceTotal] BuildTopologyCache\n - vertexAdjacency contains invalid neighbor index");
}
list2.Add(num + num4);
}
}
num += num2;
}
}
private void BuildDistanceAdjacencyCandidates(float radius, int maxNeighborsPerVertex)
{
if (this.GlobalPositions == null || this.GlobalPositions.Length == 0)
{
throw new AutoMorpherException("Reference Positions are Missing", "[ClothInstanceTotal] BuildDistanceAdjacencyCandidates\n - GlobalPositions is null or empty");
}
this.GlobalAdjacencyDistance = this.BuildDistanceAdjacencyCandidatesInternal(this.GlobalPositions, radius, maxNeighborsPerVertex);
}
private void BuildMergedAdjacency()
{
if (this.GlobalAdjacencyTopology == null || this.GlobalAdjacencyDistance == null)
{
throw new AutoMorpherException("Adjacency Inputs are Missing", "[ClothInstanceTotal] BuildMergedAdjacency\n - GlobalAdjacencyTopology or GlobalAdjacencyDistance is null");
}
if (this.GlobalAdjacencyTopology.Length != this.GlobalAdjacencyDistance.Length)
{
throw new AutoMorpherException("Adjacency Length Mismatch", "[ClothInstanceTotal] BuildMergedAdjacency\n - topology and distance adjacency length differ");
}
int num = this.GlobalAdjacencyTopology.Length;
this.GlobalAdjacencyMerged = new List<int>[num];
for (int i = 0; i < num; i++)
{
List<int> list = new List<int>((this.GlobalAdjacencyTopology[i]?.Count ?? 0) + (this.GlobalAdjacencyDistance[i]?.Count ?? 0));
HashSet<int> hashSet = new HashSet<int>();
List<int> list2 = this.GlobalAdjacencyTopology[i];
if (list2 != null)
{
for (int j = 0; j < list2.Count; j++)
{
int num2 = list2[j];
if (num2 != i && hashSet.Add(num2))
{
list.Add(num2);
}
}
}
List<int> list3 = this.GlobalAdjacencyDistance[i];
if (list3 != null)
{
for (int k = 0; k < list3.Count; k++)
{
int num3 = list3[k];
if (num3 != i && hashSet.Add(num3))
{
list.Add(num3);
}
}
}
this.GlobalAdjacencyMerged[i] = list;
}
}
private int CalculateTotalVertexCount(List<ClothInstance> clothInstances)
{
int num = 0;
for (int i = 0; i < clothInstances.Count; i++)
{
ClothInstance clothInstance = clothInstances[i];
if (clothInstance != null && clothInstance.worldVertices != null)
{
num += clothInstance.worldVertices.Length;
}
}
return num;
}
private List<int>[] BuildDistanceAdjacencyCandidatesInternal(Vector3[] referencePositions, float radius, int maxNeighborsPerVertex)
{
if (referencePositions == null || referencePositions.Length == 0)
{
throw new AutoMorpherException("Reference Positions are Missing", "[ClothInstanceTotal] BuildDistanceAdjacencyCandidatesInternal\n - referencePositions is null or empty");
}
if (radius <= 0f)
{
throw new AutoMorpherException("Radius is Invalid", "[ClothInstanceTotal] BuildDistanceAdjacencyCandidatesInternal\n - radius must be > 0");
}
int num = referencePositions.Length;
List<int>[] array = new List<int>[num];
for (int i = 0; i < num; i++)
{
array[i] = new List<int>(8);
}
float num2 = 1f / Mathf.Max(radius, 1E-12f);
float num3 = radius * radius;
Dictionary<Vector3Int, List<int>> dictionary = new Dictionary<Vector3Int, List<int>>(num);
for (int j = 0; j < num; j++)
{
Vector3 vector = referencePositions[j];
Vector3Int key = new Vector3Int(Mathf.FloorToInt(vector.x * num2), Mathf.FloorToInt(vector.y * num2), Mathf.FloorToInt(vector.z * num2));
if (!dictionary.TryGetValue(key, out var value))
{
value = new List<int>(16);
dictionary.Add(key, value);
}
value.Add(j);
}
for (int k = 0; k < num; k++)
{
Vector3 vector2 = referencePositions[k];
Vector3Int vector3Int = new Vector3Int(Mathf.FloorToInt(vector2.x * num2), Mathf.FloorToInt(vector2.y * num2), Mathf.FloorToInt(vector2.z * num2));
List<int> list = array[k];
for (int l = -1; l <= 1; l++)
{
for (int m = -1; m <= 1; m++)
{
for (int n = -1; n <= 1; n++)
{
Vector3Int key2 = new Vector3Int(vector3Int.x + l, vector3Int.y + m, vector3Int.z + n);
if (!dictionary.TryGetValue(key2, out var value2))
{
continue;
}
for (int num4 = 0; num4 < value2.Count; num4++)
{
int num5 = value2[num4];
if (num5 != k && !((referencePositions[num5] - vector2).sqrMagnitude > num3))
{
list.Add(num5);
if (maxNeighborsPerVertex > 0 && list.Count >= maxNeighborsPerVertex)
{
break;
}
}
}
if (maxNeighborsPerVertex > 0 && list.Count >= maxNeighborsPerVertex)
{
break;
}
}
}
}
}
return array;
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 565127c44f3596f4f88203da517ee42d

View File

@@ -0,0 +1,594 @@
// 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.EdenAutoMorpher
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
public class EdenAutoMorpher : MonoBehaviour
{
[SerializeField]
public GameObject sourceAvatarObject;
[SerializeField]
public GameObject sourceClothesObject;
[SerializeField]
private List<SkinnedMeshRenderer> sourceBodyMeshes = new List<SkinnedMeshRenderer>();
[SerializeField]
private IReadOnlyList<SkinnedMeshRenderer> sourceBodyMeshesReadOnly = new List<SkinnedMeshRenderer>();
[SerializeField]
public string profileName;
[SerializeField]
public GameObject targetAvatarObject;
[SerializeField]
private GameObject targetClothesObject;
[SerializeField]
private GameObject targetClothesObjectOriginal;
[SerializeField]
private List<SkinnedMeshRenderer> targetBodyMeshes = new List<SkinnedMeshRenderer>();
[SerializeField]
private IReadOnlyList<SkinnedMeshRenderer> targetBodyMeshesReadOnly = new List<SkinnedMeshRenderer>();
[SerializeField]
private float minMargin = 0.003f;
[SerializeField]
private float worldRadius = 0.1f;
[SerializeField]
private float sigma = 0.85f;
[SerializeField]
private int smoothingIteration = 1;
[SerializeField]
private int fittingExpandIteration = 10;
[SerializeField]
private int fittingShrinkIteration = 12;
[SerializeField]
public bool isBodyAutoSetup = true;
[SerializeField]
public bool isReparentAccessoryBonesToTargetAvatar = true;
[SerializeField]
public bool skipFootFitting;
[SerializeField]
public bool transferWeightToAvatar;
[SerializeField]
public bool addAnchorBone = true;
[SerializeField]
public bool armatureBoneScaleCopy;
[SerializeField]
public bool isRemoveAutoMorphedClothes = true;
private Dictionary<HumanBodyBones, HashSet<Transform>> clothesHumanoidMatchedBones;
private Dictionary<Transform, ClothBoneType> clothBoneTypeMap;
private GameObject fittedTargetAvatar;
private GameObject fittedTargetClothes;
private const string EditedMeshRootFolder = "Assets/@Eden_Mesh";
private string tagEdenMorpehrCloth = "EDENAutoMorpher_EditedCloth";
private bool doProcess;
private MorpherMode morpherMode;
private MorpherState morpherState;
private ProcessInfo processInfo;
public ProcessInfo GetProcessInfo()
{
return this.processInfo;
}
public void ChangeMode(MorpherMode newMode)
{
this.morpherMode = newMode;
this.morpherState = MorpherState.Idle;
}
public void StopProcess()
{
this.doProcess = false;
switch (this.morpherState)
{
case MorpherState.Fitting_Doing:
this.morpherState = MorpherState.Idle;
break;
case MorpherState.Weighting_Doing:
this.morpherState = MorpherState.Fitting_End;
break;
default:
this.morpherState = MorpherState.Idle;
break;
}
}
private EdenAutoMorpherConfig SetupConfigData(MorpherMode morpherMode)
{
EdenAutoMorpherConfig result = default(EdenAutoMorpherConfig);
switch (morpherMode)
{
case MorpherMode.AutoMorpher:
case MorpherMode.ManualMorpher:
result.sourceAvatarObject = this.sourceAvatarObject;
result.sourceClothesObject = this.sourceClothesObject;
result.sourceBodyMeshes = this.sourceBodyMeshesReadOnly;
result.profileName = string.Empty;
break;
case MorpherMode.ProfileMorpher:
result.sourceAvatarObject = null;
result.sourceClothesObject = this.sourceClothesObject;
result.sourceBodyMeshes = null;
result.profileName = this.profileName;
break;
default:
result.sourceAvatarObject = null;
result.sourceClothesObject = null;
result.sourceBodyMeshes = null;
result.profileName = string.Empty;
break;
}
result.targetAvatarObject = this.targetAvatarObject;
result.targetClothesObject = this.targetClothesObject;
result.targetBodyMeshes = this.targetBodyMeshesReadOnly;
result.minMargin = this.minMargin;
result.worldRadius = this.worldRadius;
result.sigma = this.sigma;
result.smoothingIteration = this.smoothingIteration;
result.fittingExpandIteration = this.fittingExpandIteration;
result.fittingShrinkIteration = this.fittingShrinkIteration;
result.isBodyAutoSetup = this.isBodyAutoSetup;
result.isReparentAccessoryBonesToTargetAvatar = this.isReparentAccessoryBonesToTargetAvatar;
result.skipFootFitting = this.skipFootFitting;
result.clothesHumanoidMatchedBones = this.clothesHumanoidMatchedBones;
result.clothBoneTypeMap = this.clothBoneTypeMap;
result.tagEdenMorpehrCloth = this.tagEdenMorpehrCloth;
result.transferWeightToAvatar = this.transferWeightToAvatar;
result.addAnchorBone = this.addAnchorBone;
result.armatureBoneScaleCopy = this.armatureBoneScaleCopy;
result.isRemoveAutoMorphedClothes = this.isRemoveAutoMorphedClothes;
return result;
}
public void AutoPoseSetup(MorpherMode morpherMode)
{
TransformInfo transformInfo = new TransformInfo(this.sourceAvatarObject.transform);
TransformInfo transformInfo2 = new TransformInfo(this.targetAvatarObject.transform);
try
{
EdenAutoMorpher_SetUpUtil edenAutoMorpher_SetUpUtil = new EdenAutoMorpher_SetUpUtil();
this.sourceBodyMeshesReadOnly = edenAutoMorpher_SetUpUtil.SetupBodyMeshes(this.sourceAvatarObject, this.isBodyAutoSetup, this.sourceBodyMeshes, "Source ").AsReadOnly();
this.targetBodyMeshesReadOnly = edenAutoMorpher_SetUpUtil.SetupBodyMeshes(this.targetAvatarObject, this.isBodyAutoSetup, this.targetBodyMeshes, "Target ").AsReadOnly();
this.targetAvatarObject.transform.SetParent(null, worldPositionStays: true);
this.targetAvatarObject.transform.localRotation = Quaternion.identity;
this.sourceAvatarObject.transform.SetParent(null, worldPositionStays: true);
this.sourceAvatarObject.transform.localRotation = Quaternion.identity;
EdenAutoMorpherConfig config = this.SetupConfigData(morpherMode);
new EdenAutoMorpher_SetUpUtil().AutoSetup(ref config, out this.clothesHumanoidMatchedBones, out this.clothBoneTypeMap);
this.targetClothesObject = config.targetClothesObject;
this.targetClothesObjectOriginal = this.targetClothesObject;
}
finally
{
transformInfo.ApplyToTransform(this.sourceAvatarObject.transform, applyParent: true, applyPosition: false, applyRotation: true, applyScale: true);
transformInfo2.ApplyToTransform(this.targetAvatarObject.transform, applyParent: true, applyPosition: false, applyRotation: true, applyScale: true);
}
}
public void ProfileSetup(MorpherMode morpherMode)
{
TransformInfo transformInfo = new TransformInfo(this.sourceClothesObject.transform);
TransformInfo transformInfo2 = new TransformInfo(this.targetAvatarObject.transform);
try
{
EdenAutoMorpher_SetUpUtil edenAutoMorpher_SetUpUtil = new EdenAutoMorpher_SetUpUtil();
this.targetBodyMeshesReadOnly = edenAutoMorpher_SetUpUtil.SetupBodyMeshes(this.targetAvatarObject, this.isBodyAutoSetup, this.targetBodyMeshes, "Target ").AsReadOnly();
this.targetAvatarObject.transform.SetParent(null, worldPositionStays: true);
this.targetAvatarObject.transform.localRotation = Quaternion.identity;
this.sourceClothesObject.transform.SetParent(null, worldPositionStays: true);
this.sourceClothesObject.transform.localScale = Vector3.one;
this.sourceClothesObject.transform.localRotation = Quaternion.identity;
EdenAutoMorpherConfig config = this.SetupConfigData(morpherMode);
new EdenAutoMorpher_SetUpUtil().ProfileAutoSetup(ref config, out this.clothesHumanoidMatchedBones, out this.clothBoneTypeMap);
this.targetClothesObject = config.targetClothesObject;
this.targetClothesObjectOriginal = this.targetClothesObject;
}
finally
{
transformInfo.ApplyToTransform(this.sourceClothesObject.transform, applyParent: true, applyPosition: false, applyRotation: true, applyScale: true);
transformInfo2.ApplyToTransform(this.targetAvatarObject.transform, applyParent: true, applyPosition: false, applyRotation: true, applyScale: true);
}
}
public IEnumerator AutoMorphingEnumerator(MorpherMode morpherMode)
{
this.doProcess = true;
yield return null;
this.ProcessInfoDebug(morpherMode, "Run ALL");
this.morpherState = MorpherState.Fitting_Doing;
IEnumerator fitEnum = null;
this.morpherMode = morpherMode;
yield return null;
Debug.Log("[Eden Auto Morpher] Run ALL - Start Fitting");
switch (morpherMode)
{
case MorpherMode.AutoMorpher:
fitEnum = this.AutoFitting(morpherMode);
break;
case MorpherMode.ManualMorpher:
fitEnum = this.ManualFitting(morpherMode);
break;
case MorpherMode.ProfileMorpher:
fitEnum = this.ProfileFitting(morpherMode);
break;
default:
Debug.LogError("Unknown Mode Index");
break;
}
while (fitEnum != null && fitEnum.MoveNext() && this.doProcess)
{
yield return fitEnum.Current;
}
this.morpherState = MorpherState.Fitting_End;
yield return null;
this.morpherState = MorpherState.Weighting_Doing;
yield return null;
Debug.Log("[Eden Auto Morpher] Run ALL - Start Weighting");
using (EdenAutoMorpherManager eamManager = new EdenAutoMorpherManager())
{
EdenAutoMorpherConfig config = this.SetupConfigData(morpherMode);
IEnumerator eamFitting = eamManager.WeightingEnumerator(config);
while (eamFitting.MoveNext() && this.doProcess)
{
var (title, text, progress) = eamManager.GetProgressInfo();
this.processInfo.title = title;
this.processInfo.text = text;
this.processInfo.progress = progress;
yield return eamFitting.Current;
}
}
yield return null;
this.doProcess = false;
this.morpherState = MorpherState.Idle;
Debug.Log("[Eden Auto Morpher] Ended Run ALL");
yield return null;
}
public IEnumerator FittingEnumerator(MorpherMode morpherMode)
{
this.doProcess = true;
this.processInfo.title = "Setup Avatar Pose";
this.processInfo.text = "Calculating avatar shape and skeletal data.";
this.processInfo.progress = 0f;
yield return null;
this.ProcessInfoDebug(morpherMode, "Fitting");
yield return null;
this.morpherState = MorpherState.Fitting_Doing;
IEnumerator fitEnum = null;
this.morpherMode = morpherMode;
yield return null;
switch (morpherMode)
{
case MorpherMode.AutoMorpher:
fitEnum = this.AutoFitting(morpherMode);
break;
case MorpherMode.ManualMorpher:
fitEnum = this.ManualFitting(morpherMode);
break;
case MorpherMode.ProfileMorpher:
fitEnum = this.ProfileFitting(morpherMode);
break;
default:
Debug.LogError("Unknown Mode Index");
break;
}
while (fitEnum != null && fitEnum.MoveNext() && this.doProcess)
{
yield return null;
}
this.morpherState = MorpherState.Fitting_End;
yield return null;
this.doProcess = false;
Debug.Log("[Eden Auto Morpher] Ended Fitting");
yield return null;
}
public IEnumerator WeightingEnumerator()
{
this.morpherState = MorpherState.Weighting_Doing;
this.doProcess = true;
yield return null;
this.ProcessInfoDebug(this.morpherMode, "Weighting");
using (EdenAutoMorpherManager eamManager = new EdenAutoMorpherManager())
{
EdenAutoMorpherConfig config = this.SetupConfigData(MorpherMode.ETC);
IEnumerator eamFitting = eamManager.WeightingEnumerator(config);
while (eamFitting.MoveNext() && this.doProcess)
{
var (title, text, progress) = eamManager.GetProgressInfo();
this.processInfo.title = title;
this.processInfo.text = text;
this.processInfo.progress = progress;
yield return eamFitting.Current;
}
}
yield return null;
this.doProcess = false;
this.morpherState = MorpherState.Idle;
Debug.Log("[Eden Auto Morpher] Ended Weighting");
yield return null;
}
public IEnumerator AutoFitting(MorpherMode morpherMode)
{
TransformInfo sourceAvatarInfo = new TransformInfo(this.sourceAvatarObject.transform);
TransformInfo targetAvatarInfo = new TransformInfo(this.targetAvatarObject.transform);
try
{
EdenAutoMorpher_SetUpUtil edenAutoMorpher_SetUpUtil = new EdenAutoMorpher_SetUpUtil();
this.sourceBodyMeshesReadOnly = edenAutoMorpher_SetUpUtil.SetupBodyMeshes(this.sourceAvatarObject, this.isBodyAutoSetup, this.sourceBodyMeshes, "Source ").AsReadOnly();
this.targetBodyMeshesReadOnly = edenAutoMorpher_SetUpUtil.SetupBodyMeshes(this.targetAvatarObject, this.isBodyAutoSetup, this.targetBodyMeshes, "Target ").AsReadOnly();
this.targetAvatarObject.transform.SetParent(null, worldPositionStays: true);
this.targetAvatarObject.transform.localRotation = Quaternion.identity;
this.sourceAvatarObject.transform.SetParent(null, worldPositionStays: true);
this.sourceAvatarObject.transform.localRotation = Quaternion.identity;
EdenAutoMorpherConfig configData = this.SetupConfigData(morpherMode);
new EdenAutoMorpher_SetUpUtil().AutoSetup(ref configData, out this.clothesHumanoidMatchedBones, out this.clothBoneTypeMap);
this.targetClothesObject = configData.targetClothesObject;
this.targetClothesObjectOriginal = this.targetClothesObject;
yield return null;
this.fittedTargetAvatar = null;
this.fittedTargetClothes = null;
yield return null;
configData = this.SetupConfigData(morpherMode);
using (EdenAutoMorpherManager eamManager = new EdenAutoMorpherManager())
{
IEnumerator eamFitting = eamManager.FittingIteration(configData, morpherMode);
while (eamFitting.MoveNext() && this.doProcess)
{
var (title, text, progress) = eamManager.GetProgressInfo();
this.processInfo.title = title;
this.processInfo.text = text;
this.processInfo.progress = progress;
yield return eamFitting.Current;
}
}
this.fittedTargetAvatar = configData.targetAvatarObject;
this.fittedTargetClothes = configData.targetClothesObject;
}
finally
{
EdenAutoMorpher edenAutoMorpher = this;
sourceAvatarInfo.ApplyToTransform(edenAutoMorpher.sourceAvatarObject.transform, applyParent: true, applyPosition: false, applyRotation: true, applyScale: true);
targetAvatarInfo.ApplyToTransform(edenAutoMorpher.targetAvatarObject.transform, applyParent: true, applyPosition: false, applyRotation: true, applyScale: true);
}
yield return null;
}
public IEnumerator ManualFitting(MorpherMode morpherMode)
{
TransformInfo sourceAvatarInfo = new TransformInfo(this.sourceAvatarObject.transform);
TransformInfo targetAvatarInfo = new TransformInfo(this.targetAvatarObject.transform);
try
{
EdenAutoMorpher_SetUpUtil edenAutoMorpher_SetUpUtil = new EdenAutoMorpher_SetUpUtil();
this.sourceBodyMeshesReadOnly = edenAutoMorpher_SetUpUtil.SetupBodyMeshes(this.sourceAvatarObject, this.isBodyAutoSetup, this.sourceBodyMeshes, "Source ").AsReadOnly();
this.targetBodyMeshesReadOnly = edenAutoMorpher_SetUpUtil.SetupBodyMeshes(this.targetAvatarObject, this.isBodyAutoSetup, this.targetBodyMeshes, "Target ").AsReadOnly();
this.targetClothesObject = this.targetClothesObjectOriginal;
EdenAutoMorpherConfig configData = this.SetupConfigData(morpherMode);
new EdenAutoMorpher_SetUpUtil().ManulSetup(ref configData, out this.clothesHumanoidMatchedBones, out this.clothBoneTypeMap);
yield return null;
this.fittedTargetAvatar = null;
this.fittedTargetClothes = null;
configData = this.SetupConfigData(morpherMode);
using (EdenAutoMorpherManager eamManager = new EdenAutoMorpherManager())
{
IEnumerator eamFitting = eamManager.FittingIteration(configData, morpherMode);
while (eamFitting.MoveNext() && this.doProcess)
{
var (title, text, progress) = eamManager.GetProgressInfo();
this.processInfo.title = title;
this.processInfo.text = text;
this.processInfo.progress = progress;
yield return eamFitting.Current;
}
}
this.fittedTargetAvatar = configData.targetAvatarObject;
this.fittedTargetClothes = configData.targetClothesObject;
}
finally
{
EdenAutoMorpher edenAutoMorpher = this;
sourceAvatarInfo.ApplyToTransform(edenAutoMorpher.sourceAvatarObject.transform, applyParent: true, applyPosition: false, applyRotation: true, applyScale: true);
targetAvatarInfo.ApplyToTransform(edenAutoMorpher.targetAvatarObject.transform, applyParent: true, applyPosition: false, applyRotation: true, applyScale: true);
}
yield return null;
}
public IEnumerator ProfileFitting(MorpherMode morpherMode)
{
TransformInfo sourceClothesInfo = new TransformInfo(this.sourceClothesObject.transform);
TransformInfo targetAvatarInfo = new TransformInfo(this.targetAvatarObject.transform);
try
{
EdenAutoMorpher_SetUpUtil edenAutoMorpher_SetUpUtil = new EdenAutoMorpher_SetUpUtil();
this.targetBodyMeshesReadOnly = edenAutoMorpher_SetUpUtil.SetupBodyMeshes(this.targetAvatarObject, this.isBodyAutoSetup, this.targetBodyMeshes, "Target ").AsReadOnly();
this.targetAvatarObject.transform.SetParent(null, worldPositionStays: true);
this.targetAvatarObject.transform.localRotation = Quaternion.identity;
this.sourceClothesObject.transform.SetParent(null, worldPositionStays: true);
this.sourceClothesObject.transform.localScale = Vector3.one;
this.sourceClothesObject.transform.localRotation = Quaternion.identity;
EdenAutoMorpherConfig configData = this.SetupConfigData(morpherMode);
new EdenAutoMorpher_SetUpUtil().ProfileAutoSetup(ref configData, out this.clothesHumanoidMatchedBones, out this.clothBoneTypeMap);
this.targetClothesObject = configData.targetClothesObject;
this.targetClothesObjectOriginal = this.targetClothesObject;
yield return null;
this.fittedTargetAvatar = null;
this.fittedTargetClothes = null;
yield return null;
configData = this.SetupConfigData(morpherMode);
using (EdenAutoMorpherManager eamManager = new EdenAutoMorpherManager())
{
IEnumerator eamFitting = eamManager.FittingIteration(configData, morpherMode);
while (eamFitting.MoveNext() && this.doProcess)
{
var (title, text, progress) = eamManager.GetProgressInfo();
this.processInfo.title = title;
this.processInfo.text = text;
this.processInfo.progress = progress;
yield return eamFitting.Current;
}
}
this.fittedTargetAvatar = configData.targetAvatarObject;
this.fittedTargetClothes = configData.targetClothesObject;
yield return null;
}
finally
{
EdenAutoMorpher edenAutoMorpher = this;
sourceClothesInfo.ApplyToTransform(edenAutoMorpher.sourceClothesObject.transform, applyParent: true, applyPosition: false, applyRotation: true, applyScale: true);
targetAvatarInfo.ApplyToTransform(edenAutoMorpher.targetAvatarObject.transform, applyParent: true, applyPosition: false, applyRotation: true, applyScale: true);
}
}
public bool IsWeightingReady(bool isAutoMode)
{
bool flag = this.morpherState == MorpherState.Fitting_End && this.fittedTargetAvatar != null && this.fittedTargetAvatar == this.targetAvatarObject;
if (!isAutoMode)
{
flag = flag && this.fittedTargetClothes == this.targetClothesObjectOriginal;
}
return flag;
}
private void ProcessInfoDebug(MorpherMode morpherMode, string processType)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine($"Start Process [{processType} / {morpherMode}]");
EdenAutoMorpherConfig edenAutoMorpherConfig = this.SetupConfigData(morpherMode);
string text = ((edenAutoMorpherConfig.sourceAvatarObject != null) ? edenAutoMorpherConfig.sourceAvatarObject.name : "null");
string text2 = ((edenAutoMorpherConfig.sourceClothesObject != null) ? edenAutoMorpherConfig.sourceClothesObject.name : "null");
string text3 = ((edenAutoMorpherConfig.targetAvatarObject != null) ? edenAutoMorpherConfig.targetAvatarObject.name : "null");
string text4 = ((edenAutoMorpherConfig.targetClothesObject != null) ? edenAutoMorpherConfig.targetClothesObject.name : "null");
stringBuilder.AppendLine("[Objects]");
if (morpherMode == MorpherMode.ProfileMorpher)
{
stringBuilder.AppendLine("- profileName: " + (string.IsNullOrEmpty(edenAutoMorpherConfig.profileName) ? "null/empty" : edenAutoMorpherConfig.profileName));
}
stringBuilder.AppendLine("- sourceAvatarObject: " + text);
stringBuilder.AppendLine("- sourceClothesObject: " + text2);
if (edenAutoMorpherConfig.sourceClothesObject != null)
{
SkinnedMeshRenderer[] componentsInChildren = edenAutoMorpherConfig.sourceClothesObject.GetComponentsInChildren<SkinnedMeshRenderer>(includeInactive: true);
stringBuilder.AppendLine($" - sourceClothes SkinnedMeshRenderers Count: {componentsInChildren.Length}");
int num = Mathf.Min(componentsInChildren.Length, 10);
for (int i = 0; i < num; i++)
{
SkinnedMeshRenderer skinnedMeshRenderer = componentsInChildren[i];
string text5 = ((skinnedMeshRenderer != null) ? skinnedMeshRenderer.name : "null");
string text6 = ((skinnedMeshRenderer != null && skinnedMeshRenderer.rootBone != null) ? skinnedMeshRenderer.rootBone.name : "null");
string text7 = ((skinnedMeshRenderer != null && skinnedMeshRenderer.sharedMesh != null) ? skinnedMeshRenderer.sharedMesh.name : "null");
stringBuilder.AppendLine($" - [{i}] SMR: {text5} / rootBone: {text6} / mesh: {text7}");
}
if (componentsInChildren.Length > num)
{
stringBuilder.AppendLine($" - ... ({componentsInChildren.Length - num} more)");
}
}
stringBuilder.AppendLine("- targetAvatarObject: " + text3);
stringBuilder.AppendLine("- targetClothesObject: " + text4);
if (edenAutoMorpherConfig.targetClothesObject != null)
{
SkinnedMeshRenderer[] componentsInChildren2 = edenAutoMorpherConfig.targetClothesObject.GetComponentsInChildren<SkinnedMeshRenderer>(includeInactive: true);
stringBuilder.AppendLine($" - targetClothes SkinnedMeshRenderers Count: {componentsInChildren2.Length}");
int num2 = Mathf.Min(componentsInChildren2.Length, 10);
for (int j = 0; j < num2; j++)
{
SkinnedMeshRenderer skinnedMeshRenderer2 = componentsInChildren2[j];
string text8 = ((skinnedMeshRenderer2 != null) ? skinnedMeshRenderer2.name : "null");
string text9 = ((skinnedMeshRenderer2 != null && skinnedMeshRenderer2.rootBone != null) ? skinnedMeshRenderer2.rootBone.name : "null");
string text10 = ((skinnedMeshRenderer2 != null && skinnedMeshRenderer2.sharedMesh != null) ? skinnedMeshRenderer2.sharedMesh.name : "null");
stringBuilder.AppendLine($" - [{j}] SMR: {text8} / rootBone: {text9} / mesh: {text10}");
}
if (componentsInChildren2.Length > num2)
{
stringBuilder.AppendLine($" - ... ({componentsInChildren2.Length - num2} more)");
}
}
stringBuilder.AppendLine();
stringBuilder.AppendLine("[Body Meshes]");
stringBuilder.AppendLine($"- isBodyAutoSetup: {edenAutoMorpherConfig.isBodyAutoSetup}");
if (!edenAutoMorpherConfig.isBodyAutoSetup)
{
if (edenAutoMorpherConfig.sourceBodyMeshes == null)
{
stringBuilder.AppendLine("- sourceBodyMeshes: null");
}
else
{
stringBuilder.AppendLine($"- sourceBodyMeshes Count: {this.sourceBodyMeshes.Count}");
for (int k = 0; k < this.sourceBodyMeshes.Count; k++)
{
SkinnedMeshRenderer skinnedMeshRenderer3 = this.sourceBodyMeshes[k];
string text11 = ((skinnedMeshRenderer3 != null) ? skinnedMeshRenderer3.name : "null");
string text12 = ((skinnedMeshRenderer3 != null && skinnedMeshRenderer3.rootBone != null) ? skinnedMeshRenderer3.rootBone.name : "null");
string text13 = ((skinnedMeshRenderer3 != null && skinnedMeshRenderer3.sharedMesh != null) ? skinnedMeshRenderer3.sharedMesh.name : "null");
stringBuilder.AppendLine($" - [{k}] SMR: {text11} / rootBone: {text12} / mesh: {text13}");
}
}
if (this.targetBodyMeshes == null)
{
stringBuilder.AppendLine("- targetBodyMeshes: null");
}
else
{
stringBuilder.AppendLine($"- targetBodyMeshes Count: {this.targetBodyMeshes.Count}");
for (int l = 0; l < this.targetBodyMeshes.Count; l++)
{
SkinnedMeshRenderer skinnedMeshRenderer4 = this.targetBodyMeshes[l];
string text14 = ((skinnedMeshRenderer4 != null) ? skinnedMeshRenderer4.name : "null");
string text15 = ((skinnedMeshRenderer4 != null && skinnedMeshRenderer4.rootBone != null) ? skinnedMeshRenderer4.rootBone.name : "null");
string text16 = ((skinnedMeshRenderer4 != null && skinnedMeshRenderer4.sharedMesh != null) ? skinnedMeshRenderer4.sharedMesh.name : "null");
stringBuilder.AppendLine($" - [{l}] SMR: {text14} / rootBone: {text15} / mesh: {text16}");
}
}
}
stringBuilder.AppendLine();
stringBuilder.AppendLine("[Parameters]");
stringBuilder.AppendLine($"- minMargin: {edenAutoMorpherConfig.minMargin}");
stringBuilder.AppendLine($"- worldRadius: {edenAutoMorpherConfig.worldRadius}");
stringBuilder.AppendLine($"- sigma: {edenAutoMorpherConfig.sigma}");
stringBuilder.AppendLine($"- smoothingIteration: {edenAutoMorpherConfig.smoothingIteration}");
stringBuilder.AppendLine($"- fittingExpandIteration: {edenAutoMorpherConfig.fittingExpandIteration}");
stringBuilder.AppendLine($"- fittingShrinkIteration: {edenAutoMorpherConfig.fittingShrinkIteration}");
stringBuilder.AppendLine();
stringBuilder.AppendLine("[Options]");
stringBuilder.AppendLine($"- isReparentAccessoryBonesToTargetAvatar: {edenAutoMorpherConfig.isReparentAccessoryBonesToTargetAvatar}");
stringBuilder.AppendLine($"- skipFootFitting: {edenAutoMorpherConfig.skipFootFitting}");
Debug.Log(stringBuilder.ToString());
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 50552370e41d31140a52da99bcc7ab74

View File

@@ -0,0 +1,55 @@
// 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.EdenAutoMorpherConfig
using System.Collections.Generic;
using UnityEngine;
public struct EdenAutoMorpherConfig
{
public GameObject sourceAvatarObject;
public GameObject sourceClothesObject;
public IReadOnlyList<SkinnedMeshRenderer> sourceBodyMeshes;
public GameObject targetAvatarObject;
public GameObject targetClothesObject;
public IReadOnlyList<SkinnedMeshRenderer> targetBodyMeshes;
public string profileName;
public float minMargin;
public float worldRadius;
public float sigma;
public int smoothingIteration;
public int fittingExpandIteration;
public int fittingShrinkIteration;
public bool isBodyAutoSetup;
public bool isReparentAccessoryBonesToTargetAvatar;
public bool skipFootFitting;
public bool isRemoveAutoMorphedClothes;
public bool transferWeightToAvatar;
public bool addAnchorBone;
public bool armatureBoneScaleCopy;
public Dictionary<HumanBodyBones, HashSet<Transform>> clothesHumanoidMatchedBones;
public Dictionary<Transform, ClothBoneType> clothBoneTypeMap;
public string tagEdenMorpehrCloth;
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 36c114e39fc870440b90581fce2b9b1c

View File

@@ -0,0 +1,395 @@
// 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.EdenAutoMorpherManager
using Eden.AutoMorpher;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
public class EdenAutoMorpherManager : IDisposable
{
private string displayTitle;
private string displayText;
private float displayProgress;
private List<ClothInstance> clothInstances;
public (string, string, float) GetProgressInfo()
{
return (this.displayTitle, this.displayText, this.displayProgress);
}
private void SetupProgress(string title, string text, float progress)
{
this.displayTitle = title;
this.displayText = text;
this.displayProgress = progress;
}
private IEnumerator SetupClothInstances(GameObject targetClothesObject, Dictionary<HumanBodyBones, HashSet<Transform>> clothesHumanoidMatchedBones, bool duplicateMesh = true)
{
this.clothInstances = new List<ClothInstance>();
SkinnedMeshRenderer[] targetClothesSMRs = targetClothesObject.GetComponentsInChildren<SkinnedMeshRenderer>(includeInactive: false);
if (targetClothesSMRs.Length == 0)
{
throw new AutoMorpherException("There is NO Skinned Mesh Renderer in Clothes", "[EdenAutoMorpherManager] SetupClothInstance\n - There is NO Skinned Mesh Renderer in Clothes");
}
EdenAutoMorpher_SetUpUtil setupUtil = new EdenAutoMorpher_SetUpUtil();
for (int rendereri = 0; rendereri < targetClothesSMRs.Length; rendereri++)
{
this.SetupProgress("Set Up", $"Setup Clothes Info [{rendereri}/{targetClothesSMRs.Length}] - ({targetClothesSMRs[rendereri].name})", Mathf.Lerp(0.05f, 0.1f, rendereri / targetClothesSMRs.Length));
yield return null;
ClothInstance clothInstance = setupUtil.SetupClothInstance(targetClothesSMRs[rendereri], clothesHumanoidMatchedBones, duplicateMesh);
if (clothInstance != null)
{
this.clothInstances.Add(clothInstance);
}
}
if (this.clothInstances.Count == 0)
{
throw new AutoMorpherException(LanguageManager.Get("UI.Exception.title.ClothInstanceAllocateFail"), LanguageManager.Get("UI.Exception.message.ClothInstanceAllocateFail"));
}
}
private IEnumerator SetupClothInstances(GameObject targetClothesObject, Dictionary<HumanBodyBones, HashSet<Transform>> clothesHumanoidMatchedBones, GameObject sourceClothesObject, MeshMatcher meshMatcher)
{
this.clothInstances = new List<ClothInstance>();
SkinnedMeshRenderer[] targetClothesSMRs = targetClothesObject.GetComponentsInChildren<SkinnedMeshRenderer>(includeInactive: false);
if (targetClothesSMRs.Length == 0)
{
throw new AutoMorpherException("There is NO Skinned Mesh Renderer in Clothes", "[EdenAutoMorpherManager] SetupClothInstance\n - There is NO Skinned Mesh Renderer in Clothes");
}
SkinnedMeshRenderer[] sourceClothesSMRs = sourceClothesObject.GetComponentsInChildren<SkinnedMeshRenderer>(includeInactive: false);
if (sourceClothesSMRs.Length == 0 || targetClothesSMRs.Length != sourceClothesSMRs.Length)
{
throw new AutoMorpherException("Clothes Skinned Mesh Renderer is Not Matched", "[EdenAutoMorpherManager] SetupClothInstance\n - Skinned Mesh Renderer of Source Clothes and Target Clothes is Not Matched");
}
EdenAutoMorpher_SetUpUtil setupUtil = new EdenAutoMorpher_SetUpUtil();
for (int rendereri = 0; rendereri < targetClothesSMRs.Length; rendereri++)
{
this.SetupProgress("Set Up", $"Setup Clothes Info [{rendereri}/{targetClothesSMRs.Length}] - ({targetClothesSMRs[rendereri].name})", Mathf.Lerp(0.07f, 0.1f, rendereri / targetClothesSMRs.Length));
yield return null;
ClothInstance clothInstance = setupUtil.SetupClothInstance(targetClothesSMRs[rendereri], sourceClothesSMRs[rendereri], meshMatcher, clothesHumanoidMatchedBones, duplicateMesh: true);
if (clothInstance != null)
{
this.clothInstances.Add(clothInstance);
}
}
if (this.clothInstances.Count == 0)
{
throw new AutoMorpherException(LanguageManager.Get("UI.Exception.title.ClothInstanceAllocateFail"), LanguageManager.Get("UI.Exception.message.ClothInstanceAllocateFail"));
}
}
public IEnumerator FittingIteration(EdenAutoMorpherConfig config, MorpherMode morpherMode)
{
this.SetupProgress("Set Up", "Setup Target Avatar Info", 0.03f);
yield return null;
MeshMatcher meshMatcher = new MeshMatcher();
BvhTriangleMesh targetBodyBVH = meshMatcher.BuildBvhMulti(config.targetBodyMeshes, config.targetAvatarObject.GetComponent<Animator>());
if (targetBodyBVH == null)
{
throw new AutoMorpherException("targetBodyBVH is Null", "[EdenAutoMorpherManater] FittingIteration\n - targetBodyBVH is null");
}
yield return null;
this.SetupProgress("Set Up", "Setup Source Avatar Info", 0.05f);
yield return null;
BvhTriangleMesh sourceBodyBVH = null;
switch (morpherMode)
{
case MorpherMode.AutoMorpher:
case MorpherMode.ManualMorpher:
sourceBodyBVH = meshMatcher.BuildBvhMulti(config.sourceBodyMeshes, config.sourceAvatarObject.GetComponent<Animator>());
break;
case MorpherMode.ProfileMorpher:
{
ProfileLoader profileLoader = new ProfileLoader();
sourceBodyBVH = profileLoader.LoadBvhWithRootTransform(config.sourceClothesObject.transform, config.profileName);
break;
}
default:
Debug.LogError("Unknown MorpherMode");
break;
}
yield return null;
if (sourceBodyBVH == null)
{
throw new AutoMorpherException("sourceBodyBVH is Null", "[EdenAutoMorpherManater] FittingIteration\n - sourceBodyBVH is null");
}
meshMatcher.bodyBVH = sourceBodyBVH;
this.SetupProgress("Set Up", "Setup Clothes Info", 0.07f);
yield return null;
IEnumerator setupClothEnum = this.SetupClothInstances(config.targetClothesObject, config.clothesHumanoidMatchedBones, config.sourceClothesObject, meshMatcher);
while (setupClothEnum.MoveNext())
{
yield return setupClothEnum.Current;
}
yield return null;
float fittingRadius = config.worldRadius;
meshMatcher.bodyBVH = targetBodyBVH;
VertexFittingUtil vertexFittingUtil = new VertexFittingUtil();
int fittingI;
for (fittingI = 0; fittingI < config.fittingExpandIteration; fittingI++)
{
foreach (ClothInstance clothInstance in this.clothInstances)
{
this.SetupProgress("Fitting", $"Phase 1 Expanding [{fittingI + 1}/{config.fittingExpandIteration}] - {clothInstance.smr.transform.name}", Mathf.Lerp(0.1f, 0.4f, (float)fittingI / (float)config.fittingExpandIteration));
yield return null;
vertexFittingUtil.ExpandClothes_World(clothInstance, this.clothInstances, meshMatcher, config, fittingRadius);
yield return null;
}
if (fittingI % 2 == 0)
{
fittingRadius *= 0.97f;
}
}
fittingRadius = config.worldRadius;
for (fittingI = 0; fittingI < config.fittingShrinkIteration; fittingI++)
{
foreach (ClothInstance clothInstance in this.clothInstances)
{
this.SetupProgress("Fitting", $"Phase 2 Fitting [{fittingI + 1}/{config.fittingShrinkIteration}] - {clothInstance.smr.transform.name}", Mathf.Lerp(0.4f, 0.8f, (float)fittingI / (float)config.fittingShrinkIteration));
yield return null;
vertexFittingUtil.ShrinkClothes_World(clothInstance, this.clothInstances, meshMatcher, config, fittingRadius);
yield return null;
vertexFittingUtil.ExpandClothes_World(clothInstance, this.clothInstances, meshMatcher, config, fittingRadius);
yield return null;
}
if (fittingI % 2 == 0)
{
fittingRadius *= 0.97f;
}
}
fittingRadius = config.worldRadius / 2f;
for (fittingI = 0; fittingI < config.fittingExpandIteration; fittingI++)
{
foreach (ClothInstance clothInstance in this.clothInstances)
{
this.SetupProgress("Fitting", $"Phase 3 Fine-tuning [{fittingI + 1}/{config.fittingExpandIteration}] - {clothInstance.smr.transform.name}", Mathf.Lerp(0.8f, 0.9f, (float)fittingI / (float)config.fittingExpandIteration));
yield return null;
vertexFittingUtil.ExpandClothes_World(clothInstance, this.clothInstances, meshMatcher, config, fittingRadius);
yield return null;
}
if (fittingI % 2 == 0)
{
fittingRadius *= 0.97f;
}
}
yield return null;
this.SetupProgress("Fitting", "Apply Transform Bone", 0.93f);
yield return null;
BoneAlignmentUtil boneAlignmentUtil = new BoneAlignmentUtil();
boneAlignmentUtil.CleanupTempBones(config.targetClothesObject.transform);
MorpherMode morpherMode2 = morpherMode;
if (morpherMode2 == MorpherMode.AutoMorpher || morpherMode2 == MorpherMode.ProfileMorpher)
{
config.targetClothesObject.transform.localScale = Vector3.one;
boneAlignmentUtil.AlignClothBonesToAvatar(this.clothInstances[0], config.targetAvatarObject.GetComponent<Animator>());
}
yield return null;
this.SetupProgress("Fitting", "Apply Transform Mesh", 0.99f);
yield return null;
fittingI = 0;
while (fittingI < this.clothInstances.Count)
{
ClothInstance clothInstance = this.clothInstances[fittingI];
this.SetupProgress("Fitting", $"Apply to Mesh [{fittingI + 1}/{this.clothInstances.Count}] - {clothInstance.smr.transform.name}", Mathf.Lerp(0.93f, 0.98f, (float)fittingI / (float)this.clothInstances.Count));
yield return null;
clothInstance.ApplyWorldVerticesToMesh();
clothInstance.smr.localBounds = new Bounds(Vector3.zero, Vector3.one * 2f);
EditorUtility.SetDirty(clothInstance.smr.sharedMesh);
EditorUtility.SetDirty(clothInstance.smr);
yield return null;
int num = fittingI + 1;
fittingI = num;
}
yield return null;
this.SetupProgress("Saving", "Saving Mesh Data", 0.99f);
yield return null;
this.SaveEditedMeshesToAssets(this.clothInstances, config);
yield return null;
this.SetupProgress("Finishing", "Finishing", 1f);
foreach (ClothInstance clothInstance2 in this.clothInstances)
{
clothInstance2.Dispose();
}
this.clothInstances = null;
yield return null;
}
public IEnumerator WeightingEnumerator(EdenAutoMorpherConfig config)
{
this.SetupProgress("Set Up", "Setup Target Avatar Info", 0f);
yield return null;
if (new MeshMatcher().BuildBvhMulti(config.targetBodyMeshes, config.targetAvatarObject.GetComponent<Animator>()) == null)
{
throw new AutoMorpherException("targetBodyBVH is Null", "[EdenAutoMorpherManater] FittingIteration\n - targetBodyBVH is null");
}
yield return null;
List<Mesh> bakedTargetBodyMeshes = new List<Mesh>();
foreach (SkinnedMeshRenderer bodyMesh in config.targetBodyMeshes)
{
this.SetupProgress("Set Up", "Setup Target Avatar BodyMesh Info", Mathf.Lerp(0.02f, 0.05f, bakedTargetBodyMeshes.Count / config.targetBodyMeshes.Count));
yield return null;
Mesh mesh = new Mesh();
bodyMesh.BakeMesh(mesh);
mesh.triangles = bodyMesh.sharedMesh.triangles;
mesh.boneWeights = bodyMesh.sharedMesh.boneWeights;
bakedTargetBodyMeshes.Add(mesh);
}
yield return null;
IEnumerator setupClothEnum = this.SetupClothInstances(config.targetClothesObject, config.clothesHumanoidMatchedBones, duplicateMesh: false);
while (setupClothEnum.MoveNext())
{
yield return setupClothEnum.Current;
}
yield return null;
Dictionary<Transform, Transform> clonedBoneMap = null;
if (!config.transferWeightToAvatar)
{
new EdenAutoMorpher_SetUpUtil().CreateClothesArmature(config, out clonedBoneMap);
}
yield return null;
WeightTransferUtil weightTransferUtil = new WeightTransferUtil();
WeightTransferUtil.Settings wtSettings = new WeightTransferUtil.Settings
{
maxDistance = 0.07f,
maxNormalAngleDeg = 35f,
allowFlippedNormal = true,
enableSmoothing = true,
smoothingIterations = 4,
smoothingAlpha = 0.25f,
enforceFourBoneLimit = true,
weightInClothes = !config.transferWeightToAvatar
};
yield return null;
int weightingI = 0;
while (weightingI < this.clothInstances.Count)
{
ClothInstance clothInstance = this.clothInstances[weightingI];
float num = 0.1f;
float num2 = (0.95f - num) / (float)Mathf.Max(1, this.clothInstances.Count);
float num3 = num + num2 * (float)weightingI;
float num4 = 0.8f;
float weightingStart = num3;
float weightingEnd = num3 + num2 * num4;
float applyStart = num3 + num2 * num4;
int step = 1;
this.SetupProgress("Weighting", $"Weighting | Step {step} [{weightingI + 1}/{this.clothInstances.Count}] - {clothInstance.smr.transform.name}", weightingStart);
yield return null;
IEnumerator weightingEnum = weightTransferUtil.RetargetAndTransfer(clothInstance, config.targetAvatarObject.GetComponent<Animator>(), config.targetBodyMeshes, bakedTargetBodyMeshes, 0, wtSettings, config.clothBoneTypeMap, clonedBoneMap);
while (weightingEnum.MoveNext())
{
yield return null;
step++;
float t = 1f - 1f / ((float)step + 1f);
float progress = Mathf.Lerp(weightingStart, weightingEnd, t);
this.SetupProgress("Weighting", $"Weighting | Step {step} [{weightingI + 1}/{this.clothInstances.Count}] - {clothInstance.smr.transform.name}", progress);
yield return weightingEnum.Current;
}
yield return null;
step++;
this.SetupProgress("Weighting", $"Weighting | Step {step} - Apply to Mesh [{weightingI + 1}/{this.clothInstances.Count}] - {clothInstance.smr.transform.name}", applyStart);
yield return null;
clothInstance.ApplyWorldVerticesToMesh();
clothInstance.smr.localBounds = new Bounds(Vector3.zero, Vector3.one * 2f);
EditorUtility.SetDirty(clothInstance.smr.sharedMesh);
EditorUtility.SetDirty(clothInstance.smr);
yield return null;
int num5 = weightingI + 1;
weightingI = num5;
}
this.SetupProgress("Weighting", "Allocate Bones", 0.95f);
yield return null;
if (config.transferWeightToAvatar && config.isReparentAccessoryBonesToTargetAvatar)
{
new BoneAlignmentUtil().ReparentAccessoryBonesToAvatar(config);
}
this.SetupProgress("Finishing", "Finishing", 1f);
yield return null;
foreach (ClothInstance clothInstance2 in this.clothInstances)
{
clothInstance2.Dispose();
}
this.clothInstances = null;
yield return null;
}
private void SaveEditedMeshesToAssets(List<ClothInstance> clothInstances, EdenAutoMorpherConfig config)
{
if (clothInstances == null || clothInstances.Count == 0)
{
Debug.LogWarning("[EdenAutoMorpher] 저장할 ClothInstance가 없습니다.");
throw new AutoMorpherException("Can't Save Mesh", "Therer is no ClothInstance to save mesh");
}
if (config.targetClothesObject == null || config.targetAvatarObject == null)
{
Debug.LogWarning("[EdenAutoMorpher] targetClothesObject 또는 targetAvatarObject 가 null 입니다. 메쉬 저장 경로를 만들 수 없습니다.");
throw new AutoMorpherException("Can't Save Mesh", "Target Clothes Object or Target Avatar Object is null.\nCan't Create Mesh Folder");
}
string text = "Assets/@Eden_Mesh";
if (!AssetDatabase.IsValidFolder(text))
{
AssetDatabase.CreateFolder("Assets", "@Eden_Mesh");
}
string text2 = SanitizeForAssetName(config.targetAvatarObject.name);
string text3 = text + "/" + text2;
if (!AssetDatabase.IsValidFolder(text3))
{
AssetDatabase.CreateFolder(text, text2);
}
string text4 = SanitizeForAssetName(config.targetClothesObject.name);
string text5 = text3 + "/" + text4;
if (!AssetDatabase.IsValidFolder(text5))
{
AssetDatabase.CreateFolder(text3, text4);
}
string text6 = AssetDatabase.GenerateUniqueAssetPath(text5 + "/" + text4 + "_Meshes.asset");
int num = 0;
AssetDatabase.CreateAsset(new Mesh
{
name = text4 + "_RootMesh"
}, text6);
foreach (ClothInstance clothInstance in clothInstances)
{
if (clothInstance != null && !(clothInstance.smr == null))
{
Mesh sharedMesh = clothInstance.smr.sharedMesh;
if (!(sharedMesh == null))
{
Mesh mesh = UnityEngine.Object.Instantiate(sharedMesh);
mesh.name = SanitizeForAssetName(clothInstance.smr.gameObject.name + "_EditedMesh");
AssetDatabase.AddObjectToAsset(mesh, text6);
clothInstance.smr.sharedMesh = mesh;
clothInstance.editableMesh = clothInstance.smr.sharedMesh;
EditorUtility.SetDirty(clothInstance.smr);
EditorUtility.SetDirty(clothInstance.smr.sharedMesh);
EditorUtility.SetDirty(clothInstance.smr.gameObject);
num++;
}
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Debug.Log($"[EdenAutoMorpher] 편집된 메쉬 {num}개를 " + "'" + text6 + "' 에 서브 에셋으로 저장했습니다. (원본 프리팹은 변경하지 않음)");
static string SanitizeForAssetName(string rawName)
{
char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
foreach (char oldChar in invalidFileNameChars)
{
rawName = rawName.Replace(oldChar, '_');
}
return rawName.Trim();
}
}
public void Dispose()
{
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: a0a53153b37b0594c8d32b305724f9b9

View File

@@ -0,0 +1,675 @@
// 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.EdenAutoMorpher_SetUpUtil
using Eden.AutoMorpher;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
public class EdenAutoMorpher_SetUpUtil
{
public GameObject InstantiateTargetClothes(GameObject sourceClothesObject, GameObject targetAvatarObject, string tagEdenMorpherCloth, bool removeAutoMorphedClothes)
{
EnsureTagExists(tagEdenMorpherCloth);
if (removeAutoMorphedClothes)
{
List<GameObject> list = new List<GameObject>();
Transform[] componentsInChildren = targetAvatarObject.GetComponentsInChildren<Transform>(includeInactive: true);
foreach (Transform transform in componentsInChildren)
{
if (!(transform.gameObject == targetAvatarObject) && transform.CompareTag(tagEdenMorpherCloth))
{
list.Add(transform.gameObject);
}
}
foreach (GameObject item in list)
{
UnityEngine.Object.DestroyImmediate(item);
}
}
GameObject gameObject = UnityEngine.Object.Instantiate(sourceClothesObject, targetAvatarObject.transform);
gameObject.SetActive(value: true);
gameObject.transform.localPosition = Vector3.zero;
gameObject.transform.localRotation = Quaternion.identity;
gameObject.transform.localScale = Vector3.one;
gameObject.tag = tagEdenMorpherCloth;
return gameObject;
}
private static void EnsureTagExists(string tag)
{
if (string.IsNullOrEmpty(tag))
{
throw new AutoMorpherException("Clothes Tag is Invalid", "[EdenAutoMorpherManager] EnsureTagExists\n - tagEdenMorpherCloth is null or empty");
}
string[] tags = InternalEditorUtility.tags;
for (int i = 0; i < tags.Length; i++)
{
if (tags[i] == tag)
{
return;
}
}
SerializedObject serializedObject = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]);
SerializedProperty serializedProperty = serializedObject.FindProperty("tags");
int arraySize = serializedProperty.arraySize;
serializedProperty.InsertArrayElementAtIndex(arraySize);
serializedProperty.GetArrayElementAtIndex(arraySize).stringValue = tag;
serializedObject.ApplyModifiedProperties();
}
public void AutoSetup(ref EdenAutoMorpherConfig config, out Dictionary<HumanBodyBones, HashSet<Transform>> clothesHumanoidMatchedBones, out Dictionary<Transform, ClothBoneType> clothBoneTypeMap)
{
config.targetClothesObject = this.InstantiateTargetClothes(config.sourceClothesObject, config.targetAvatarObject, config.tagEdenMorpehrCloth, config.isRemoveAutoMorphedClothes);
if (config.targetClothesObject == null)
{
throw new AutoMorpherException("Target Clothes Object is Null", "[EdenAutoMorpher_SetUpUtil] AutoSetup\n - config.targetClothesObject is null");
}
BoneMatchUtil boneMatchUtil = new BoneMatchUtil();
List<BoneMatchUtil.BoneRootLocalData> bodyRootLocalBones = boneMatchUtil.GetBodyRootLocalBones(config.sourceAvatarObject.transform, config.sourceAvatarObject.GetComponent<Animator>(), config.sourceBodyMeshes.ToList());
List<BoneMatchUtil.BoneRootLocalData> rootLocalBones = boneMatchUtil.GetRootLocalBones(config.targetClothesObject.transform, boneMatchUtil.GetMeshBones(config.targetClothesObject.GetComponentsInChildren<SkinnedMeshRenderer>().ToList()));
boneMatchUtil.MatchClothesToBodyBones(bodyRootLocalBones, rootLocalBones, out clothesHumanoidMatchedBones, out clothBoneTypeMap, out var clothToBodyMatched);
Dictionary<Transform, Transform> sourceToProxy;
GameObject gameObject = new BodyPoseMatchUtil().AutoAdjustBodyPose(config.sourceAvatarObject, config.sourceBodyMeshes, config.targetAvatarObject, config.targetBodyMeshes, out sourceToProxy);
if (gameObject == null)
{
throw new AutoMorpherException(LanguageManager.Get("UI.Exception.title.BodyProxyNull"), LanguageManager.Get("UI.Exception.message.BodyProxyNull"));
}
try
{
if (clothesHumanoidMatchedBones == null || clothesHumanoidMatchedBones.Count == 0)
{
throw new AutoMorpherException("Clothes Humanoid Matched Bones is Null", "[EdenAutoMorpher_SetUpUtil] AutoSetup\n - clothesHumanoidMatchedBones is null\n - Please check whether the outfits bones match the bones of the source avatar.");
}
if (clothBoneTypeMap == null)
{
throw new AutoMorpherException("Cloth Bone Type Map is Null", "[EdenAutoMorpher_SetUpUtil] AutoSetup\n - clothBoneTypeMap is null\n - Please check whether the outfits bones match the bones of the source avatar.");
}
if (AutoMorpherDev.isDeveloperMode)
{
this.DebugPrintSameNameBonePaths(clothToBodyMatched, sourceToProxy);
}
new BodyPoseToClothApplier().ApplyBodyPoseToClothes(gameObject.transform, config.targetClothesObject.transform, clothToBodyMatched, sourceToProxy);
}
finally
{
UnityEngine.Object.DestroyImmediate(gameObject);
}
}
public void DebugPrintSameNameBonePaths(Dictionary<Transform, BoneMatchUtil.BoneRootLocalData> clothToBodyMatched, Dictionary<Transform, Transform> sourceToProxy)
{
if (clothToBodyMatched == null)
{
throw new AutoMorpherException("clothToBodyMatched is Missing", "[DebugBonePath] DebugPrintSameNameBonePaths\n - clothToBodyMatched is null");
}
if (sourceToProxy == null)
{
throw new AutoMorpherException("sourceToProxy is Missing", "[DebugBonePath] DebugPrintSameNameBonePaths\n - sourceToProxy is null");
}
Dictionary<string, List<Transform>> dictionary = new Dictionary<string, List<Transform>>();
foreach (KeyValuePair<Transform, Transform> item in sourceToProxy)
{
Transform key = item.Key;
if (!(key == null))
{
if (!dictionary.TryGetValue(key.name, out var value))
{
value = new List<Transform>();
dictionary.Add(key.name, value);
}
value.Add(key);
}
}
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine("[DebugBonePath] Same-name bone path comparison");
stringBuilder.AppendLine("--------------------------------------------------");
foreach (KeyValuePair<Transform, BoneMatchUtil.BoneRootLocalData> item2 in clothToBodyMatched)
{
_ = item2.Key;
Transform transform = GetSourceTransform(item2.Value);
if (transform == null)
{
continue;
}
string name = transform.name;
if (!dictionary.TryGetValue(name, out var value2))
{
continue;
}
stringBuilder.AppendLine("[Bone Name] " + name);
stringBuilder.AppendLine(" - BoneRootLocalData Source Path: " + GetPath(transform));
foreach (Transform item3 in value2)
{
stringBuilder.AppendLine(" - sourceToProxy Source Path : " + GetPath(item3));
}
stringBuilder.AppendLine("--------------------------------------------------");
}
Debug.Log(stringBuilder.ToString());
static string GetPath(Transform t)
{
if (t == null)
{
return "(null)";
}
StringBuilder stringBuilder2 = new StringBuilder();
while (t != null)
{
stringBuilder2.Insert(0, t.name);
t = t.parent;
if (t != null)
{
stringBuilder2.Insert(0, "/");
}
}
return stringBuilder2.ToString();
}
static Transform GetSourceTransform(BoneMatchUtil.BoneRootLocalData data)
{
if (data == null)
{
return null;
}
FieldInfo[] fields = data.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (FieldInfo fieldInfo in fields)
{
if (typeof(Transform).IsAssignableFrom(fieldInfo.FieldType))
{
return fieldInfo.GetValue(data) as Transform;
}
}
return null;
}
}
public void ManulSetup(ref EdenAutoMorpherConfig config, out Dictionary<HumanBodyBones, HashSet<Transform>> clothesHumanoidMatchedBones, out Dictionary<Transform, ClothBoneType> clothBoneTypeMap)
{
BoneMatchUtil boneMatchUtil = new BoneMatchUtil();
List<BoneMatchUtil.BoneRootLocalData> bodyRootLocalBones = boneMatchUtil.GetBodyRootLocalBones(config.sourceAvatarObject.transform, config.sourceAvatarObject.GetComponent<Animator>(), config.sourceBodyMeshes.ToList());
List<BoneMatchUtil.BoneRootLocalData> rootLocalBones = boneMatchUtil.GetRootLocalBones(config.sourceClothesObject.transform, boneMatchUtil.GetMeshBones(config.sourceClothesObject.GetComponentsInChildren<SkinnedMeshRenderer>().ToList()));
boneMatchUtil.MatchClothesToBodyBones(bodyRootLocalBones, rootLocalBones, out var clothHumanBones, out var clothBoneTypeMap2, out var _);
boneMatchUtil.RemapSourceClothMatchToTargetCloth(config.sourceClothesObject.transform, config.targetClothesObject.transform, clothHumanBones, clothBoneTypeMap2, out clothesHumanoidMatchedBones, out clothBoneTypeMap);
if (clothesHumanoidMatchedBones == null || clothesHumanoidMatchedBones.Count == 0)
{
throw new AutoMorpherException("Clothes Humanoid Matched Bones is Null", "[EdenAutoMorpher_SetUpUtil] ManulSetup\n - clothesHumanoidMatchedBones is null\n - Please check whether the Source Clothess bones match the bones of the source avatar.");
}
if (clothBoneTypeMap == null)
{
throw new AutoMorpherException("Cloth Bone Type Map is Null", "[EdenAutoMorpher_SetUpUtil] ManulSetup\n - clothBoneTypeMap is null\n - Please check whether the Source Clothess bones match the bones of the source avatar.");
}
MeshClassifier meshClassifier = new MeshClassifier();
Dictionary<HumanBodyBones, HashSet<Transform>> humanBoneMap = meshClassifier.MeshHumanoidBoneMatcher(config.sourceAvatarObject.GetComponent<Animator>(), config.sourceBodyMeshes);
Dictionary<HumanBodyBones, HashSet<Transform>> humanBoneMap2 = meshClassifier.MeshHumanoidBoneMatcher(config.targetAvatarObject.GetComponent<Animator>(), config.sourceBodyMeshes);
BodyPoseMatchSetupUtil bodyPoseMatchSetupUtil = new BodyPoseMatchSetupUtil();
bodyPoseMatchSetupUtil.AdjustAvatarScaleByNeck(config.sourceAvatarObject.transform, humanBoneMap, 1.5f);
bodyPoseMatchSetupUtil.AdjustAvatarScaleByNeck(config.targetAvatarObject.transform, humanBoneMap2, 1.5f);
}
public void ProfileAutoSetup(ref EdenAutoMorpherConfig config, out Dictionary<HumanBodyBones, HashSet<Transform>> clothesHumanoidMatchedBones, out Dictionary<Transform, ClothBoneType> clothBoneTypeMap)
{
config.targetClothesObject = this.InstantiateTargetClothes(config.sourceClothesObject, config.targetAvatarObject, config.tagEdenMorpehrCloth, config.isRemoveAutoMorphedClothes);
if (config.targetClothesObject == null)
{
throw new AutoMorpherException("Target Clothes Object is Null", "[EdenAutoMorpher_SetUpUtil] ProfileAutoSetup\n - config.targetClothesObject is null");
}
ProfileData profileData = new ProfileLoader().LoadProfileData(config.profileName);
if (profileData == null)
{
throw new AutoMorpherException("Clothes Humanoid Matched Bones is Null", "[EdenAutoMorpher_SetUpUtil] ProfileAutoSetup\n - profile Data is null");
}
BoneMatchUtil boneMatchUtil = new BoneMatchUtil();
List<BoneMatchUtil.BoneRootLocalData> bodyBones = boneMatchUtil.ConvertProfileBoneDataToRootLocalData(profileData.bones);
List<BoneMatchUtil.BoneRootLocalData> rootLocalBones = boneMatchUtil.GetRootLocalBones(config.targetClothesObject.transform, boneMatchUtil.GetMeshBones(config.targetClothesObject.GetComponentsInChildren<SkinnedMeshRenderer>().ToList()));
boneMatchUtil.MatchClothesToBodyBones(bodyBones, rootLocalBones, out clothesHumanoidMatchedBones, out clothBoneTypeMap, out var _);
if (clothesHumanoidMatchedBones == null || clothesHumanoidMatchedBones.Count == 0)
{
throw new AutoMorpherException("Cloth Body Bones is Null", "[EdenAutoMorpher_SetUpUtil] ProfileAutoSetup\n - clothesHumanoidMatchedBones is null\n - Please check whether you have selected the correct profile for the outfit.");
}
if (clothBoneTypeMap == null)
{
throw new AutoMorpherException("Cloth Bone Type Map is Null", "[EdenAutoMorpher_SetUpUtil] ProfileAutoSetup\n - clothBoneTypeMap is null\n - Please check whether you have selected the correct profile for the outfit.");
}
new ProfilePoseMatchUtil().ProfilePoseMatcher(config.targetAvatarObject, config.targetBodyMeshes, config.targetClothesObject, profileData, clothesHumanoidMatchedBones, clothBoneTypeMap);
}
public List<SkinnedMeshRenderer> SetupBodyMeshes(GameObject bodyObject, bool isBodyAutoSetup, List<SkinnedMeshRenderer> userAllocatedBoeyMeshes, string errorPreFix = "")
{
new EdenAutoMorpherManager();
List<SkinnedMeshRenderer> list = (isBodyAutoSetup ? this.GetBodyMeshes(bodyObject) : userAllocatedBoeyMeshes);
if (list == null)
{
throw new AutoMorpherException(errorPreFix + "Body Mesh Is Null or Empty", errorPreFix + "Body Mesh list is null or empty");
}
foreach (SkinnedMeshRenderer item in list)
{
if (item == null)
{
throw new AutoMorpherException(errorPreFix + "Body Mesh Is Null", "Null Mesh in " + errorPreFix + " Body Meshes");
}
}
return list;
}
public List<SkinnedMeshRenderer> GetBodyMeshes(GameObject avatarObject)
{
MeshClassifier meshClassifier = new MeshClassifier();
List<SkinnedMeshRenderer> list = new List<SkinnedMeshRenderer>();
Animator component = avatarObject.GetComponent<Animator>();
if (component != null && component.avatar != null && component.avatar.isHuman)
{
list.Add(meshClassifier.GetBodyMesh(avatarObject.transform, component));
{
foreach (SkinnedMeshRenderer item in list)
{
if (item == null)
{
throw new AutoMorpherException(LanguageManager.Get("UI.Exception.title.BodyMeshNull"), LanguageManager.GetFormat("UI.Exception.message.BodyMeshNull", new object[1] { avatarObject.name }));
}
}
return list;
}
}
throw new AutoMorpherException(LanguageManager.Get("UI.Exception.title.BodyMeshNull"), LanguageManager.GetFormat("UI.Exception.message.BodyMeshNull", new object[1] { avatarObject.name }));
}
public ClothInstance SetupClothInstance(SkinnedMeshRenderer clothSMR, Dictionary<HumanBodyBones, HashSet<Transform>> clothesHumanoidMatchedBones, bool duplicateMesh)
{
ClothHumanoidMaskUtil clothHumanoidMaskUtil = new ClothHumanoidMaskUtil();
if (clothSMR == null || clothSMR.sharedMesh == null)
{
throw new AutoMorpherException(LanguageManager.Get("UI.Exception.title.TargetRendererNull"), LanguageManager.Get("UI.Exception.message.TargetRendererNull"));
}
ClothInstance clothInstance = new ClothInstance(clothSMR, duplicateMesh);
clothInstance.humanoidMatchedBones = clothesHumanoidMatchedBones;
clothHumanoidMaskUtil.BuildExcludedVertexMaskForHandsAndHead(clothInstance);
return clothInstance;
}
public ClothInstance SetupClothInstance(SkinnedMeshRenderer clothSMR, SkinnedMeshRenderer coupledSMR, MeshMatcher meshMatcher, Dictionary<HumanBodyBones, HashSet<Transform>> clothesHumanoidMatchedBones, bool duplicateMesh)
{
if (coupledSMR == null)
{
throw new AutoMorpherException("Coupled Skinned Mesh Renderer is Null", "[EdenAutoMorpher_SetupUtil] SetupClothInstance\n\n - Coupled Skinned Mesh Renderer is null");
}
if (coupledSMR.sharedMesh == null || coupledSMR.sharedMesh.vertexCount == 0)
{
throw new AutoMorpherException("Coupled Skinned Mesh Renderer's Mesh is Null or empty", "[EdenAutoMorpher_SetupUtil] SetupClothInstance\n\n - Coupled Skinned Mesh Renderer's mesh is null or no vertices");
}
ClothInstance clothInstance = this.SetupClothInstance(clothSMR, clothesHumanoidMatchedBones, duplicateMesh);
if (clothInstance == null)
{
return null;
}
Vector3[] worldVertices = new WorldVertexUtil().GetWorldVertices(coupledSMR);
clothInstance.minDistanceVector = meshMatcher.GetMinDistanceToBody(worldVertices);
if (clothInstance.minDistanceVector == null || clothInstance.minDistanceVector.Length == 0)
{
throw new AutoMorpherException("Min Distance is Null", "[EdenAutoMorpher_SetupUtil] SetupClothInstance\n - minDistanceVector is null or empty");
}
if (clothInstance.minDistanceVector != null)
{
clothInstance.minDistance = clothInstance.minDistanceVector.Select((Vector3 v) => v.magnitude).ToArray();
}
clothInstance.isInsideVertex = meshMatcher.GetBodyInsideFlags(worldVertices);
if (clothInstance.isInsideVertex == null || clothInstance.isInsideVertex.Length == 0)
{
throw new AutoMorpherException("isInsideVertex is Null", "[EdenAutoMorpher_SetupUtil] SetupClothInstance\n - isInsideVertex is null or empty");
}
return clothInstance;
}
public Transform CreateClothesArmature(EdenAutoMorpherConfig config, out Dictionary<Transform, Transform> clonedBoneMap)
{
clonedBoneMap = null;
if (config.targetClothesObject == null)
{
throw new AutoMorpherException("Target Clothes Object is Missing", "[EdenAutoMorpherManager] CreateClothesArmature\n - config.targetClothesObject is null");
}
if (config.targetAvatarObject == null)
{
throw new AutoMorpherException("Target Avatar Object is Missing", "[EdenAutoMorpherManager] CreateClothesArmature\n - config.targetAvatarObject is null");
}
Animator component = config.targetAvatarObject.GetComponent<Animator>();
if (component == null || !component.isHuman)
{
throw new AutoMorpherException("Target Avatar Animator is Invalid", "[EdenAutoMorpherManager] CreateClothesArmature\n - targetAvatarAnimator is null or not a Humanoid");
}
Transform boneTransform = component.GetBoneTransform(HumanBodyBones.Hips);
if (boneTransform == null)
{
throw new AutoMorpherException("Humanoid Root Bone is Missing", "[EdenAutoMorpherManager] CreateClothesArmature\n - Animator.GetBoneTransform(HumanBodyBones.Hips) returned null");
}
if (config.targetBodyMeshes == null || config.targetBodyMeshes.Count == 0)
{
throw new AutoMorpherException("Target Body Meshes are Missing", "[EdenAutoMorpherManager] CreateClothesArmature\n - config.targetBodyMeshes is null or empty");
}
Transform transform = config.targetClothesObject.transform;
Transform transform2 = this.FindArmature(config, config.targetClothesObject.transform);
if (transform2 == null)
{
transform2 = new GameObject("Armature.1").transform;
transform2.SetParent(transform, worldPositionStays: false);
transform2.localPosition = Vector3.zero;
transform2.localRotation = Quaternion.identity;
transform2.localScale = Vector3.one;
}
if (transform2.name == "Armature")
{
transform2.name = "Armature.1";
}
Dictionary<Transform, Transform> dictionary = new Dictionary<Transform, Transform>();
if (config.clothesHumanoidMatchedBones != null && config.clothesHumanoidMatchedBones.Count > 0)
{
foreach (KeyValuePair<HumanBodyBones, HashSet<Transform>> clothesHumanoidMatchedBone in config.clothesHumanoidMatchedBones)
{
HumanBodyBones key = clothesHumanoidMatchedBone.Key;
HashSet<Transform> value = clothesHumanoidMatchedBone.Value;
if (value == null || value.Count == 0)
{
continue;
}
Transform boneTransform2 = component.GetBoneTransform(key);
if (boneTransform2 == null)
{
continue;
}
Transform transform3 = null;
int num = int.MaxValue;
foreach (Transform item in value)
{
if (!(item == null))
{
int num2 = 0;
Transform transform4 = item;
while (transform4 != null)
{
num2++;
transform4 = transform4.parent;
}
if (num2 < num)
{
num = num2;
transform3 = item;
}
else if (num2 == num && transform3 != null && string.Compare(item.name, transform3.name, StringComparison.Ordinal) < 0)
{
transform3 = item;
}
}
}
if (!(transform3 == null) && !dictionary.ContainsKey(boneTransform2))
{
dictionary.Add(boneTransform2, transform3);
}
}
}
MeshClassifier meshClassifier = new MeshClassifier();
HashSet<Transform> hashSet = new HashSet<Transform>();
for (int i = 0; i < config.targetBodyMeshes.Count; i++)
{
SkinnedMeshRenderer skinnedMeshRenderer = config.targetBodyMeshes[i];
if (skinnedMeshRenderer == null)
{
continue;
}
HashSet<Transform> activeBones = meshClassifier.GetActiveBones(skinnedMeshRenderer);
if (activeBones == null)
{
continue;
}
foreach (Transform item2 in activeBones)
{
if (item2 != null)
{
hashSet.Add(item2);
}
}
}
HashSet<Transform> hashSet2 = new HashSet<Transform>(hashSet);
foreach (Transform item3 in hashSet)
{
if (item3 == null)
{
continue;
}
Transform transform5 = item3;
while (transform5 != null)
{
hashSet2.Add(transform5);
if (transform5 == boneTransform)
{
break;
}
transform5 = transform5.parent;
}
}
Dictionary<Transform, Transform> dictionary2 = new Dictionary<Transform, Transform>(hashSet2.Count);
Dictionary<Transform, Transform> dictionary3 = new Dictionary<Transform, Transform>(hashSet2.Count);
foreach (Transform item4 in hashSet2)
{
if (item4 == null)
{
continue;
}
Transform transform6 = null;
Transform transform7 = null;
if (dictionary.TryGetValue(item4, out var value2) && value2 != null)
{
transform6 = value2;
if (config.addAnchorBone)
{
transform7 = new GameObject(item4.name).transform;
transform7.SetParent(transform2, worldPositionStays: false);
transform7.position = item4.position;
transform7.rotation = item4.rotation;
transform7.localScale = Vector3.one;
transform6.SetParent(transform7, worldPositionStays: true);
transform6.name = item4.name + "_clothes";
transform6.localPosition = Vector3.zero;
transform6.localScale = Vector3.one;
}
else
{
transform6.name = item4.name;
transform6.position = item4.position;
this.ChildBonePositionPreserve(transform6, item4);
if (config.armatureBoneScaleCopy)
{
transform6.localScale = item4.localScale;
}
else
{
transform6.localScale = Vector3.one;
}
}
}
else
{
transform6 = new GameObject(item4.name).transform;
transform6.SetParent(transform2, worldPositionStays: false);
transform6.position = item4.position;
transform6.rotation = item4.rotation;
if (config.armatureBoneScaleCopy)
{
transform6.localScale = item4.localScale;
}
else
{
transform6.localScale = Vector3.one;
}
}
if (!(transform6 == null))
{
dictionary2[item4] = transform6;
dictionary3[item4] = ((transform7 != null) ? transform7 : transform6);
}
}
foreach (Transform item5 in hashSet2)
{
if (item5 == null)
{
continue;
}
if (!dictionary2.TryGetValue(item5, out var value3) || value3 == null)
{
throw new AutoMorpherException("Mapped Clothes Bone is Missing", "[EdenAutoMorpherManager] CreateClothesArmature\n - clonedByOriginal does not contain originalBone or mappedClothesBone is null\n - originalBone: " + item5.name);
}
if (!dictionary3.TryGetValue(item5, out var value4) || value4 == null)
{
throw new AutoMorpherException("Mapped Anchor Bone is Missing", "[EdenAutoMorpherManager] CreateClothesArmature\n - parentAnchorByOriginal does not contain originalBone or mappedAnchorBone is null\n - originalBone: " + item5.name);
}
if (item5 == boneTransform)
{
value4.SetParent(transform2, worldPositionStays: true);
continue;
}
Transform parent = item5.parent;
Transform value5;
if (parent == null)
{
value4.SetParent(transform2, worldPositionStays: true);
}
else if (dictionary3.TryGetValue(parent, out value5) && value5 != null)
{
value4.SetParent(value5, worldPositionStays: true);
}
else
{
value4.SetParent(transform2, worldPositionStays: true);
}
}
if (!dictionary3.TryGetValue(boneTransform, out var value6) || value6 == null)
{
throw new AutoMorpherException("Cloned Humanoid Root Bone is Missing", "[EdenAutoMorpherManager] CreateClothesArmature\n - failed to map clone for HumanBodyBones.Hips");
}
value6.SetParent(transform2, worldPositionStays: true);
clonedBoneMap = dictionary2;
return transform2;
}
private Transform FindArmature(EdenAutoMorpherConfig config, Transform clothesRoot)
{
if (clothesRoot == null)
{
throw new AutoMorpherException("Armature Root Resolve Failed", "[EdenAutoMorpherManager] FindSingleArmatureRootFromHumanoidMatchedBones\n - config is null or clothesRoot is null");
}
if (config.clothesHumanoidMatchedBones == null || config.clothesHumanoidMatchedBones.Count == 0)
{
return null;
}
Transform transform = null;
bool flag = false;
foreach (KeyValuePair<HumanBodyBones, HashSet<Transform>> clothesHumanoidMatchedBone in config.clothesHumanoidMatchedBones)
{
HashSet<Transform> value = clothesHumanoidMatchedBone.Value;
if (value == null || value.Count == 0)
{
continue;
}
foreach (Transform item in value)
{
if (!(item == null) && (!(item != clothesRoot) || item.IsChildOf(clothesRoot)))
{
flag = true;
Transform topChildUnderRoot = this.GetTopChildUnderRoot(item, clothesRoot);
if (topChildUnderRoot == null || topChildUnderRoot == clothesRoot)
{
return null;
}
if (transform == null)
{
transform = topChildUnderRoot;
}
else if (transform != topChildUnderRoot)
{
return null;
}
}
}
}
if (!flag)
{
return null;
}
if (transform == null || transform == clothesRoot)
{
return null;
}
return transform;
}
private Transform GetTopChildUnderRoot(Transform bone, Transform clothesRoot)
{
if (bone == null || clothesRoot == null)
{
return null;
}
if (bone == clothesRoot)
{
return clothesRoot;
}
Transform transform = bone;
while (transform.parent != null && transform.parent != clothesRoot)
{
transform = transform.parent;
}
if (transform.parent == clothesRoot)
{
return transform;
}
return clothesRoot;
}
private void ChildBonePositionPreserve(Transform reusableClothBone, Transform referenceAvatarBone)
{
if (reusableClothBone == null || referenceAvatarBone == null)
{
throw new AutoMorpherException("Reusable Bone Sync Failed", "[EdenAutoMorpherManager] SyncReusableBoneRotationPreserveChildrenWorld\n - reusableClothBone or referenceAvatarBone is null");
}
List<Transform> list = new List<Transform>();
List<Vector3> list2 = new List<Vector3>();
List<Quaternion> list3 = new List<Quaternion>();
for (int i = 0; i < reusableClothBone.childCount; i++)
{
Transform child = reusableClothBone.GetChild(i);
if (!(child == null))
{
this.CollectDescendants(child, list);
}
}
for (int j = 0; j < list.Count; j++)
{
Transform transform = list[j];
list2.Add(transform.position);
list3.Add(transform.rotation);
}
reusableClothBone.localRotation = referenceAvatarBone.localRotation;
for (int k = 0; k < list.Count; k++)
{
list[k].SetPositionAndRotation(list2[k], list3[k]);
}
}
private void CollectDescendants(Transform root, List<Transform> resultList)
{
if (root == null)
{
return;
}
resultList.Add(root);
for (int i = 0; i < root.childCount; i++)
{
Transform child = root.GetChild(i);
if (!(child == null))
{
this.CollectDescendants(child, resultList);
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More