diff --git a/Editor/MeshSettingsPass.cs b/Editor/MeshSettingsPass.cs index 4382fc07..3c8df32a 100644 --- a/Editor/MeshSettingsPass.cs +++ b/Editor/MeshSettingsPass.cs @@ -1,5 +1,8 @@ -using System.Linq; +using System; +using System.Collections.Generic; +using System.Linq; using UnityEngine; +using Object = UnityEngine.Object; namespace nadena.dev.modular_avatar.core.editor { @@ -50,12 +53,12 @@ namespace nadena.dev.modular_avatar.core.editor or ModularAvatarMeshSettings.InheritMode.Inherit or ModularAvatarMeshSettings.InheritMode.DontSet or ModularAvatarMeshSettings.InheritMode.SetOrInherit), _): - throw new System.InvalidOperationException($"Logic failure: invalid InheritMode: {currentMode}"); + throw new InvalidOperationException($"Logic failure: invalid InheritMode: {currentMode}"); case (_, not (ModularAvatarMeshSettings.InheritMode.Set or ModularAvatarMeshSettings.InheritMode.Inherit or ModularAvatarMeshSettings.InheritMode.DontSet or ModularAvatarMeshSettings.InheritMode.SetOrInherit)): - throw new System.ArgumentOutOfRangeException(nameof(srcMode), $"Invalid InheritMode: {srcMode}"); + throw new ArgumentOutOfRangeException(nameof(srcMode), $"Invalid InheritMode: {srcMode}"); // If current value is came from Set or DontSet, it should not be changed case (ModularAvatarMeshSettings.InheritMode.Set, _): @@ -144,9 +147,56 @@ namespace nadena.dev.modular_avatar.core.editor if (newMesh) context.SaveAsset(newMesh); } - smr.rootBone = settings.RootBone; - smr.localBounds = settings.Bounds; + + var settingsRootBone = settings.RootBone; + settingsRootBone = settingsRootBone == null ? smr.transform : settingsRootBone; + var smrRootBone = smr.rootBone; + smrRootBone = smrRootBone == null ? smr.transform : smrRootBone; + + if (IsInverted(smrRootBone) != IsInverted(settingsRootBone)) + { + smr.rootBone = GetInvertedRootBone(settingsRootBone); + + var bounds = settings.Bounds; + var center = bounds.center; + center.x *= -1; + bounds.center = center; + smr.localBounds = bounds; + } + else + { + smr.rootBone = settings.RootBone; + smr.localBounds = settings.Bounds; + } } } + + private bool IsInverted(Transform bone) + { + var inverseCount = 0; + + var scale = bone.lossyScale; + if (scale.x < 0) inverseCount += 1; + if (scale.y < 0) inverseCount += 1; + if (scale.z < 0) inverseCount += 1; + + return (inverseCount % 2) != 0; + } + private Dictionary invertedRootBoneCache = new(); + private Transform GetInvertedRootBone(Transform rootBone) + { + if (invertedRootBoneCache.TryGetValue(rootBone, out var cache)) { return cache; } + + var cloned = Object.Instantiate(rootBone.gameObject, rootBone, true); + cloned.name = rootBone.gameObject.name + "-InvertedRootBone"; + + var invertedRootBone = cloned.transform; + var scale = invertedRootBone.localScale; + scale.x *= -1; + invertedRootBone.localScale = scale; + + invertedRootBoneCache[rootBone] = invertedRootBone; + return invertedRootBone; + } } -} \ No newline at end of file +}