Compare commits
15 Commits
0d54b7056c
...
Decompile
| Author | SHA1 | Date | |
|---|---|---|---|
| a00490fb35 | |||
| f3e104a200 | |||
| 793e544eb0 | |||
| e4566118f7 | |||
| 7637ff2ac0 | |||
| 6c2bb74df3 | |||
| 34507ca208 | |||
| 15efd5b720 | |||
| ff3a3c522e | |||
| bf39155bf3 | |||
| 5d4f773fe5 | |||
| 8e1adbd907 | |||
| 9903d26200 | |||
| d55375fa7c | |||
| e672d0aac5 |
6
.vsconfig
Normal file
6
.vsconfig
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"version": "1.0",
|
||||
"components": [
|
||||
"Microsoft.VisualStudio.Workload.ManagedGame"
|
||||
]
|
||||
}
|
||||
8
Assets/@Eden_Tools.meta
Normal file
8
Assets/@Eden_Tools.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dcaa6555c32099948b000b2924ed7e2f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/@Eden_Tools/Eden_AutoMorpher.meta
Normal file
8
Assets/@Eden_Tools/Eden_AutoMorpher.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4826438966086d644a3997c5803cf5aa
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,49 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &7464217327116044082
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 8068461331216787135}
|
||||
- component: {fileID: 6752720059844632398}
|
||||
m_Layer: 0
|
||||
m_Name: EdenAUtoMorpher_ProfileSaver
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &8068461331216787135
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7464217327116044082}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &6752720059844632398
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7464217327116044082}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 2fd1a8210b48a8d49843a3f2859e67b6, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
sourceAvatar: {fileID: 0}
|
||||
sourceBodyMeshes: []
|
||||
profileName:
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e67ca88eb0cf57141b82536914d0cace
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
67
Assets/@Eden_Tools/Eden_AutoMorpher/EdenAutoMorpher.prefab
Normal file
67
Assets/@Eden_Tools/Eden_AutoMorpher/EdenAutoMorpher.prefab
Normal file
@@ -0,0 +1,67 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &1593401673962086623
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1906542585506803867}
|
||||
- component: {fileID: 2852885081601766632}
|
||||
m_Layer: 0
|
||||
m_Name: EdenAutoMorpher
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &1906542585506803867
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1593401673962086623}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &2852885081601766632
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1593401673962086623}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 50552370e41d31140a52da99bcc7ab74, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
sourceAvatarObject: {fileID: 0}
|
||||
sourceClothesObject: {fileID: 0}
|
||||
sourceBodyMeshes: []
|
||||
profileName: Milfy
|
||||
targetAvatarObject: {fileID: 0}
|
||||
targetClothesObject: {fileID: 0}
|
||||
targetClothesObjectOriginal: {fileID: 0}
|
||||
targetBodyMeshes: []
|
||||
minMargin: 0.003
|
||||
worldRadius: 0.1
|
||||
sigma: 0.85
|
||||
smoothingIteration: 1
|
||||
fittingExpandIteration: 10
|
||||
fittingShrinkIteration: 12
|
||||
isBodyAutoSetup: 1
|
||||
isReparentAccessoryBonesToTargetAvatar: 1
|
||||
skipFootFitting: 0
|
||||
transferWeightToAvatar: 0
|
||||
addAnchorBone: 1
|
||||
armatureBoneScaleCopy: 0
|
||||
isRemoveAutoMorphedClothes: 1
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4512c204bb8c0a742b80d55d66adc895
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/@Eden_Tools/Eden_AutoMorpher/Editor.meta
Normal file
8
Assets/@Eden_Tools/Eden_AutoMorpher/Editor.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dcd2dae79e135544e8f59bbfd335d224
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 48dbd59641bef954eb938512667a41d1
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 367e223b416de1d4d92bdcaee21b1df7
|
||||
1007
Assets/@Eden_Tools/Eden_AutoMorpher/Editor/EdenAutoMorpherEditor.cs
Normal file
1007
Assets/@Eden_Tools/Eden_AutoMorpher/Editor/EdenAutoMorpherEditor.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2a5cebf384008fb4fa1e1141a4845238
|
||||
16
Assets/@Eden_Tools/Eden_AutoMorpher/Editor/ResultInfo.cs
Normal file
16
Assets/@Eden_Tools/Eden_AutoMorpher/Editor/ResultInfo.cs
Normal 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 = "";
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 45a0e5ffc6837dc48b871f340e85e7a4
|
||||
8
Assets/@Eden_Tools/Eden_AutoMorpher/LanguageManager.meta
Normal file
8
Assets/@Eden_Tools/Eden_AutoMorpher/LanguageManager.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 839d259bdc2a4ec45b739da7ecbf4e70
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f3c01fc12e499944da78f3441a00f36a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,213 @@
|
||||
{
|
||||
"entries": [
|
||||
{
|
||||
"key": "UI.Mode.AutoFitting",
|
||||
"value": "Auto Fitting Mode"
|
||||
},
|
||||
{
|
||||
"key": "UI.Mode.ManualFitting",
|
||||
"value": "Manual Fitting Mode"
|
||||
},
|
||||
{
|
||||
"key": "UI.Mode.ProfileFitting",
|
||||
"value": "Profile Mode"
|
||||
},
|
||||
{
|
||||
"key": "Error.BodyMesh.NotFound",
|
||||
"value": "Failed to find Body Mesh."
|
||||
},
|
||||
{
|
||||
"key": "Error.KeyNotFound",
|
||||
"value": "[EN] Could not find key: {0}"
|
||||
},
|
||||
{
|
||||
"key": "UI.Mode.ManualFittingGuide",
|
||||
"value": "Manual Setting Mode\n1. Assign the Objects and Meshes for the Source / Target Avatars.\n2. Adjust the target clothes object (Target Clothes Object) to match the target avatar.\n3. Press [Run Fitting] to start the fitting.\n4. Press [Run Weighting] to start weight assignment."
|
||||
},
|
||||
{
|
||||
"key": "UI.Mode.AutoFittingGuide",
|
||||
"value": "Auto Setting Mode\n1. Assign the Source avatar body and clothing objects to the Source Avatar.\n2. Assign the target avatar body to the Target Avatar.\n3. Press [Run Fitting] to begin fitting.\n4. Press [Run Weighting] to start weight assignment."
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.MinMarginInfo",
|
||||
"value": "If the clothes stick too closely to the body, increase the MinMargin value. (Default: 0.003)"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.SkipFootFittingInfo",
|
||||
"value": "Check this option to disable foot-based shape corrections during the fitting stage."
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.BodyMeshTitle",
|
||||
"value": "Automatically Assign Body Mesh"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.BodyMeshInfo",
|
||||
"value": "If the body mesh cannot be detected automatically, \nplease manually assign the mesh corresponding to the body (excluding the head) to Body Meshes."
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.SigmaInfo",
|
||||
"value": "Increasing this value makes a wider area of the clothing deform smoothly together. (Default: 0.85)"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.SmoothingInfo",
|
||||
"value": "Increasing this value applies the Smooth effect more strongly, making the deformation smoother. (Default: 1)\n - Higher values will increase computation time."
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.IterationInfo",
|
||||
"value": "If you want more deformation for the clothes, increase the number of fitting iterations."
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.ReparentAccessoryBones",
|
||||
"value": "Moves and places accessory bones into the target avatar’s armature during weighting."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.ReferenceCheck",
|
||||
"value": "The following items must all be assigned:"
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.SourceClothesChildCheck",
|
||||
"value": "The Source Clothes Object must be a child of the Source Avatar Object.\n→ Please place the clothes under the Source Avatar object."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.TargetClothesChildCheck",
|
||||
"value": "The Target Clothes Object must be a child of the Target Avatar Object.\n→ Please place the clothes under the Target Avatar object."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.ClothesArmatureCheck",
|
||||
"value": "Clothes Object - The Bone Armature referenced by the SkinnedMeshRenderer is not correctly included in the Clothes Object."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.SourceAvatarAnimatorCheck",
|
||||
"value": "The Source Avatar Object does not have a Humanoid Avatar assigned.\n→ Please check the Animator component and Avatar settings."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.TargetAvatarAnimatorCheck",
|
||||
"value": "The Target Avatar Object does not have a Humanoid Avatar assigned.\n→ Please check the Animator component and Avatar settings."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.CheckRendererCountCheck",
|
||||
"value": "The number of SkinnedMeshRenderers in the Source / Target Clothes does not match."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.VertexCountCheck",
|
||||
"value": "The vertex count of the corresponding SkinnedMeshRenderer meshes does not match."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.Can'tFitting",
|
||||
"value": "Unable to run\n\n"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.title.BodyProxyNull",
|
||||
"value": "Body Proxy Null Error"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.BodyProxyNull",
|
||||
"value": "Failed to assign the Body Proxy.\nPlease make sure the Source Avatar is correctly assigned and the bones are properly set in the Animator."
|
||||
},
|
||||
|
||||
{
|
||||
"key": "UI.Exception.title.SourceBodyMeshNull",
|
||||
"value": "Source Body Mesh Not Found"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.SourceBodyMeshNull",
|
||||
"value": "Could not find the Source Body Mesh."
|
||||
},
|
||||
|
||||
{
|
||||
"key": "UI.Exception.title.TargetBodyMeshNull",
|
||||
"value": "Target Body Mesh Not Found"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.TargetBodyMeshNull",
|
||||
"value": "Could not find the Target Body Mesh."
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.title.BodyMeshNull",
|
||||
"value": "BodyMesh Search Failed"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.BodyMeshNull",
|
||||
"value": "The BodyMesh of [{0}] could not be found."
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.title.TargetRendererNull",
|
||||
"value": "Target Renderer Null Error"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.TargetRendererNull",
|
||||
"value": "targetRenderers contains one or more null elements."
|
||||
},
|
||||
|
||||
{
|
||||
"key": "UI.Exception.title.ClothInstanceAllocateFail",
|
||||
"value": "ClothInstance Allocation Failed"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.ClothInstanceAllocateFail",
|
||||
"value": "No ClothInstance could be allocated.\nPlease check if the clothes have a SkinnedMeshRenderer."
|
||||
},
|
||||
|
||||
{
|
||||
"key": "UI.Exception.title.WeightingNotReady",
|
||||
"value": "Weighting Is Not Ready"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.WeightingNotReady",
|
||||
"value": "Fitting has not finished before calling WeightingEnumerator, or the Target Avatar has been changed.\nPlease run Run Fitting again."
|
||||
},
|
||||
|
||||
{
|
||||
"key": "UI.Exception.title.BodyBVHFail",
|
||||
"value": "Body BVH Creation Failed"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.BodyBVHFail",
|
||||
"value": "Failed to build BVH for {0}.\nbvhMesh is Null : {1}\nbvhMesh triangles is Null : {2}"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Guide",
|
||||
"value": "This section is for generating Profile data.\nPlease set the avatar Scale to 1,1,1.\nAdjust ShapeKeys so that the avatar BodyMesh is not occluded."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.ProfileName.Tooltip",
|
||||
"value": "Name of the Profile to be saved"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.SourceAvatar.Tooltip",
|
||||
"value": "Avatar root Transform with Humanoid Rig and Animator configured"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.SourceBodyMeshes.Tooltip",
|
||||
"value": "List of body SkinnedMeshRenderers used for Profile generation"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.ProfileNameEmpty",
|
||||
"value": "Profile Name is empty."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.SourceAvatarNull",
|
||||
"value": "Source Avatar is not assigned."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.SourceAvatarAnimatorMissing",
|
||||
"value": "Source Avatar does not have an Animator."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.SourceBodyMeshesEmpty",
|
||||
"value": "Source Body Meshes is empty."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.SourceBodyMeshesContainNull",
|
||||
"value": "Source Body Meshes contains NULL."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.BodyMeshNotChildOfAvatar",
|
||||
"value": "Source Body Meshes must be children of the Source Avatar."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.BaseDataMissing",
|
||||
"value": "No Base file exists in the BaseData folder."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0aa9f12300a0596408771775b2d5148e
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,212 @@
|
||||
{
|
||||
"entries": [
|
||||
{
|
||||
"key": "UI.Mode.AutoFitting",
|
||||
"value": "自動セットアップモード"
|
||||
},
|
||||
{
|
||||
"key": "UI.Mode.ManualFitting",
|
||||
"value": "手動セットアップモード"
|
||||
},
|
||||
{
|
||||
"key": "UI.Mode.ProfileFitting",
|
||||
"value": "プロファイルモード"
|
||||
},
|
||||
{
|
||||
"key": "Error.BodyMesh.NotFound",
|
||||
"value": "Body Mesh を見つけられませんでした。"
|
||||
},
|
||||
{
|
||||
"key": "Error.KeyNotFound",
|
||||
"value": "[JP] キーが見つかりません: {0}"
|
||||
},
|
||||
{
|
||||
"key": "UI.Mode.ManualFittingGuide",
|
||||
"value": "手動セットアップモード\n1. Source / Target Avatar に対応するオブジェクトとメッシュを割り当ててください。\n2. 対応する衣装(Target Clothes Object)をターゲットアバターに合わせて調整してください。\n3. [Run Fitting] を押してフィッティングを開始してください。\n4. [Run Weighting] を押してウェイト割り当てを開始してください。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Mode.AutoFittingGuide",
|
||||
"value": "自動セットアップモード\n1. Source Avatar にソースアバターのボディと衣装オブジェクトを割り当ててください。\n2. Target Avatar にターゲットアバターのボディを割り当ててください。\n3. [Run Fitting] を押してフィッティングを開始してください。\n4. [Run Weighting] を押してウェイト割り当てを開始してください。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.MinMarginInfo",
|
||||
"value": "衣装が体に密着しすぎる場合は、MinMarginの値を大きくしてください。(初期値: 0.003)"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.SkipFootFittingInfo",
|
||||
"value": "Fitting工程において、足(foot)を基準とした形状補正を適用しない場合はチェックしてください。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.BodyMeshTitle",
|
||||
"value": "ボディメッシュを自動で割り当てる"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.BodyMeshInfo",
|
||||
"value": "ボディメッシュを自動で検出できない場合は、\n(頭部を除く)ボディに該当するメッシュを Body Meshes に手動で割り当ててください。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.SigmaInfo",
|
||||
"value": "値を上げるほど、衣装のより広い範囲が一緒に滑らかに変形します。(初期値:0.85)"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.SmoothingInfo",
|
||||
"value": "値を上げるほど、Smooth効果がより強く適用され、変形がより滑らかになります。(初期値:1)\n - 値を上げると処理時間が長くなります。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.IterationInfo",
|
||||
"value": "衣装をさらに変形させたい場合は、Fittingの反復回数を増やしてください。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.ReparentAccessoryBones",
|
||||
"value": "Weighting 時にアクセサリーボーンを Target アバターのアーマチュアへ移動して配置します。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.ReferenceCheck",
|
||||
"value": "次の項目がすべて割り当てられている必要があります:"
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.SourceClothesChildCheck",
|
||||
"value": "Source Clothes Object は必ず Source Avatar Object の子オブジェクトである必要があります。\n→ Source Avatar オブジェクトの下に衣装を配置してください。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.TargetClothesChildCheck",
|
||||
"value": "Target Clothes Object は必ず Target Avatar Object の子オブジェクトである必要があります。\n→ Target Avatar オブジェクトの下に衣装を配置してください。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.ClothesArmatureCheck",
|
||||
"value": "Clothes Object - Clothes オブジェクトに、SkinnedMeshRenderer が参照するボーンアーマチュアが正しく含まれていません。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.SourceAvatarAnimatorCheck",
|
||||
"value": "Source Avatar Object に Humanoid Avatar が設定されていません。\n→ Animator コンポーネントと Avatar 設定を確認してください。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.TargetAvatarAnimatorCheck",
|
||||
"value": "Target Avatar Object に Humanoid Avatar が設定されていません。\n→ Animator コンポーネントと Avatar 設定を確認してください。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.CheckRendererCountCheck",
|
||||
"value": "Source / Target Clothes の SkinnedMeshRenderer の数が一致していません。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.VertexCountCheck",
|
||||
"value": "対応する SkinnedMeshRenderer の Mesh vertex 数が一致していません。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.Can'tFitting",
|
||||
"value": "を実行できません\n\n"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.title.BodyProxyNull",
|
||||
"value": "Body Proxy Null エラー"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.BodyProxyNull",
|
||||
"value": "Body Proxy を割り当てることができませんでした。\nSource Avatar が正しく割り当てられているか、Animator にボーンが正しく設定されているか確認してください。"
|
||||
},
|
||||
|
||||
{
|
||||
"key": "UI.Exception.title.SourceBodyMeshNull",
|
||||
"value": "Source Body Mesh の探索に失敗しました"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.SourceBodyMeshNull",
|
||||
"value": "Source Body Mesh を見つけることができませんでした。"
|
||||
},
|
||||
|
||||
{
|
||||
"key": "UI.Exception.title.TargetBodyMeshNull",
|
||||
"value": "Target Body Mesh の探索に失敗しました"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.TargetBodyMeshNull",
|
||||
"value": "Target Body Mesh を見つけることができませんでした。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.title.BodyMeshNull",
|
||||
"value": "BodyMesh の探索に失敗しました"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.BodyMeshNull",
|
||||
"value": "[{0}] の BodyMesh を見つけることができません。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.title.TargetRendererNull",
|
||||
"value": "Target Renderer Null エラー"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.TargetRendererNull",
|
||||
"value": "targetRenderers に null が含まれています。"
|
||||
},
|
||||
|
||||
{
|
||||
"key": "UI.Exception.title.ClothInstanceAllocateFail",
|
||||
"value": "ClothInstance の割り当てに失敗しました"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.ClothInstanceAllocateFail",
|
||||
"value": "割り当て可能な ClothInstance がありません。\n衣装に SkinnedMeshRenderer が含まれているか確認してください。"
|
||||
},
|
||||
|
||||
{
|
||||
"key": "UI.Exception.title.WeightingNotReady",
|
||||
"value": "Weighting の準備ができていません"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.WeightingNotReady",
|
||||
"value": "WeightingEnumerator を呼び出す前に Fitting が完了していないか、Target Avatar が変更されています。\nRun Fitting を再実行してください。"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.title.BodyBVHFail",
|
||||
"value": "Body BVH の生成に失敗しました"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.BodyBVHFail",
|
||||
"value": "{0} の BVH の生成に失敗しました。\nbvhMesh is Null : {1}\nbvhMesh triangles is Null : {2}"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Guide",
|
||||
"value": "Profileデータ生成のための設定です。\nアバターのScaleは 1,1,1 に設定してください。\nアバターのBodyMeshが隠れないようにShapeKeyを調整してください。"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.ProfileName.Tooltip",
|
||||
"value": "保存されるProfileの名前"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.SourceAvatar.Tooltip",
|
||||
"value": "Humanoid Rig と Animator が設定された Avatar の Root Transform"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.SourceBodyMeshes.Tooltip",
|
||||
"value": "Profile生成に使用される Body SkinnedMeshRenderer の一覧"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.ProfileNameEmpty",
|
||||
"value": "Profile Name が空です。"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.SourceAvatarNull",
|
||||
"value": "Source Avatar が指定されていません。"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.SourceAvatarAnimatorMissing",
|
||||
"value": "Source Avatar に Animator が存在しません。"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.SourceBodyMeshesEmpty",
|
||||
"value": "Source Body Meshes が空です。"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.SourceBodyMeshesContainNull",
|
||||
"value": "Source Body Meshes に NULL が含まれています。"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.BodyMeshNotChildOfAvatar",
|
||||
"value": "Source Body Meshes は必ず Source Avatar の子オブジェクトである必要があります。"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.BaseDataMissing",
|
||||
"value": "BaseData フォルダに Base ファイルが存在しません。"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 07befa424eefac04e8670c57d4c2a2ec
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,211 @@
|
||||
{
|
||||
"entries": [
|
||||
{
|
||||
"key": "UI.Mode.AutoFitting",
|
||||
"value": "자동 셋팅 모드"
|
||||
},
|
||||
{
|
||||
"key": "UI.Mode.ManualFitting",
|
||||
"value": "직접 셋팅 모드"
|
||||
},
|
||||
{
|
||||
"key": "UI.Mode.ProfileFitting",
|
||||
"value": "프로필 모드"
|
||||
},
|
||||
{
|
||||
"key": "Error.BodyMesh.NotFound",
|
||||
"value": "Body Mesh를 찾지 못했습니다."
|
||||
},
|
||||
{
|
||||
"key": "Error.KeyNotFound",
|
||||
"value": "[KO] 해당 키를 찾을 수 없습니다: {0}"
|
||||
},
|
||||
{
|
||||
"key": "UI.Mode.ManualFittingGuide",
|
||||
"value": "직접 셋팅 모드\n1. Source / Target Avatar에 해당하는 Object와 Mesh들을 할당해 주세요.\n2. 대응할 의상(Target Clothes Object)을 대응할 아바타에 맞춰 조정해주세요.\n3. [Run Fitting]을 눌러서 대응을 시작하세요.\n4. [Run Weighting]을 눌러서 Weight 할당을 시작하세요."
|
||||
},
|
||||
{
|
||||
"key": "UI.Mode.AutoFittingGuide",
|
||||
"value": "자동 셋팅 모드\n1. Source Avatar에 Source 아바타 바디와 의상 Object를 할당해주세요.\n2. Target Avatar에 Target 아바타 바디를 할당해주세요.\n3. [Run Fitting]을 눌러 대응을 시작하세요.\n4. [Run Weighting]을 눌러서 Weight 할당을 시작하세요."
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.MinMarginInfo",
|
||||
"value": "의상이 몸에 너무 달라 붙는다면, MinMargin 값을 늘려주세요. (초기값: 0.003)"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.SkipFootFittingInfo",
|
||||
"value": "Fitting 단계에서 발(foot) 기준의 형태 보정을 적용하지 않으려면 체크해주세요."
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.BodyMeshTitle",
|
||||
"value": "Body Mesh 자동으로 할당하기."
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.BodyMeshInfo",
|
||||
"value": "Body Mesh를 자동으로 찾지 못 할 경우, \n(Head 제외) 바디에 해당하는 Mesh를 Body Meshes에 할당해 주세요."
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.SigmaInfo",
|
||||
"value": "값을 높일수록 의상의 더 넓은 부분이 함께 부드럽게 변형됩니다. (초기값: 0.85)"
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.SmoothingInfo",
|
||||
"value": "값을 높일수록 Smooth 효과가 더 많이 적용되어 변형이 더욱 부드러워집니다. (초기값: 1)\n - 값이 높아질수록 연산 시간이 증가합니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.IterationInfo",
|
||||
"value": "의상을 더 많이 변형시키고 싶다면, Fitting 반복 횟수를 늘려주세요."
|
||||
},
|
||||
{
|
||||
"key": "UI.Property.ReparentAccessoryBones",
|
||||
"value": "Weighting시 악세서리 본을 Target Avatar에 Armature로 옮겨 배치합니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.ReferenceCheck",
|
||||
"value": "다음 항목이 모두 할당되어야 합니다:"
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.SourceClothesChildCheck",
|
||||
"value": "Source Clothes Object 는 반드시 Source Avatar Object 의 자식이어야 합니다.\n→ Source Avatar 오브젝트 하위에 의상을 넣어 주세요."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.TargetClothesChildCheck",
|
||||
"value": "Target Clothes Object 는 반드시 Target Avatar Object 의 자식이어야 합니다.\n→ Target Avatar 오브젝트 하위에 의상을 넣어 주세요."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.ClothesArmatureCheck",
|
||||
"value": "Clothes Object - 의상에 SkinnedMeshRenderer가 참조하는 Bone Armature가 올바르게 포함되어 있지 않습니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.SourceAvatarAnimatorCheck",
|
||||
"value": "Source Avatar Object 에 Humanoid Avatar 가 설정되어 있지 않습니다.\n→ Animator 컴포넌트 및 Avatar 설정을 확인해 주세요."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.TargetAvatarAnimatorCheck",
|
||||
"value": "Target Avatar Object 에 Humanoid Avatar 가 설정되어 있지 않습니다.\n→ Animator 컴포넌트 및 Avatar 설정을 확인해 주세요."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.CheckRendererCountCheck",
|
||||
"value": "Source / Target Clothes 의 SkinnedMeshRenderer 개수가 일치하지 않습니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.VertexCountCheck",
|
||||
"value": "대응되는 SkinnedMeshRenderer 의 Mesh vertex 수가 일치하지 않습니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.Validator.Can'tFitting",
|
||||
"value": "실행 불가\n\n"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.title.BodyProxyNull",
|
||||
"value": "Body Proxy Null 에러"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.BodyProxyNull",
|
||||
"value": "Body Proxy를 할당할 수 없습니다.\nSource Avatar가 제대로 할당되어 있으며, Animator에 본이 제대로 셋팅되어 있는지 확인해주세요."
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.title.SourceBodyMeshNull",
|
||||
"value": "Source Body Mesh 탐색 실패"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.SourceBodyMeshNull",
|
||||
"value": "Source Body Mesh 를 찾을 수 없습니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.title.TargetBodyMeshNull",
|
||||
"value": "Target Body Mesh 탐색 실패"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.TargetBodyMeshNull",
|
||||
"value": "Target Body Mesh 를 찾을 수 없습니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.title.BodyMeshNull",
|
||||
"value": "Body Mesh 탐색 실패"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.BodyMeshNull",
|
||||
"value": "[{0}]의 Body Mesh 를 찾을 수 없습니다."
|
||||
},
|
||||
|
||||
{
|
||||
"key": "UI.Exception.title.TargetRendererNull",
|
||||
"value": "Target Renderer Null 에러"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.TargetRendererNull",
|
||||
"value": "targetRenderers 에 null 이 포함되어 있습니다."
|
||||
},
|
||||
|
||||
{
|
||||
"key": "UI.Exception.title.ClothInstanceAllocateFail",
|
||||
"value": "ClothInstance 할당 실패"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.ClothInstanceAllocateFail",
|
||||
"value": "할당할 수 있는 ClothInstance가 없습니다.\n의상에 SkinnedMeshRenderer가 있는지 확인해주세요."
|
||||
},
|
||||
|
||||
{
|
||||
"key": "UI.Exception.title.WeightingNotReady",
|
||||
"value": "Weighting이 준비되지 않았습니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.WeightingNotReady",
|
||||
"value": "WeightingEnumerator 호출 전 Fitting이 완료되지 않았거나, Target Avatar가 변경되었습니다.\nRun Fitting을 다시 실행해 주세요."
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.title.BodyBVHFail",
|
||||
"value": "Body BVH 생성 실패"
|
||||
},
|
||||
{
|
||||
"key": "UI.Exception.message.BodyBVHFail",
|
||||
"value": "{0} 의 BVH를 만드는데 실패하였습니다.\nbvhMesh is Null : {1}\nbvhMesh triangles is Null : {2}"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Guide",
|
||||
"value": "Profile 데이터 생성을 위한 설정 영역입니다.\n아바타의 Scale은 1,1,1로 맞춰주세요.\n아바타의 BodyMesh가 가려지지 않도록 ShapeKey를 조절해 주세요."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.ProfileName.Tooltip",
|
||||
"value": "저장될 Profile 이름"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.SourceAvatar.Tooltip",
|
||||
"value": "Humanoid Rig + Animator가 설정된 Avatar Root Transform"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.SourceBodyMeshes.Tooltip",
|
||||
"value": "Profile 생성에 사용될 Body SkinnedMeshRenderer 목록"
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.ProfileNameEmpty",
|
||||
"value": "Profile Name이 비어 있습니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.SourceAvatarNull",
|
||||
"value": "Source Avatar가 지정되지 않았습니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.SourceAvatarAnimatorMissing",
|
||||
"value": "Source Avatar에 Animator가 존재하지 않습니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.SourceBodyMeshesEmpty",
|
||||
"value": "Source Body Meshes가 비어 있습니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.SourceBodyMeshesContainNull",
|
||||
"value": "Source Body Meshes에 NULL이 존재합니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.BodyMeshNotChildOfAvatar",
|
||||
"value": "Source Body Meshes 는 반드시 Source Avatar 의 자식이어야 합니다."
|
||||
},
|
||||
{
|
||||
"key": "UI.ProfileSaver.Error.BaseDataMissing",
|
||||
"value": "BaseData 폴더에 Base 파일이 존재하지 않습니다."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 06a08864e1cbb6740a46cbde54883c6a
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,285 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
using UnityEngine;
|
||||
|
||||
namespace Eden.AutoMorpher
|
||||
{
|
||||
public enum Language
|
||||
{
|
||||
Korean = 0,
|
||||
Japanese = 1,
|
||||
English = 2,
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class LocalizationEntry
|
||||
{
|
||||
public string key;
|
||||
public string value;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class LocalizationFile
|
||||
{
|
||||
public LocalizationEntry[] entries;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[InitializeOnLoad]
|
||||
#endif
|
||||
public static class LanguageManager
|
||||
{
|
||||
private const string PREF_KEY_LANG = "EdenAutoMorpher_Language";
|
||||
|
||||
private const string PATH_KO = "Language/Language_ko";
|
||||
private const string PATH_JA = "Language/Language_ja";
|
||||
private const string PATH_EN = "Language/Language_en";
|
||||
|
||||
private static Language _currentLanguage = Language.Korean;
|
||||
|
||||
private static Dictionary<string, string> _koTable;
|
||||
private static Dictionary<string, string> _jaTable;
|
||||
private static Dictionary<string, string> _enTable;
|
||||
|
||||
public static Language CurrentLanguage
|
||||
{
|
||||
get => _currentLanguage;
|
||||
set
|
||||
{
|
||||
if (_currentLanguage == value) return;
|
||||
_currentLanguage = value;
|
||||
#if UNITY_EDITOR
|
||||
EditorPrefs.SetInt(PREF_KEY_LANG, (int)_currentLanguage);
|
||||
#else
|
||||
PlayerPrefs.SetInt(PREF_KEY_LANG, (int)_currentLanguage);
|
||||
PlayerPrefs.Save();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static LanguageManager()
|
||||
{
|
||||
// Editor 시작 시 언어 로드
|
||||
#if UNITY_EDITOR
|
||||
int saved = EditorPrefs.GetInt(PREF_KEY_LANG, (int)Language.Korean);
|
||||
#else
|
||||
int saved = PlayerPrefs.GetInt(PREF_KEY_LANG, (int)Language.Korean);
|
||||
#endif
|
||||
_currentLanguage = (Language)Mathf.Clamp(saved, 0, 2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 현재 언어에서 문자열 가져오기.
|
||||
/// key 없으면 fallback → 다른 언어 → 최종적으로 key 자체 반환.
|
||||
/// </summary>
|
||||
public static string Get(string key)
|
||||
{
|
||||
if (string.IsNullOrEmpty(key))
|
||||
return string.Empty;
|
||||
|
||||
// 현재 언어 테이블에서 먼저 검색
|
||||
if (TryGetFromCurrentLanguage(key, out string value))
|
||||
return value;
|
||||
|
||||
return FormatKeyNotFound(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 언어별로 다른 키를 쓰고 싶을 때 (번호 기반 등)도 가능하도록
|
||||
/// 번호를 바로 key 문자열로 변환해서 사용하는 버전.
|
||||
/// </summary>
|
||||
public static string GetById(int id)
|
||||
{
|
||||
// 예: "ID.1001" 이런 식으로 통일하면 관리가 편함
|
||||
string key = $"ID.{id}";
|
||||
return Get(key);
|
||||
}
|
||||
|
||||
public static void SetLanguage(Language lang)
|
||||
{
|
||||
CurrentLanguage = lang;
|
||||
}
|
||||
|
||||
// ================== 내부 구현 ==================
|
||||
|
||||
private static bool TryGetFromCurrentLanguage(string key, out string value)
|
||||
{
|
||||
var table = GetTable(_currentLanguage);
|
||||
if (table != null && table.TryGetValue(key, out value))
|
||||
return true;
|
||||
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool TryGetFromOtherLanguages(string key, out string value)
|
||||
{
|
||||
// 현재 언어 제외한 나머지 순회
|
||||
foreach (Language lang in System.Enum.GetValues(typeof(Language)))
|
||||
{
|
||||
if (lang == _currentLanguage)
|
||||
continue;
|
||||
|
||||
var table = GetTable(lang);
|
||||
if (table != null && table.TryGetValue(key, out value))
|
||||
return true;
|
||||
}
|
||||
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Dictionary<string, string> GetTable(Language lang)
|
||||
{
|
||||
switch (lang)
|
||||
{
|
||||
case Language.Korean:
|
||||
if (_koTable == null)
|
||||
_koTable = LoadTable(PATH_KO);
|
||||
return _koTable;
|
||||
|
||||
case Language.Japanese:
|
||||
if (_jaTable == null)
|
||||
_jaTable = LoadTable(PATH_JA);
|
||||
return _jaTable;
|
||||
|
||||
case Language.English:
|
||||
if (_enTable == null)
|
||||
_enTable = LoadTable(PATH_EN);
|
||||
return _enTable;
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// fileName: "lang_ko", "lang_ja", "lang_en" 처럼 사용
|
||||
private static Dictionary<string, string> LoadTable(string fileName)
|
||||
{
|
||||
var dict = new Dictionary<string, string>();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
// 스크립트 기준 Language 폴더 아래의 json 경로
|
||||
string assetPath = GetLanguageJsonAssetPath(fileName);
|
||||
// Assets/... 형식 경로를 실제 디스크 경로로 변환
|
||||
string fullPath = Path.GetFullPath(assetPath);
|
||||
|
||||
if (!File.Exists(fullPath))
|
||||
{
|
||||
Debug.LogWarning($"[AutoMorpherLanguage] Localization file not found: {fullPath}");
|
||||
return dict;
|
||||
}
|
||||
|
||||
string jsonText;
|
||||
try
|
||||
{
|
||||
// ✅ 강제로 UTF-8 로 읽기 (BOM 유무 상관 없음)
|
||||
jsonText = File.ReadAllText(fullPath, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Debug.LogError($"[AutoMorpherLanguage] Failed to read localization file: {fullPath}\n{ex}");
|
||||
return dict;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var file = JsonUtility.FromJson<LocalizationFile>(jsonText);
|
||||
if (file?.entries != null)
|
||||
{
|
||||
foreach (var entry in file.entries)
|
||||
{
|
||||
if (string.IsNullOrEmpty(entry.key))
|
||||
continue;
|
||||
|
||||
dict[entry.key] = entry.value ?? string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Debug.LogError($"[AutoMorpherLanguage] Failed to parse localization file: {fullPath}\n{ex}");
|
||||
}
|
||||
#else
|
||||
// 런타임 빌드에서 쓸 계획이 없으면 비워둬도 됨
|
||||
#endif
|
||||
return dict;
|
||||
}
|
||||
private static string FormatKeyNotFound(string key)
|
||||
{
|
||||
// 먼저 현재 언어의 "Error.KeyNotFound" 가져오기
|
||||
if (TryGetFromCurrentLanguage("Error.KeyNotFound", out string template))
|
||||
return template.Replace("{0}", key);
|
||||
|
||||
// JSON 자체가 없어서 템플릿도 없는 경우 (최후 fallback)
|
||||
switch (CurrentLanguage)
|
||||
{
|
||||
case Language.Korean:
|
||||
return $"[KO] 해당 키를 찾을 수 없습니다: {key}";
|
||||
case Language.Japanese:
|
||||
return $"[JP] キーが見つかりません: {key}";
|
||||
default:
|
||||
return $"[EN] Could not find key: {key}";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static string GetLanguageFolderPath()
|
||||
{
|
||||
string scriptDir = "Assets\\@Eden_Tools\\Eden_AutoMorpher\\LanguageManager\\Language";
|
||||
#if UNITY_EDITOR
|
||||
// AutoMorpherLanguage 스크립트의 GUID 찾기
|
||||
string[] guids = AssetDatabase.FindAssets("LanguageManager t:MonoScript");
|
||||
if (guids == null || guids.Length == 0)
|
||||
{
|
||||
Debug.LogError("[LanguageManager] Could not find LanguageManager.cs script.");
|
||||
return "Assets"; // 최소 fallback
|
||||
}
|
||||
|
||||
string scriptPath = AssetDatabase.GUIDToAssetPath(guids[0]); // 예: Assets/@Eden_Tools/.../AutoMorpherLanguage.cs
|
||||
scriptDir = Path.GetDirectoryName(scriptPath); // 그 폴더
|
||||
|
||||
|
||||
// 폴더가 없으면 에디터에서 자동 생성
|
||||
if (!Directory.Exists(scriptDir))
|
||||
{
|
||||
Directory.CreateDirectory(scriptDir);
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
#endif
|
||||
// Unity Asset 경로 포맷으로 정리
|
||||
scriptDir = scriptDir.Replace("\\", "/");
|
||||
return scriptDir;
|
||||
}
|
||||
|
||||
public static string GetLanguageJsonAssetPath(string fileNameWithoutExt)
|
||||
{
|
||||
string folder = GetLanguageFolderPath();
|
||||
string path = Path.Combine(folder, fileNameWithoutExt + ".json");
|
||||
return path.Replace("\\", "/");
|
||||
}
|
||||
|
||||
public static string GetFormat(string key, params object[] args)
|
||||
{
|
||||
string raw = Get(key);
|
||||
if (string.IsNullOrEmpty(raw))
|
||||
return string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
return string.Format(raw, args);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[LanguageManager] Format failed for key: {key}\n{ex}");
|
||||
return raw; // 최소한 원문이라도 보여주기
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b4990eee90808bc488656e484f9ea0d8
|
||||
8
Assets/@Eden_Tools/Eden_AutoMorpher/ProfileSaver.meta
Normal file
8
Assets/@Eden_Tools/Eden_AutoMorpher/ProfileSaver.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3f15b8b51b341c647a98a34a47707efb
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 42ffaa733fd3b8f4bb16b48ac9321699
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9edd784ea5aea9d419070655b91a1ade
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f4b157cb0292d6a43b5b593c5d80b658
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 06e603c0e6910f74e8ae69f4b1025e99
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a87e8255c6175649ab3d14c5d7390a0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 33819e87e935234448269d35d6e155b5
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8d3573fd768baee41b6e2b78d647bf04
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 48d80c2519b3d8b4a97a8d6d5cd7b159
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2fd1a8210b48a8d49843a3f2859e67b6
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ba923ad66ccb9824aa21217281bc8f03
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ca85c008bacb4c04fab51354ef3d6365
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1b9accce356c005478e76fd0fa193f3a
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d62ebbd77f472fd4bb8abf3546d9d12a
|
||||
@@ -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]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 08f2754ac23e3bd419413380289a1d1f
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0575b5a00bd94c64d96d49da0465ee70
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c2016668835db4f418cb2b3ef14bd00e
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b987b9b34807b3b48b843afcb2aefa28
|
||||
@@ -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]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 404cff939caffe44bbb6cfbb33580445
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 094b9fc668fbf684aa9bd5db84b2aaad
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 26eb8c4f9b6a08e4abb70a33d9b81ccf
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b1bc4188262eb1140b111907361dfc56
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c9990806ed64171428cb56bac9d781fa
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3e693ae64a726864a88a172c17d13af9
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d1647fc2736619c4fbf9804e952bf2c6
|
||||
8
Assets/@Eden_Tools/Eden_AutoMorpher/Profiles.meta
Normal file
8
Assets/@Eden_Tools/Eden_AutoMorpher/Profiles.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e2a1bcfd751cc3849a426ce40c0cc77a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/@Eden_Tools/Eden_AutoMorpher/Profiles/Milfy.meta
Normal file
8
Assets/@Eden_Tools/Eden_AutoMorpher/Profiles/Milfy.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e7a2f45922601af4b8c5ddf7a2690616
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 089a65b7b2de5d340be9185301f4742b
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
5307
Assets/@Eden_Tools/Eden_AutoMorpher/Profiles/Milfy/Milfy.json
Normal file
5307
Assets/@Eden_Tools/Eden_AutoMorpher/Profiles/Milfy/Milfy.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fac35f9984a9b074b96aef1277e7c9e2
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fa918e3ca04b78e468ae9f5a1de3a753
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1ae9d7589452c7249b1f5273111af6fc
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8f11fb0ea5a15f347b7e8562f8b474f8
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5a6c324ec591f174cbc97744c8447ff6
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e4bed78da4a082428935e1820a5034f
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d5c9a011babea74aba9abf5a8f4bf56
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ef45d213589843a4ebe6d9b7a5b24247
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 175670fba1461ee44938eef5d12c329e
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 42349d897410ba04dbc6958029fe7b7c
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7b3fe5d7e8d8b8d46b1961db5f53753e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ea3639083c9301544b84c17809fce603
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 24eca8dc2fe8df84f9a0ea6d286044fb
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1041a0f4b4eaa5445800c894655b3715
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user