From c7fc420d14f5924e2531dd1ff0267705c21be377 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Mon, 16 May 2022 14:07:20 +0900 Subject: [PATCH 01/19] =?UTF-8?q?=E3=82=B3=E3=83=BC=E3=83=89=E6=95=B4?= =?UTF-8?q?=E7=90=86=E3=80=81=E6=9C=AA=E4=BD=BF=E7=94=A8=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MeshUtility/BoneMeshEraserWizard.cs | 190 ------------------ .../MeshUtility/BoneMeshEraserWizard.cs.meta | 13 -- .../Editor/MeshUtility/MeshProcessDialog.cs | 33 ++- .../MeshUtility/MeshProcessDialogEditor.cs | 34 +++- .../{Tabs.cs => MeshProcessDialogTabs.cs} | 2 +- ....cs.meta => MeshProcessDialogTabs.cs.meta} | 2 +- .../Editor/MeshUtility/TabBoneMeshRemover.cs | 5 +- .../UniGLTF/Editor/MeshUtility/Tabs.cs.meta | 11 - .../Editor/MeshUtility/TextureSaver.cs | 57 ------ 9 files changed, 45 insertions(+), 302 deletions(-) delete mode 100644 Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserWizard.cs delete mode 100644 Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserWizard.cs.meta rename Assets/UniGLTF/Editor/MeshUtility/{Tabs.cs => MeshProcessDialogTabs.cs} (75%) rename Assets/UniGLTF/Editor/MeshUtility/{TextureSaver.cs.meta => MeshProcessDialogTabs.cs.meta} (83%) delete mode 100644 Assets/UniGLTF/Editor/MeshUtility/Tabs.cs.meta delete mode 100644 Assets/UniGLTF/Editor/MeshUtility/TextureSaver.cs diff --git a/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserWizard.cs b/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserWizard.cs deleted file mode 100644 index 4e0c71201..000000000 --- a/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserWizard.cs +++ /dev/null @@ -1,190 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEditor; -using UnityEngine; - - -namespace UniGLTF.MeshUtility -{ - [CustomPropertyDrawer(typeof(BoneMeshEraser.EraseBone))] - public class EraseBoneDrawer : PropertyDrawer - { - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - //EditorGUI.BeginProperty(position, label, property); - - var leftWidth = 0.6f; - var rightWidth = 1.0f - leftWidth; - - var leftSide = new Rect(position.x, position.y, position.width * leftWidth, position.height); - var rightSide = new Rect(position.width * leftWidth, position.y, position.width * rightWidth, position.height); - { - EditorGUI.PropertyField(leftSide, property.FindPropertyRelative("Bone"), new GUIContent("", "")); - EditorGUI.PropertyField(rightSide, property.FindPropertyRelative("Erase")); - } - - //EditorGUI.EndProperty(); - } - - public override float GetPropertyHeight(SerializedProperty property, GUIContent label) - { - var height = base.GetPropertyHeight(property, label); - return height; - } - } - - public class BoneMeshEraserWizard : ScriptableWizard - { - public const string BONE_MESH_ERASER_NAME = "BoneMeshEraser"; - const string ASSET_SUFFIX = ".asset"; - - [SerializeField] - SkinnedMeshRenderer m_skinnedMesh; - - [SerializeField] - Animator m_animator; - - [SerializeField] - Transform EraseRoot; - - [SerializeField] - BoneMeshEraser.EraseBone[] m_eraseBones; - - private void OnEnable() - { - var root = Selection.activeGameObject; - if (root != null) - { - m_animator = root.GetComponent(); - m_skinnedMesh = root.GetComponent(); - OnValidate(); - } - } - - void OnValidate() - { - //Debug.Log("OnValidate"); - if (m_skinnedMesh == null) - { - m_eraseBones = new BoneMeshEraser.EraseBone[] { }; - return; - } - - if (EraseRoot == null) - { - if (m_animator != null) - { - EraseRoot = m_animator.GetBoneTransform(HumanBodyBones.Head); - //Debug.LogFormat("head: {0}", EraseRoot); - } - } - - m_eraseBones = m_skinnedMesh.bones.Select(x => - { - var eb = new BoneMeshEraser.EraseBone - { - Bone = x, - }; - - if (EraseRoot != null) - { - // 首の子孫を消去 - if (eb.Bone.Ancestor().Any(y => y == EraseRoot)) - { - //Debug.LogFormat("erase {0}", x); - eb.Erase = true; - } - } - - return eb; - }) - .ToArray(); - } - - void OnWizardUpdate() - { - helpString = "select target skinnedMesh and animator"; - } - - SkinnedMeshRenderer _Erase(GameObject go) - { - if (go == null) - { - Debug.LogWarning("select root object in hierarchy"); - return null; - } - if (m_skinnedMesh == null) - { - Debug.LogWarning("no skinnedmesh"); - return null; - } - - var bones = m_skinnedMesh.bones; - var eraseBones = m_eraseBones - .Where(x => x.Erase) - .Select(x => Array.IndexOf(bones, x.Bone)) - .ToArray(); - - var meshNode = new GameObject(BONE_MESH_ERASER_NAME); - meshNode.transform.SetParent(go.transform, false); - - var erased = meshNode.AddComponent(); - erased.sharedMesh = BoneMeshEraser.CreateErasedMesh(m_skinnedMesh.sharedMesh, eraseBones); - erased.sharedMaterials = m_skinnedMesh.sharedMaterials; - erased.bones = m_skinnedMesh.bones; - - return erased; - } - - public static UnityEngine.Object GetPrefab(GameObject instance) - { -#if UNITY_2018_2_OR_NEWER - return PrefabUtility.GetCorrespondingObjectFromSource(instance); -#else - return PrefabUtility.GetPrefabParent(go); -#endif - } - - void Erase() - { - var go = Selection.activeGameObject; - var renderer = _Erase(go); - if (renderer == null) - { - return; - } - - // save mesh to Assets - var assetPath = string.Format("{0}{1}", go.name, ASSET_SUFFIX); - var prefab = GetPrefab(go); - if (prefab != null) - { - var prefabPath = AssetDatabase.GetAssetPath(prefab); - assetPath = string.Format("{0}/{1}{2}", - Path.GetDirectoryName(prefabPath), - Path.GetFileNameWithoutExtension(prefabPath), - ASSET_SUFFIX - ); - } - - Debug.LogFormat("CreateAsset: {0}", assetPath); - AssetDatabase.CreateAsset(renderer.sharedMesh, assetPath); - } - - void OnWizardCreate() - { - //Debug.Log("OnWizardCreate"); - Erase(); - - // close - } - - void OnWizardOtherButton() - { - //Debug.Log("OnWizardOtherButton"); - Erase(); - } - } -} diff --git a/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserWizard.cs.meta b/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserWizard.cs.meta deleted file mode 100644 index ef9f39767..000000000 --- a/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserWizard.cs.meta +++ /dev/null @@ -1,13 +0,0 @@ -fileFormatVersion: 2 -guid: 881b00db73f639c48a3f043a775fa61a -timeCreated: 1518503829 -licenseType: Free -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs index a5a4c97e7..72c5f26d0 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs @@ -9,7 +9,8 @@ namespace UniGLTF.MeshUtility { public class MeshProcessDialog : EditorWindow { - private Tabs _tab; + const string TITLE = "Mesh Processing Window"; + public MeshProcessDialogTabs Tab; private GameObject _exportTarget; @@ -21,16 +22,16 @@ namespace UniGLTF.MeshUtility private Vector2 _scrollPos = new Vector2(0, 0); [SerializeField] - private SkinnedMeshRenderer _cSkinnedMesh = null; + public SkinnedMeshRenderer _skinnedMesh = null; [SerializeField] - private bool _separateByBlendShape = true; + public bool _separateByBlendShape = true; private Animator _cAnimator = null; private Transform _cEraseRoot = null; [SerializeField] - private BoneMeshEraser.EraseBone[] _eraseBones; + public BoneMeshEraser.EraseBone[] _eraseBones; private MethodInfo _processFunction; @@ -42,7 +43,7 @@ namespace UniGLTF.MeshUtility { var window = (MeshProcessDialog)EditorWindow.GetWindow(typeof(MeshProcessDialog)); - window.titleContent = new GUIContent("Mesh Processing Window"); + window.titleContent = new GUIContent(TITLE); window.Show(); } @@ -78,18 +79,17 @@ namespace UniGLTF.MeshUtility } // tab - _tab = TabBar.OnGUI(_tab, _tabButtonStyle, _tabButtonSize); + Tab = TabBar.OnGUI(Tab, _tabButtonStyle, _tabButtonSize); var processed = false; - switch (_tab) + switch (Tab) { - case Tabs.MeshSeparator: + case MeshProcessDialogTabs.MeshSeparator: EditorGUILayout.HelpBox(MeshProcessingMessages.MESH_SEPARATOR.Msg(), MessageType.Info); processed = TabMeshSeparator.OnGUI(_exportTarget); break; - case Tabs.MeshIntegrator: + case MeshProcessDialogTabs.MeshIntegrator: EditorGUILayout.HelpBox(MeshProcessingMessages.MESH_INTEGRATOR.Msg(), MessageType.Info); - _boneMeshEraserEditor.Tabs = _tab; if (_boneMeshEraserEditor) { _boneMeshEraserEditor.OnInspectorGUI(); @@ -97,22 +97,21 @@ namespace UniGLTF.MeshUtility processed = TabMeshIntegrator.OnGUI(_exportTarget, _separateByBlendShape); break; - case Tabs.BoneMeshEraser: + case MeshProcessDialogTabs.BoneMeshEraser: EditorGUILayout.HelpBox(MeshProcessingMessages.BONE_MESH_ERASER.Msg(), MessageType.Info); - _boneMeshEraserEditor.Tabs = _tab; if (_boneMeshEraserEditor) { _boneMeshEraserEditor.OnInspectorGUI(); } // any better way we can detect component change? - if (_cSkinnedMesh != _pSkinnedMesh || _cAnimator != _pAnimator || _cEraseRoot != _pEraseRoot) + if (_skinnedMesh != _pSkinnedMesh || _cAnimator != _pAnimator || _cEraseRoot != _pEraseRoot) { BoneMeshEraserValidate(); } - _pSkinnedMesh = _cSkinnedMesh; + _pSkinnedMesh = _skinnedMesh; _pAnimator = _cAnimator; _pEraseRoot = _cEraseRoot; - processed = TabBoneMeshRemover.OnGUI(_exportTarget, _cSkinnedMesh, _eraseBones); + processed = TabBoneMeshRemover.OnGUI(_exportTarget, _skinnedMesh, _eraseBones); break; } EditorGUILayout.EndScrollView(); @@ -127,7 +126,7 @@ namespace UniGLTF.MeshUtility private void BoneMeshEraserValidate() { - if (_cSkinnedMesh == null) + if (_skinnedMesh == null) { _eraseBones = new BoneMeshEraser.EraseBone[] { }; return; @@ -142,7 +141,7 @@ namespace UniGLTF.MeshUtility } } - _eraseBones = _cSkinnedMesh.bones.Select(x => + _eraseBones = _skinnedMesh.bones.Select(x => { var eb = new BoneMeshEraser.EraseBone { diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogEditor.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogEditor.cs index db7929a0a..23c6c963b 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogEditor.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogEditor.cs @@ -7,26 +7,40 @@ namespace UniGLTF.MeshUtility [CustomEditor(typeof(MeshProcessDialog), true)] class MeshProcessDialogEditor : Editor { - public Tabs Tabs; + MeshProcessDialog _targetDialog; + SerializedProperty _separateByBlendShape; + SerializedProperty _skinnedMesh; + SerializedProperty _eraseBones; + + void OnEnable() + { + _targetDialog = (MeshProcessDialog)target; + _separateByBlendShape = serializedObject.FindProperty(nameof(MeshProcessDialog._separateByBlendShape)); + _skinnedMesh = serializedObject.FindProperty(nameof(MeshProcessDialog._skinnedMesh)); + _eraseBones = serializedObject.FindProperty(nameof(MeshProcessDialog._eraseBones)); + } public override void OnInspectorGUI() { serializedObject.Update(); - switch (Tabs) + switch (_targetDialog.Tab) { - case Tabs.MeshIntegrator: + case MeshProcessDialogTabs.MeshSeparator: { - var skinnedMesh = serializedObject.FindProperty("_separateByBlendShape"); - EditorGUILayout.PropertyField(skinnedMesh, new GUIContent(MeshProcessingMessages.MESH_SEPARATOR_BY_BLENDSHAPE.Msg())); + // no properties break; } - case Tabs.BoneMeshEraser: + case MeshProcessDialogTabs.MeshIntegrator: { - var skinnedMesh = serializedObject.FindProperty("_cSkinnedMesh"); - EditorGUILayout.PropertyField(skinnedMesh, new GUIContent("Skinned Mesh"), true); - var list = serializedObject.FindProperty("_eraseBones"); - EditorGUILayout.PropertyField(list, new GUIContent("Erase Bones"), true); + EditorGUILayout.PropertyField(_separateByBlendShape, new GUIContent(MeshProcessingMessages.MESH_SEPARATOR_BY_BLENDSHAPE.Msg())); + break; + } + + case MeshProcessDialogTabs.BoneMeshEraser: + { + EditorGUILayout.PropertyField(_skinnedMesh); + EditorGUILayout.PropertyField(_eraseBones); break; } } diff --git a/Assets/UniGLTF/Editor/MeshUtility/Tabs.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogTabs.cs similarity index 75% rename from Assets/UniGLTF/Editor/MeshUtility/Tabs.cs rename to Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogTabs.cs index dbc064734..87ad28880 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/Tabs.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogTabs.cs @@ -1,6 +1,6 @@ namespace UniGLTF.MeshUtility { - enum Tabs + public enum MeshProcessDialogTabs { MeshSeparator, MeshIntegrator, diff --git a/Assets/UniGLTF/Editor/MeshUtility/TextureSaver.cs.meta b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogTabs.cs.meta similarity index 83% rename from Assets/UniGLTF/Editor/MeshUtility/TextureSaver.cs.meta rename to Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogTabs.cs.meta index 733e8bdc1..76e129bdc 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/TextureSaver.cs.meta +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogTabs.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 01c8541cb3fd27f4882e3d32c37a45aa +guid: 829a678062065f04582189619babae79 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs b/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs index 812fd8a52..672adccc7 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs @@ -9,6 +9,7 @@ namespace UniGLTF.MeshUtility { public static class TabBoneMeshRemover { + const string BONE_MESH_ERASER_NAME = "BoneMeshEraser"; const string ASSET_SUFFIX = ".mesh.asset"; public static bool OnGUI(GameObject root, SkinnedMeshRenderer smr, BoneMeshEraser.EraseBone[] eraseBones) @@ -44,7 +45,7 @@ namespace UniGLTF.MeshUtility var bones = smr.bones; - var meshNode = new GameObject(BoneMeshEraserWizard.BONE_MESH_ERASER_NAME); + var meshNode = new GameObject(BONE_MESH_ERASER_NAME); meshNode.transform.SetParent(root.transform, false); var erased = meshNode.AddComponent(); @@ -74,7 +75,7 @@ namespace UniGLTF.MeshUtility // destroy BoneMeshEraser in the source foreach (var skinnedMesh in root.GetComponentsInChildren()) { - if (skinnedMesh.gameObject.name == BoneMeshEraserWizard.BONE_MESH_ERASER_NAME) + if (skinnedMesh.gameObject.name == BONE_MESH_ERASER_NAME) { GameObject.DestroyImmediate(skinnedMesh.gameObject); } diff --git a/Assets/UniGLTF/Editor/MeshUtility/Tabs.cs.meta b/Assets/UniGLTF/Editor/MeshUtility/Tabs.cs.meta deleted file mode 100644 index 485c04f70..000000000 --- a/Assets/UniGLTF/Editor/MeshUtility/Tabs.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 57ace5e28eb8e7746b00eaa9405197a9 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/UniGLTF/Editor/MeshUtility/TextureSaver.cs b/Assets/UniGLTF/Editor/MeshUtility/TextureSaver.cs deleted file mode 100644 index 02bec1797..000000000 --- a/Assets/UniGLTF/Editor/MeshUtility/TextureSaver.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System.IO; -using UnityEditor; -using UnityEngine; -using VRMShaders; -using ColorSpace = VRMShaders.ColorSpace; - -namespace UniGLTF.MeshUtility -{ - public static class EditorChangeTextureType - { - public static void SaveAsPng(bool sRGB) - { - var texture = Selection.activeObject as Texture2D; - var path = SaveDialog(AssetsPath.FromAsset(texture)); - if (string.IsNullOrEmpty(path)) - { - return; - } - - var (tex, mime) = new EditorTextureSerializer().ExportBytesWithMime(texture, sRGB ? ColorSpace.sRGB : ColorSpace.Linear); - - File.WriteAllBytes(path, tex); - Debug.Log($"save: {path}"); - - var assetsPath = AssetsPath.FromFullpath(path); - - EditorApplication.delayCall += () => - { - assetsPath.ImportAsset(); - var importer = assetsPath.GetImporter(); - if (importer == null) - { - Debug.LogWarningFormat("fail to get TextureImporter: {0}", assetsPath); - } - importer.sRGBTexture = sRGB; - importer.SaveAndReimport(); - Debug.Log($"sRGB: {sRGB}"); - }; - } - - private static string m_lastExportDir; - static string SaveDialog(AssetsPath assetsPath) - { - // save dialog - var path = EditorUtility.SaveFilePanel( - "Save png", - assetsPath.Parent.FullPath, - $"{assetsPath.FileNameWithoutExtension}.png", - "png"); - if (!string.IsNullOrEmpty(path)) - { - m_lastExportDir = Path.GetDirectoryName(path).Replace("\\", "/"); - } - return path; - } - } -} From d9208010169aa00c385062546712e204aa9c1a34 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Mon, 16 May 2022 15:06:56 +0900 Subject: [PATCH 02/19] =?UTF-8?q?BoneMeshRemoverValidator=20=E9=9A=94?= =?UTF-8?q?=E9=9B=A2=E3=80=82MeshProcessDialog=20=E6=95=B4=E7=90=86?= =?UTF-8?q?=E3=80=82=E5=A4=89=E6=95=B0=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MeshUtility/BoneMeshRemoverValidator.cs | 66 +++++++++++ .../BoneMeshRemoverValidator.cs.meta | 11 ++ .../Editor/MeshUtility/MeshProcessDialog.cs | 109 +++++------------- .../MeshUtility/MeshProcessDialogEditor.cs | 38 +++--- .../Editor/MeshUtility/TabBoneMeshRemover.cs | 5 +- 5 files changed, 121 insertions(+), 108 deletions(-) create mode 100644 Assets/UniGLTF/Editor/MeshUtility/BoneMeshRemoverValidator.cs create mode 100644 Assets/UniGLTF/Editor/MeshUtility/BoneMeshRemoverValidator.cs.meta diff --git a/Assets/UniGLTF/Editor/MeshUtility/BoneMeshRemoverValidator.cs b/Assets/UniGLTF/Editor/MeshUtility/BoneMeshRemoverValidator.cs new file mode 100644 index 000000000..29d4b7c24 --- /dev/null +++ b/Assets/UniGLTF/Editor/MeshUtility/BoneMeshRemoverValidator.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace UniGLTF.MeshUtility +{ + public class BoneMeshRemoverValidator + { + private Animator _cAnimator = null; + private Transform _cEraseRoot = null; + private SkinnedMeshRenderer _pSkinnedMesh; + private Animator _pAnimator; + private Transform _pEraseRoot; + + public void Validate(SkinnedMeshRenderer _skinnedMesh, List _eraseBones) + { + // any better way we can detect component change? + if (_skinnedMesh != _pSkinnedMesh || _cAnimator != _pAnimator || _cEraseRoot != _pEraseRoot) + { + BoneMeshEraserValidate(_skinnedMesh, _eraseBones); + } + _pSkinnedMesh = _skinnedMesh; + _pAnimator = _cAnimator; + _pEraseRoot = _cEraseRoot; + } + + void BoneMeshEraserValidate(SkinnedMeshRenderer skinnedMeshRenderer, List eraseBones) + { + eraseBones.Clear(); + if (skinnedMeshRenderer == null) + { + return; + } + + if (_cEraseRoot == null) + { + if (_cAnimator != null) + { + _cEraseRoot = _cAnimator.GetBoneTransform(HumanBodyBones.Head); + //Debug.LogFormat("head: {0}", EraseRoot); + } + } + + eraseBones.AddRange(skinnedMeshRenderer.bones.Select(x => + { + var eb = new BoneMeshEraser.EraseBone + { + Bone = x, + }; + + if (_cEraseRoot != null) + { + // 首の子孫を消去 + if (eb.Bone.Ancestor().Any(y => y == _cEraseRoot)) + { + //Debug.LogFormat("erase {0}", x); + eb.Erase = true; + } + } + + return eb; + })); + } + } +} diff --git a/Assets/UniGLTF/Editor/MeshUtility/BoneMeshRemoverValidator.cs.meta b/Assets/UniGLTF/Editor/MeshUtility/BoneMeshRemoverValidator.cs.meta new file mode 100644 index 000000000..48f27b214 --- /dev/null +++ b/Assets/UniGLTF/Editor/MeshUtility/BoneMeshRemoverValidator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fb28fac2e7b5e684fb023a88862106f0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs index 72c5f26d0..6b5c6e87f 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs @@ -1,9 +1,7 @@ -using System.Linq; -using System.Reflection; using UnityEngine; using UnityEditor; -using UniGLTF; using UniGLTF.M17N; +using System.Collections.Generic; namespace UniGLTF.MeshUtility { @@ -14,30 +12,19 @@ namespace UniGLTF.MeshUtility private GameObject _exportTarget; - private MeshProcessDialogEditor _boneMeshEraserEditor; - - private SkinnedMeshRenderer _pSkinnedMesh; - private Animator _pAnimator; - private Transform _pEraseRoot; - private Vector2 _scrollPos = new Vector2(0, 0); - - [SerializeField] - public SkinnedMeshRenderer _skinnedMesh = null; + public BoneMeshRemoverValidator _boneMeshRemoverValidator = new BoneMeshRemoverValidator(); [SerializeField] public bool _separateByBlendShape = true; - private Animator _cAnimator = null; - private Transform _cEraseRoot = null; + [SerializeField] + public SkinnedMeshRenderer _skinnedMeshRenderer = null; [SerializeField] - public BoneMeshEraser.EraseBone[] _eraseBones; - - private MethodInfo _processFunction; - - GUIStyle _tabButtonStyle => "LargeButton"; - GUI.ToolbarButtonSize _tabButtonSize => GUI.ToolbarButtonSize.Fixed; + public List _eraseBones; + private MeshProcessDialogEditor _boneMeshEraserEditor; + private Vector2 _scrollPos = new Vector2(0, 0); public static void OpenWindow() { @@ -68,10 +55,12 @@ namespace UniGLTF.MeshUtility LanguageGetter.OnGuiSelectLang(); { + // _exportTarget EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(MeshProcessingMessages.TARGET_OBJECT.Msg(), GUILayout.MaxWidth(146.0f)); _exportTarget = (GameObject)EditorGUILayout.ObjectField(_exportTarget, typeof(GameObject), true); EditorGUILayout.EndHorizontal(); + // auto select ? if (_exportTarget == null && IsGameObjectSelected()) { _exportTarget = Selection.activeObject as GameObject; @@ -79,40 +68,36 @@ namespace UniGLTF.MeshUtility } // tab - Tab = TabBar.OnGUI(Tab, _tabButtonStyle, _tabButtonSize); + Tab = TabBar.OnGUI(Tab, "LargeButton", GUI.ToolbarButtonSize.Fixed); var processed = false; switch (Tab) { case MeshProcessDialogTabs.MeshSeparator: - EditorGUILayout.HelpBox(MeshProcessingMessages.MESH_SEPARATOR.Msg(), MessageType.Info); - processed = TabMeshSeparator.OnGUI(_exportTarget); - break; + { + EditorGUILayout.HelpBox(MeshProcessingMessages.MESH_SEPARATOR.Msg(), MessageType.Info); + processed = TabMeshSeparator.OnGUI(_exportTarget); + break; + } case MeshProcessDialogTabs.MeshIntegrator: - EditorGUILayout.HelpBox(MeshProcessingMessages.MESH_INTEGRATOR.Msg(), MessageType.Info); - if (_boneMeshEraserEditor) { - _boneMeshEraserEditor.OnInspectorGUI(); + EditorGUILayout.HelpBox(MeshProcessingMessages.MESH_INTEGRATOR.Msg(), MessageType.Info); + _separateByBlendShape = EditorGUILayout.Toggle(MeshProcessingMessages.MESH_SEPARATOR_BY_BLENDSHAPE.Msg(), _separateByBlendShape); + processed = TabMeshIntegrator.OnGUI(_exportTarget, _separateByBlendShape); + break; } - processed = TabMeshIntegrator.OnGUI(_exportTarget, _separateByBlendShape); - break; case MeshProcessDialogTabs.BoneMeshEraser: - EditorGUILayout.HelpBox(MeshProcessingMessages.BONE_MESH_ERASER.Msg(), MessageType.Info); - if (_boneMeshEraserEditor) { - _boneMeshEraserEditor.OnInspectorGUI(); + EditorGUILayout.HelpBox(MeshProcessingMessages.BONE_MESH_ERASER.Msg(), MessageType.Info); + if (_boneMeshEraserEditor) + { + _boneMeshEraserEditor.OnInspectorGUI(); + } + _boneMeshRemoverValidator.Validate(_skinnedMeshRenderer, _eraseBones); + processed = TabBoneMeshRemover.OnGUI(_exportTarget, _skinnedMeshRenderer, _eraseBones); + break; } - // any better way we can detect component change? - if (_skinnedMesh != _pSkinnedMesh || _cAnimator != _pAnimator || _cEraseRoot != _pEraseRoot) - { - BoneMeshEraserValidate(); - } - _pSkinnedMesh = _skinnedMesh; - _pAnimator = _cAnimator; - _pEraseRoot = _cEraseRoot; - processed = TabBoneMeshRemover.OnGUI(_exportTarget, _skinnedMesh, _eraseBones); - break; } EditorGUILayout.EndScrollView(); @@ -122,45 +107,5 @@ namespace UniGLTF.MeshUtility GUIUtility.ExitGUI(); } } - - - private void BoneMeshEraserValidate() - { - if (_skinnedMesh == null) - { - _eraseBones = new BoneMeshEraser.EraseBone[] { }; - return; - } - - if (_cEraseRoot == null) - { - if (_cAnimator != null) - { - _cEraseRoot = _cAnimator.GetBoneTransform(HumanBodyBones.Head); - //Debug.LogFormat("head: {0}", EraseRoot); - } - } - - _eraseBones = _skinnedMesh.bones.Select(x => - { - var eb = new BoneMeshEraser.EraseBone - { - Bone = x, - }; - - if (_cEraseRoot != null) - { - // 首の子孫を消去 - if (eb.Bone.Ancestor().Any(y => y == _cEraseRoot)) - { - //Debug.LogFormat("erase {0}", x); - eb.Erase = true; - } - } - - return eb; - }) - .ToArray(); - } } } \ No newline at end of file diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogEditor.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogEditor.cs index 23c6c963b..b262b3401 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogEditor.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogEditor.cs @@ -4,46 +4,36 @@ using UnityEngine; namespace UniGLTF.MeshUtility { + /// + /// BoneMeshRemover 向けのエディタ。 + /// + /// SerializedProperty 経由で ユーザー定義 struct のフィールド + /// public List _eraseBones; + /// を EditorGUILayout.PropertyField するための細工である。 + /// + /// SerializedObject は UnityEngine.Object から作成するので、 + /// UnityEngine.Object を継承したクラスのフィールドに ユーザー定義 struct を配置する。 + /// 持ち主の SerializedObject を経由して EditorGUILayout.PropertyField してる。 + /// [CustomEditor(typeof(MeshProcessDialog), true)] class MeshProcessDialogEditor : Editor { MeshProcessDialog _targetDialog; - SerializedProperty _separateByBlendShape; SerializedProperty _skinnedMesh; SerializedProperty _eraseBones; void OnEnable() { _targetDialog = (MeshProcessDialog)target; - _separateByBlendShape = serializedObject.FindProperty(nameof(MeshProcessDialog._separateByBlendShape)); - _skinnedMesh = serializedObject.FindProperty(nameof(MeshProcessDialog._skinnedMesh)); + _skinnedMesh = serializedObject.FindProperty(nameof(MeshProcessDialog._skinnedMeshRenderer)); _eraseBones = serializedObject.FindProperty(nameof(MeshProcessDialog._eraseBones)); } public override void OnInspectorGUI() { serializedObject.Update(); - switch (_targetDialog.Tab) - { - case MeshProcessDialogTabs.MeshSeparator: - { - // no properties - break; - } - - case MeshProcessDialogTabs.MeshIntegrator: - { - EditorGUILayout.PropertyField(_separateByBlendShape, new GUIContent(MeshProcessingMessages.MESH_SEPARATOR_BY_BLENDSHAPE.Msg())); - break; - } - - case MeshProcessDialogTabs.BoneMeshEraser: - { - EditorGUILayout.PropertyField(_skinnedMesh); - EditorGUILayout.PropertyField(_eraseBones); - break; - } - } + EditorGUILayout.PropertyField(_skinnedMesh); + EditorGUILayout.PropertyField(_eraseBones); serializedObject.ApplyModifiedProperties(); } } diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs b/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs index 672adccc7..0862413a5 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using UniGLTF.M17N; @@ -12,7 +13,7 @@ namespace UniGLTF.MeshUtility const string BONE_MESH_ERASER_NAME = "BoneMeshEraser"; const string ASSET_SUFFIX = ".mesh.asset"; - public static bool OnGUI(GameObject root, SkinnedMeshRenderer smr, BoneMeshEraser.EraseBone[] eraseBones) + public static bool OnGUI(GameObject root, SkinnedMeshRenderer smr, List eraseBones) { var _isInvokeSuccess = false; GUILayout.BeginVertical(); @@ -29,7 +30,7 @@ namespace UniGLTF.MeshUtility return _isInvokeSuccess; } - private static bool Execute(GameObject root, SkinnedMeshRenderer smr, BoneMeshEraser.EraseBone[] eraseBones) + private static bool Execute(GameObject root, SkinnedMeshRenderer smr, List eraseBones) { if (root == null) { From 1b01d6d8d7a4c869cb7de5da18c543cf666e5043 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Mon, 16 May 2022 15:26:56 +0900 Subject: [PATCH 03/19] Intgrate --- Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs | 2 +- Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs index 4e2db9cdb..81759c546 100644 --- a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs +++ b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs @@ -230,7 +230,7 @@ namespace UniGLTF.MeshUtility } } - public void Intgrate(MeshEnumerateOption onlyBlendShapeRenderers) + public void Integrate(MeshEnumerateOption onlyBlendShapeRenderers) { var mesh = new Mesh(); diff --git a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs index 87f44f189..5938452d1 100644 --- a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs +++ b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs @@ -87,7 +87,7 @@ namespace UniGLTF.MeshUtility } } - integrator.Intgrate(onlyBlendShapeRenderers); + integrator.Integrate(onlyBlendShapeRenderers); integrator.Result.IntegratedRenderer.transform.SetParent(go.transform, false); return integrator.Result; } From 5fd2a743a191eb52d6ef726b98349e83a9872ecc Mon Sep 17 00:00:00 2001 From: ousttrue Date: Mon, 16 May 2022 16:44:01 +0900 Subject: [PATCH 04/19] =?UTF-8?q?=E7=B5=B1=E5=90=88Mesh=E3=82=92=E3=83=92?= =?UTF-8?q?=E3=82=A8=E3=83=A9=E3=83=AB=E3=82=AD=E3=83=BC=E3=81=AB=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0=E3=81=99=E3=82=8B=E3=82=BF=E3=82=A4=E3=83=9F=E3=83=B3?= =?UTF-8?q?=E3=82=B0=E3=82=92=E3=82=B3=E3=83=94=E3=83=BC=E5=BE=8C=E3=81=AB?= =?UTF-8?q?=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Editor/MeshUtility/TabMeshIntegrator.cs | 84 ++----------------- .../Runtime/MeshUtility/MeshIntegrator.cs | 5 +- .../MeshUtility/MeshIntegratorUtility.cs | 61 +++++++++++++- .../VrmMeshIntegratorWizard.cs | 65 +++++++++++--- .../VRMMeshIntegratorUtility.cs | 33 +------- 5 files changed, 123 insertions(+), 125 deletions(-) diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs b/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs index ed366f531..66b19537d 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs @@ -1,4 +1,4 @@ -using System.IO; +using System.Collections.Generic; using UniGLTF.M17N; using UnityEditor; using UnityEngine; @@ -7,8 +7,6 @@ namespace UniGLTF.MeshUtility { public static class TabMeshIntegrator { - const string ASSET_SUFFIX = ".mesh.asset"; - public static bool OnGUI(GameObject root, bool onlyBlendShapeRenderers) { var _isInvokeSuccess = false; @@ -44,6 +42,7 @@ namespace UniGLTF.MeshUtility static bool Execute(GameObject root, bool onlyBlendShapeRenderers) { + // check if (root == null) { EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_GAMEOBJECT_SELECTED.Msg(), "ok"); @@ -62,87 +61,22 @@ namespace UniGLTF.MeshUtility return false; } + // execute + var results = new List(); if (onlyBlendShapeRenderers) { - MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithBlendShape); - MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithoutBlendShape); + results.Add(MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithBlendShape)); + results.Add(MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithoutBlendShape)); } else { - MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.All); + results.Add(MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.All)); } - CopyAndSaveAssetEtc(root); + // 統合結果を適用した新しいヒエラルキーをコピーから作成する + MeshIntegratorUtility.CopyAndReplaceWithResults(root, results); return true; } - - static void CopyAndSaveAssetEtc(GameObject root) - { - // copy hierarchy - var outputObject = GameObject.Instantiate(root); - outputObject.name = outputObject.name + "_mesh_integration"; - var skinnedMeshes = outputObject.GetComponentsInChildren(); - - // destroy integrated meshes in the source - foreach (var skinnedMesh in root.GetComponentsInChildren()) - { - if (skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_NAME || - skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_BLENDSHAPE_NAME) - { - GameObject.DestroyImmediate(skinnedMesh.gameObject); - } - } - foreach (var skinnedMesh in skinnedMeshes) - { - // destroy original meshes in the copied GameObject - if (!(skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_NAME || - skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_BLENDSHAPE_NAME)) - { - GameObject.DestroyImmediate(skinnedMesh); - } - // check if the integrated mesh is empty - else if (skinnedMesh.sharedMesh.subMeshCount == 0) - { - GameObject.DestroyImmediate(skinnedMesh.gameObject); - } - // save mesh data - else if (skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_NAME || - skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_BLENDSHAPE_NAME) - { - SaveMeshData(skinnedMesh.sharedMesh); - } - } - - var normalMeshes = outputObject.GetComponentsInChildren(); - foreach (var normalMesh in normalMeshes) - { - if (normalMesh.sharedMesh.name != MeshIntegratorUtility.INTEGRATED_MESH_NAME) - { - if (normalMesh.gameObject.GetComponent()) - { - GameObject.DestroyImmediate(normalMesh.gameObject.GetComponent()); - } - GameObject.DestroyImmediate(normalMesh); - } - } - } - - static void SaveMeshData(Mesh mesh) - { - var assetPath = string.Format("{0}{1}", Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX); - Debug.Log(assetPath); - if (!string.IsNullOrEmpty((AssetDatabase.GetAssetPath(mesh)))) - { - var directory = Path.GetDirectoryName(AssetDatabase.GetAssetPath(mesh)).Replace("\\", "/"); - assetPath = string.Format("{0}/{1}{2}", directory, Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX); - } - else - { - assetPath = string.Format("Assets/{0}{1}", Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX); - } - Debug.LogFormat("CreateAsset: {0}", assetPath); - AssetDatabase.CreateAsset(mesh, assetPath); - } } } diff --git a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs index 81759c546..f4ddfdd20 100644 --- a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs +++ b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs @@ -25,7 +25,7 @@ namespace UniGLTF.MeshUtility public Vector3[] Tangents; } - public MeshIntegrationResult Result { get; } = new MeshIntegrationResult(); + MeshIntegrationResult Result { get; } = new MeshIntegrationResult(); List Positions { get; } = new List(); List Normals { get; } = new List(); List UV { get; } = new List(); @@ -230,7 +230,7 @@ namespace UniGLTF.MeshUtility } } - public void Integrate(MeshEnumerateOption onlyBlendShapeRenderers) + public MeshIntegrationResult Integrate(MeshEnumerateOption onlyBlendShapeRenderers) { var mesh = new Mesh(); @@ -290,6 +290,7 @@ namespace UniGLTF.MeshUtility integrated.bones = Bones.ToArray(); Result.IntegratedRenderer = integrated; Result.MeshMap.Integrated = mesh; + return Result; } } } diff --git a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs index 5938452d1..f01b42dbc 100644 --- a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs +++ b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs @@ -1,10 +1,14 @@ using System.Collections.Generic; +using System.IO; +using UnityEditor; using UnityEngine; namespace UniGLTF.MeshUtility { public static class MeshIntegratorUtility { + const string ASSET_SUFFIX = ".mesh.asset"; + public static string INTEGRATED_MESH_NAME => MeshIntegrator.INTEGRATED_MESH_NAME; public static string INTEGRATED_MESH_BLENDSHAPE_NAME => MeshIntegrator.INTEGRATED_MESH_BLENDSHAPE_NAME; @@ -19,7 +23,9 @@ namespace UniGLTF.MeshUtility /// null: すべてのSkinnedMeshRenderer + MeshRenderer /// /// - public static MeshIntegrationResult Integrate(GameObject go, MeshEnumerateOption onlyBlendShapeRenderers, IEnumerable excludes = null) + public static MeshIntegrationResult Integrate(GameObject go, MeshEnumerateOption onlyBlendShapeRenderers, + IEnumerable excludes = null, + bool destroyIntegratedRenderer = false) { var exclude = new MeshExclude(excludes); @@ -87,9 +93,7 @@ namespace UniGLTF.MeshUtility } } - integrator.Integrate(onlyBlendShapeRenderers); - integrator.Result.IntegratedRenderer.transform.SetParent(go.transform, false); - return integrator.Result; + return integrator.Integrate(onlyBlendShapeRenderers); } public static IEnumerable EnumerateSkinnedMeshRenderer(Transform root, MeshEnumerateOption hasBlendShape) @@ -160,5 +164,54 @@ namespace UniGLTF.MeshUtility } } } + + public static void CopyAndReplaceWithResults(GameObject root, List results) + { + // copy hierarchy + var outputObject = GameObject.Instantiate(root); + outputObject.name = outputObject.name + "_mesh_integration"; + + // destroy original meshes in the copied GameObject + foreach (var skinnedMesh in outputObject.GetComponentsInChildren()) + { + GameObject.DestroyImmediate(skinnedMesh); + } + foreach (var normalMesh in outputObject.GetComponentsInChildren()) + { + if (normalMesh.sharedMesh.name != MeshIntegratorUtility.INTEGRATED_MESH_NAME) + { + if (normalMesh.gameObject.GetComponent()) + { + GameObject.DestroyImmediate(normalMesh.gameObject.GetComponent()); + } + GameObject.DestroyImmediate(normalMesh); + } + } + + foreach (var result in results) + { + // Add integrated + result.IntegratedRenderer.transform.SetParent(outputObject.transform, false); + // save mesh data + SaveMeshData(result.IntegratedRenderer.sharedMesh); + } + } + + static void SaveMeshData(Mesh mesh) + { + var assetPath = string.Format("{0}{1}", Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX); + Debug.Log(assetPath); + if (!string.IsNullOrEmpty((AssetDatabase.GetAssetPath(mesh)))) + { + var directory = Path.GetDirectoryName(AssetDatabase.GetAssetPath(mesh)).Replace("\\", "/"); + assetPath = string.Format("{0}/{1}{2}", directory, Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX); + } + else + { + assetPath = string.Format("Assets/{0}{1}", Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX); + } + Debug.LogFormat("CreateAsset: {0}", assetPath); + AssetDatabase.CreateAsset(mesh, assetPath); + } } } \ No newline at end of file diff --git a/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs b/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs index 3f991627b..a5db19875 100644 --- a/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs +++ b/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs @@ -217,6 +217,9 @@ namespace VRM // helpString = "Set target gameobject `in scene`. Prefab not supported."; } + /// + /// Prefab に対する操作として実装されている + /// void Integrate() { var prefabPath = AssetDatabase.GetAssetPath(m_root); @@ -241,33 +244,70 @@ namespace VRM Undo.RecordObject(m_root, "Mesh Integration"); var instance = VrmPrefabUtility.InstantiatePrefab(m_root); - var clips = new List(); var proxy = instance.GetComponent(); if (proxy != null && proxy.BlendShapeAvatar != null) { - clips = proxy.BlendShapeAvatar.Clips; + clips.AddRange(proxy.BlendShapeAvatar.Clips); } foreach (var clip in clips) { Undo.RecordObject(clip, "Mesh Integration"); } + _Integrate(instance, excludes, assetPath, clips); + + // destroy source renderers + UnityEngine.Object.DestroyImmediate(instance); + } + + void _Integrate(GameObject instance, IEnumerable excludes, UniGLTF.UnityPath assetPath, List clips) + { // Execute - var results = VRMMeshIntegratorUtility.Integrate(instance, clips, excludes, m_separateByBlendShape); - // integrationResults = MeshIntegratorEditor.Integrate(m_root, assetPath, excludes, m_separateByBlendShape).Select(x => x.MeshMap).ToArray(); - // public static List Integrate(GameObject prefab, UniGLTF.UnityPath writeAssetPath, IEnumerable excludes, bool separateByBlendShape) + var results = new List(); + if (m_separateByBlendShape) + { + var withoutBlendShape = MeshIntegratorUtility.Integrate(instance, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithoutBlendShape, excludes: excludes); + if (withoutBlendShape.IntegratedRenderer != null) + { + results.Add(withoutBlendShape); + } + + var onlyBlendShape = MeshIntegratorUtility.Integrate(instance, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithBlendShape, excludes: excludes); + if (onlyBlendShape.IntegratedRenderer != null) + { + results.Add(onlyBlendShape); + VRMMeshIntegratorUtility.FollowBlendshapeRendererChange(clips, onlyBlendShape, instance); + } + } + else + { + var integrated = MeshIntegratorUtility.Integrate(instance, onlyBlendShapeRenderers: MeshEnumerateOption.All, excludes: excludes); + if (integrated.IntegratedRenderer != null) + { + results.Add(integrated); + } + } + + DeactivateOldRendererAndAddIntegrated(instance, results, assetPath, + UniGLTF.UnityPath.FromUnityPath(AssetDatabase.GetAssetPath(m_root)).Equals(assetPath)); + } + + static void DeactivateOldRendererAndAddIntegrated(GameObject instance, List results, UniGLTF.UnityPath assetPath, + bool applyToPrefab) + { + // TODO: add integrated // disable source renderer - foreach (var res in results) + foreach (var result in results) { - foreach (var renderer in res.SourceSkinnedMeshRenderers) + foreach (var renderer in result.SourceSkinnedMeshRenderers) { Undo.RecordObject(renderer.gameObject, "Deactivate old renderer"); renderer.gameObject.SetActive(false); } - foreach (var renderer in res.SourceMeshRenderers) + foreach (var renderer in result.SourceMeshRenderers) { Undo.RecordObject(renderer.gameObject, "Deactivate old renderer"); renderer.gameObject.SetActive(false); @@ -278,6 +318,10 @@ namespace VRM { if (result.IntegratedRenderer == null) continue; + // Add integrated + result.IntegratedRenderer.transform.SetParent(instance.transform, false); + + // save as asset mesh var childAssetPath = assetPath.Parent.Child($"{result.IntegratedRenderer.gameObject.name}{ASSET_SUFFIX}"); Debug.LogFormat("CreateAsset: {0}", childAssetPath); childAssetPath.CreateAsset(result.IntegratedRenderer.sharedMesh); @@ -285,7 +329,7 @@ namespace VRM } // Apply to Prefab - if (UniGLTF.UnityPath.FromUnityPath(AssetDatabase.GetAssetPath(m_root)).Equals(assetPath)) + if (applyToPrefab) { VrmPrefabUtility.ApplyChangesToPrefab(instance); } @@ -297,9 +341,6 @@ namespace VRM throw new System.Exception($"PrefabUtility.SaveAsPrefabAsset: {assetPath}"); } } - - // destroy source renderers - UnityEngine.Object.DestroyImmediate(instance); } void OnWizardCreate() diff --git a/Assets/VRM/Runtime/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs b/Assets/VRM/Runtime/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs index fea51d76c..066b55fbd 100644 --- a/Assets/VRM/Runtime/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs +++ b/Assets/VRM/Runtime/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs @@ -11,38 +11,7 @@ namespace VRM /// public static class VRMMeshIntegratorUtility { - public static List Integrate(GameObject root, List blendshapeClips, IEnumerable excludes, bool separateByBlendShape) - { - var result = new List(); - - if (separateByBlendShape) - { - var withoutBlendShape = MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithoutBlendShape, excludes: excludes); - if (withoutBlendShape.IntegratedRenderer != null) - { - result.Add(withoutBlendShape); - } - - var onlyBlendShape = MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithBlendShape, excludes: excludes); - if (onlyBlendShape.IntegratedRenderer != null) - { - result.Add(onlyBlendShape); - FollowBlendshapeRendererChange(blendshapeClips, onlyBlendShape, root); - } - } - else - { - var integrated = MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.All, excludes: excludes); - if (integrated.IntegratedRenderer != null) - { - result.Add(integrated); - } - } - - return result; - } - - private static void FollowBlendshapeRendererChange(List clips, MeshIntegrationResult result, GameObject root) + public static void FollowBlendshapeRendererChange(List clips, MeshIntegrationResult result, GameObject root) { if (clips == null || result == null || result.IntegratedRenderer == null || root == null) return; From 41a7aeda6566cef0834bd065b5f5ffb5669b534c Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 17 May 2022 13:25:17 +0900 Subject: [PATCH 05/19] disable process button if not validated --- .../Editor/MeshUtility/MeshProcessDialog.cs | 56 ++++++++------- .../MeshUtility/MeshProcessingMessages.cs | 4 +- .../Editor/MeshUtility/TabBoneMeshRemover.cs | 30 ++++---- .../Editor/MeshUtility/TabMeshIntegrator.cs | 70 ++++++++++--------- .../Editor/MeshUtility/TabMeshSeparator.cs | 46 ++++++------ 5 files changed, 112 insertions(+), 94 deletions(-) diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs index 6b5c6e87f..4bbe07ada 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs @@ -8,7 +8,7 @@ namespace UniGLTF.MeshUtility public class MeshProcessDialog : EditorWindow { const string TITLE = "Mesh Processing Window"; - public MeshProcessDialogTabs Tab; + MeshProcessDialogTabs _tab; private GameObject _exportTarget; @@ -42,40 +42,28 @@ namespace UniGLTF.MeshUtility } } - static bool IsGameObjectSelected() - { - return Selection.activeObject != null && Selection.activeObject is GameObject; - } - private void OnGUI() { _scrollPos = EditorGUILayout.BeginScrollView(_scrollPos); - EditorGUIUtility.labelWidth = 300; - // lang + EditorGUIUtility.labelWidth = 200; LanguageGetter.OnGuiSelectLang(); + _exportTarget = (GameObject)EditorGUILayout.ObjectField(MeshProcessingMessages.TARGET_OBJECT.Msg(), _exportTarget, typeof(GameObject), true); + _tab = TabBar.OnGUI(_tab, "LargeButton", GUI.ToolbarButtonSize.Fixed); - { - // _exportTarget - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField(MeshProcessingMessages.TARGET_OBJECT.Msg(), GUILayout.MaxWidth(146.0f)); - _exportTarget = (GameObject)EditorGUILayout.ObjectField(_exportTarget, typeof(GameObject), true); - EditorGUILayout.EndHorizontal(); - // auto select ? - if (_exportTarget == null && IsGameObjectSelected()) - { - _exportTarget = Selection.activeObject as GameObject; - } - } - - // tab - Tab = TabBar.OnGUI(Tab, "LargeButton", GUI.ToolbarButtonSize.Fixed); var processed = false; - switch (Tab) + switch (_tab) { case MeshProcessDialogTabs.MeshSeparator: { EditorGUILayout.HelpBox(MeshProcessingMessages.MESH_SEPARATOR.Msg(), MessageType.Info); - processed = TabMeshSeparator.OnGUI(_exportTarget); + if (TabMeshSeparator.TryExecutable(_exportTarget, out string msg)) + { + processed = TabMeshSeparator.OnGUI(_exportTarget); + } + else + { + EditorGUILayout.HelpBox(msg, MessageType.Error); + } break; } @@ -83,7 +71,14 @@ namespace UniGLTF.MeshUtility { EditorGUILayout.HelpBox(MeshProcessingMessages.MESH_INTEGRATOR.Msg(), MessageType.Info); _separateByBlendShape = EditorGUILayout.Toggle(MeshProcessingMessages.MESH_SEPARATOR_BY_BLENDSHAPE.Msg(), _separateByBlendShape); - processed = TabMeshIntegrator.OnGUI(_exportTarget, _separateByBlendShape); + if (TabMeshIntegrator.TryExecutable(_exportTarget, out string msg)) + { + processed = TabMeshIntegrator.OnGUI(_exportTarget, _separateByBlendShape); + } + else + { + EditorGUILayout.HelpBox(msg, MessageType.Error); + } break; } @@ -95,7 +90,14 @@ namespace UniGLTF.MeshUtility _boneMeshEraserEditor.OnInspectorGUI(); } _boneMeshRemoverValidator.Validate(_skinnedMeshRenderer, _eraseBones); - processed = TabBoneMeshRemover.OnGUI(_exportTarget, _skinnedMeshRenderer, _eraseBones); + if (TabBoneMeshRemover.TryExecutable(_exportTarget, _skinnedMeshRenderer, out string msg)) + { + processed = TabBoneMeshRemover.OnGUI(_exportTarget, _skinnedMeshRenderer, _eraseBones); + } + else + { + EditorGUILayout.HelpBox(msg, MessageType.Error); + } break; } } diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs index 3b63cc538..965e70846 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs @@ -80,8 +80,8 @@ namespace UniGLTF.MeshUtility [LangMsg(Languages.en, "Skinned/Static mesh is not contained")] NO_MESH, - [LangMsg(Languages.ja, "ターゲットオブジェクトはVRMモデルです。`VRM0-> MeshIntegrator`を使ってください")] - [LangMsg(Languages.en, "Target object is VRM model, use `VRM0 -> MeshIntegrator` instead")] + [LangMsg(Languages.ja, "BlendShapeClipが不整合を起こすので、`VRM0-> MeshIntegrator`を使ってください")] + [LangMsg(Languages.en, "Because BlendShapeClip causes inconsistency , use `VRM0 -> MeshIntegrator` instead")] VRM_DETECTED, } } \ No newline at end of file diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs b/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs index 0862413a5..9e7566e78 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs @@ -13,6 +13,24 @@ namespace UniGLTF.MeshUtility const string BONE_MESH_ERASER_NAME = "BoneMeshEraser"; const string ASSET_SUFFIX = ".mesh.asset"; + public static bool TryExecutable(GameObject root, SkinnedMeshRenderer smr, out string msg) + { + if (root == null) + { + msg = MeshProcessingMessages.NO_GAMEOBJECT_SELECTED.Msg(); + return false; + } + + if (smr == null) + { + msg = MeshProcessingMessages.SELECT_SKINNED_MESH.Msg(); + return false; + } + + msg = ""; + return true; + } + public static bool OnGUI(GameObject root, SkinnedMeshRenderer smr, List eraseBones) { var _isInvokeSuccess = false; @@ -32,18 +50,6 @@ namespace UniGLTF.MeshUtility private static bool Execute(GameObject root, SkinnedMeshRenderer smr, List eraseBones) { - if (root == null) - { - EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_GAMEOBJECT_SELECTED.Msg(), "ok"); - return false; - } - - if (smr == null) - { - EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.SELECT_SKINNED_MESH.Msg(), "ok"); - return false; - } - var bones = smr.bones; var meshNode = new GameObject(BONE_MESH_ERASER_NAME); diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs b/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs index 66b19537d..c54833634 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs @@ -7,21 +7,29 @@ namespace UniGLTF.MeshUtility { public static class TabMeshIntegrator { - public static bool OnGUI(GameObject root, bool onlyBlendShapeRenderers) + public static bool TryExecutable(GameObject root, out string msg) { - var _isInvokeSuccess = false; - GUILayout.BeginVertical(); + // check + if (root == null) { - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - if (GUILayout.Button("Process", GUILayout.MinWidth(100))) - { - _isInvokeSuccess = TabMeshIntegrator.Execute(root, onlyBlendShapeRenderers); - } - GUILayout.EndHorizontal(); + msg = MeshProcessingMessages.NO_GAMEOBJECT_SELECTED.Msg(); + return false; } - GUILayout.EndVertical(); - return _isInvokeSuccess; + + if (HasVrm(root)) + { + msg = MeshProcessingMessages.VRM_DETECTED.Msg(); + return false; + } + + if (root.GetComponentsInChildren().Length == 0 && root.GetComponentsInChildren().Length == 0) + { + msg = MeshProcessingMessages.NO_MESH.Msg(); + return false; + } + + msg = ""; + return true; } const string VRM_META = "VRMMeta"; @@ -40,28 +48,25 @@ namespace UniGLTF.MeshUtility return false; } + public static bool OnGUI(GameObject root, bool onlyBlendShapeRenderers) + { + var _isInvokeSuccess = false; + GUILayout.BeginVertical(); + { + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + if (GUILayout.Button("Process", GUILayout.MinWidth(100))) + { + _isInvokeSuccess = TabMeshIntegrator.Execute(root, onlyBlendShapeRenderers); + } + GUILayout.EndHorizontal(); + } + GUILayout.EndVertical(); + return _isInvokeSuccess; + } + static bool Execute(GameObject root, bool onlyBlendShapeRenderers) { - // check - if (root == null) - { - EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_GAMEOBJECT_SELECTED.Msg(), "ok"); - return false; - } - - if (HasVrm(root)) - { - EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.VRM_DETECTED.Msg(), "ok"); - return false; - } - - if (root.GetComponentsInChildren().Length == 0 && root.GetComponentsInChildren().Length == 0) - { - EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_MESH.Msg(), "ok"); - return false; - } - - // execute var results = new List(); if (onlyBlendShapeRenderers) { @@ -75,7 +80,6 @@ namespace UniGLTF.MeshUtility // 統合結果を適用した新しいヒエラルキーをコピーから作成する MeshIntegratorUtility.CopyAndReplaceWithResults(root, results); - return true; } } diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabMeshSeparator.cs b/Assets/UniGLTF/Editor/MeshUtility/TabMeshSeparator.cs index 6e8caf398..3dab965b2 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/TabMeshSeparator.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/TabMeshSeparator.cs @@ -12,15 +12,32 @@ namespace UniGLTF.MeshUtility /// public static class TabMeshSeparator { - private static readonly Vector3 ZERO_MOVEMENT = Vector3.zero; - const string ASSET_SUFFIX = ".mesh.asset"; + private const string ASSET_SUFFIX = ".mesh.asset"; - enum BlendShapeLogic + private enum BlendShapeLogic { WithBlendShape, WithoutBlendShape, } + public static bool TryExecutable(GameObject root, out string msg) + { + if (root == null) + { + msg = MeshProcessingMessages.NO_GAMEOBJECT_SELECTED.Msg(); + return false; + } + + if (root.GetComponentsInChildren().Length == 0) + { + msg = MeshProcessingMessages.NO_SKINNED_MESH.Msg(); + return false; + } + + msg = ""; + return true; + } + public static bool OnGUI(GameObject root) { var _isInvokeSuccess = false; @@ -38,36 +55,25 @@ namespace UniGLTF.MeshUtility return _isInvokeSuccess; } - static bool Execute(GameObject root) + private static bool Execute(GameObject root) { - if (root == null) - { - EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_GAMEOBJECT_SELECTED.Msg(), "ok"); - return false; - } - - if (root.GetComponentsInChildren().Length == 0) - { - EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_SKINNED_MESH.Msg(), "ok"); - return false; - } - // copy var outputObject = GameObject.Instantiate(root); outputObject.name = outputObject.name + "_mesh_separation"; // 改変と asset の作成 var list = SeparationProcessing(outputObject); + + // asset の永続化 foreach (var (src, with, without) in list) { - // asset の永続化 SaveMesh(src, with, BlendShapeLogic.WithBlendShape); SaveMesh(src, without, BlendShapeLogic.WithoutBlendShape); } return true; } - static void SaveMesh(Mesh mesh, Mesh newMesh, BlendShapeLogic blendShapeLabel) + private static void SaveMesh(Mesh mesh, Mesh newMesh, BlendShapeLogic blendShapeLabel) { // save mesh as asset var assetPath = string.Format("{0}{1}", Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX); @@ -98,7 +104,7 @@ namespace UniGLTF.MeshUtility /// /// /// (Mesh 分割前, Mesh BlendShape有り、Mesh BlendShape無し)のリストを返す - public static List<(Mesh Src, Mesh With, Mesh Without)> SeparationProcessing(GameObject go) + private static List<(Mesh Src, Mesh With, Mesh Without)> SeparationProcessing(GameObject go) { var list = new List<(Mesh Src, Mesh With, Mesh Without)>(); var skinnedMeshRenderers = go.GetComponentsInChildren(); @@ -131,7 +137,7 @@ namespace UniGLTF.MeshUtility for (int j = 0; j < deltaVertices.Length; j++) { - if (!deltaVertices[j].Equals(ZERO_MOVEMENT)) + if (!deltaVertices[j].Equals(Vector3.zero)) { if (!indicesUsedByBlendShape.Values.Contains(j)) { From b6b12944794b04d14b4eb65520363a5a5fcbacb0 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 17 May 2022 13:41:50 +0900 Subject: [PATCH 06/19] GameObjectType --- .../Editor/MeshUtility/GameObjectType.cs | 43 +++++++++++++++++++ .../Editor/MeshUtility/GameObjectType.cs.meta | 11 +++++ .../VrmMeshIntegratorWizard.cs | 7 +++ 3 files changed, 61 insertions(+) create mode 100644 Assets/UniGLTF/Editor/MeshUtility/GameObjectType.cs create mode 100644 Assets/UniGLTF/Editor/MeshUtility/GameObjectType.cs.meta diff --git a/Assets/UniGLTF/Editor/MeshUtility/GameObjectType.cs b/Assets/UniGLTF/Editor/MeshUtility/GameObjectType.cs new file mode 100644 index 000000000..9f1d09db0 --- /dev/null +++ b/Assets/UniGLTF/Editor/MeshUtility/GameObjectType.cs @@ -0,0 +1,43 @@ +using UnityEditor; +using UnityEngine; + +namespace UniGLTF.MeshUtility +{ + public enum GameObjectType + { + Null, + SceneInstance, + PrefabInstance, + AssetPrefab, + } + + public static class GameObjectTypeUtility + { + public static GameObjectType GetGameObjectType(this GameObject go) + { + if (go == null) + { + return GameObjectType.Null; + } + + if (!go.scene.IsValid()) + { + if (PrefabUtility.IsPartOfAnyPrefab(go)) + { + return GameObjectType.AssetPrefab; + } + else + { + throw new System.Exception("unknown"); + } + } + + if (PrefabUtility.IsPartOfAnyPrefab(go)) + { + return GameObjectType.PrefabInstance; + } + + return GameObjectType.SceneInstance; + } + } +} diff --git a/Assets/UniGLTF/Editor/MeshUtility/GameObjectType.cs.meta b/Assets/UniGLTF/Editor/MeshUtility/GameObjectType.cs.meta new file mode 100644 index 000000000..721cf19ee --- /dev/null +++ b/Assets/UniGLTF/Editor/MeshUtility/GameObjectType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 95cda911ba335b449901767f9bee8ca8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs b/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs index a5db19875..86f2fcd86 100644 --- a/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs +++ b/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs @@ -104,6 +104,13 @@ namespace VRM OnValidate(); } + protected override bool DrawWizardGUI() + { + var t = m_root.GetGameObjectType(); + EditorGUILayout.HelpBox($"{t}", MessageType.Info); + return base.DrawWizardGUI(); + } + static object GetPropertyValue(Shader shader, int i, Material m) { var propType = ShaderUtil.GetPropertyType(shader, i); From 0f951fb1360069a2a6602f1152ee0f27bd209f63 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 17 May 2022 13:42:12 +0900 Subject: [PATCH 07/19] fix warning when recompile --- .../Editor/MeshUtility/MeshProcessDialogEditor.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogEditor.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogEditor.cs index b262b3401..e14659de0 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogEditor.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialogEditor.cs @@ -24,9 +24,12 @@ namespace UniGLTF.MeshUtility void OnEnable() { - _targetDialog = (MeshProcessDialog)target; - _skinnedMesh = serializedObject.FindProperty(nameof(MeshProcessDialog._skinnedMeshRenderer)); - _eraseBones = serializedObject.FindProperty(nameof(MeshProcessDialog._eraseBones)); + _targetDialog = target as MeshProcessDialog; + if (_targetDialog) + { + _skinnedMesh = serializedObject.FindProperty(nameof(MeshProcessDialog._skinnedMeshRenderer)); + _eraseBones = serializedObject.FindProperty(nameof(MeshProcessDialog._eraseBones)); + } } public override void OnInspectorGUI() From 4a41d42e02735fb475220ccae8071b12db65a621 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 17 May 2022 14:06:14 +0900 Subject: [PATCH 08/19] =?UTF-8?q?=E5=87=A6=E7=90=86=E3=82=92=E6=95=B4?= =?UTF-8?q?=E7=90=86=E3=80=82Integration=20=E3=81=8C=20scene=20=E3=81=A8?= =?UTF-8?q?=20prefab=20=E3=81=A9=E3=81=A3=E3=81=A1=E3=81=A7=E3=82=82?= =?UTF-8?q?=E5=8B=95=E3=81=8F=E3=82=88=E3=81=86=E3=81=AB=E3=81=AA=E3=81=A3?= =?UTF-8?q?=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Editor/MeshUtility/MeshProcessDialog.cs | 5 +- .../Editor/MeshUtility/TabMeshIntegrator.cs | 64 ++++++++++++------- .../MeshUtility/MeshIntegratorUtility.cs | 28 +++----- 3 files changed, 54 insertions(+), 43 deletions(-) diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs index 4bbe07ada..63c0c6e99 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs @@ -73,7 +73,10 @@ namespace UniGLTF.MeshUtility _separateByBlendShape = EditorGUILayout.Toggle(MeshProcessingMessages.MESH_SEPARATOR_BY_BLENDSHAPE.Msg(), _separateByBlendShape); if (TabMeshIntegrator.TryExecutable(_exportTarget, out string msg)) { - processed = TabMeshIntegrator.OnGUI(_exportTarget, _separateByBlendShape); + if (GUILayout.Button("Process", GUILayout.MinWidth(100))) + { + processed = TabMeshIntegrator.Execute(_exportTarget, _separateByBlendShape); + } } else { diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs b/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs index c54833634..7b8d8c8cf 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs @@ -48,38 +48,56 @@ namespace UniGLTF.MeshUtility return false; } - public static bool OnGUI(GameObject root, bool onlyBlendShapeRenderers) - { - var _isInvokeSuccess = false; - GUILayout.BeginVertical(); - { - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - if (GUILayout.Button("Process", GUILayout.MinWidth(100))) - { - _isInvokeSuccess = TabMeshIntegrator.Execute(root, onlyBlendShapeRenderers); - } - GUILayout.EndHorizontal(); - } - GUILayout.EndVertical(); - return _isInvokeSuccess; - } - - static bool Execute(GameObject root, bool onlyBlendShapeRenderers) + /// GameObject instance in scene or prefab + public static bool Execute(GameObject src, bool onlyBlendShapeRenderers) { var results = new List(); + + // instance or prefab => copy + var copy = GameObject.Instantiate(src); + copy.name = copy.name + "_mesh_integration"; + + // integrate if (onlyBlendShapeRenderers) { - results.Add(MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithBlendShape)); - results.Add(MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithoutBlendShape)); + results.Add(MeshIntegratorUtility.Integrate(copy, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithBlendShape)); + results.Add(MeshIntegratorUtility.Integrate(copy, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithoutBlendShape)); } else { - results.Add(MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.All)); + results.Add(MeshIntegratorUtility.Integrate(copy, onlyBlendShapeRenderers: MeshEnumerateOption.All)); + } + + // replace + MeshIntegratorUtility.ReplaceMeshWithResults(copy, results); + + // write mesh asset. + foreach (var result in results) + { + var mesh = result.IntegratedRenderer.sharedMesh; + var assetPath = MeshIntegratorUtility.GetMeshWritePath(mesh); + Debug.LogFormat("CreateAsset: {0}", assetPath); + AssetDatabase.CreateAsset(mesh, assetPath); + } + + if (src.GetGameObjectType() == GameObjectType.AssetPrefab) + { + // write prefab. + { + var prefabPath = UnityPath.FromAsset(src); + prefabPath = prefabPath.Parent.Child($"{prefabPath.FileNameWithoutExtension}_integrated.prefab"); + Debug.LogFormat("WritePrefab: {0}", prefabPath); + PrefabUtility.SaveAsPrefabAsset(copy, prefabPath.Value); + } + + // destroy copy in scene. + GameObject.DestroyImmediate(copy); + } + else + { + // do nothing. keep copy. } - // 統合結果を適用した新しいヒエラルキーをコピーから作成する - MeshIntegratorUtility.CopyAndReplaceWithResults(root, results); return true; } } diff --git a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs index f01b42dbc..5c914a144 100644 --- a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs +++ b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs @@ -165,18 +165,14 @@ namespace UniGLTF.MeshUtility } } - public static void CopyAndReplaceWithResults(GameObject root, List results) + public static void ReplaceMeshWithResults(GameObject copy, List results) { - // copy hierarchy - var outputObject = GameObject.Instantiate(root); - outputObject.name = outputObject.name + "_mesh_integration"; - - // destroy original meshes in the copied GameObject - foreach (var skinnedMesh in outputObject.GetComponentsInChildren()) + // destroy original meshes + foreach (var skinnedMesh in copy.GetComponentsInChildren()) { GameObject.DestroyImmediate(skinnedMesh); } - foreach (var normalMesh in outputObject.GetComponentsInChildren()) + foreach (var normalMesh in copy.GetComponentsInChildren()) { if (normalMesh.sharedMesh.name != MeshIntegratorUtility.INTEGRATED_MESH_NAME) { @@ -188,30 +184,24 @@ namespace UniGLTF.MeshUtility } } + // Add integrated foreach (var result in results) { - // Add integrated - result.IntegratedRenderer.transform.SetParent(outputObject.transform, false); - // save mesh data - SaveMeshData(result.IntegratedRenderer.sharedMesh); + result.IntegratedRenderer.transform.SetParent(copy.transform, false); } } - static void SaveMeshData(Mesh mesh) + public static string GetMeshWritePath(Mesh mesh) { - var assetPath = string.Format("{0}{1}", Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX); - Debug.Log(assetPath); if (!string.IsNullOrEmpty((AssetDatabase.GetAssetPath(mesh)))) { var directory = Path.GetDirectoryName(AssetDatabase.GetAssetPath(mesh)).Replace("\\", "/"); - assetPath = string.Format("{0}/{1}{2}", directory, Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX); + return $"{directory}/{Path.GetFileNameWithoutExtension(mesh.name)}{ASSET_SUFFIX}"; } else { - assetPath = string.Format("Assets/{0}{1}", Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX); + return $"Assets/{Path.GetFileNameWithoutExtension(mesh.name)}{ASSET_SUFFIX}"; } - Debug.LogFormat("CreateAsset: {0}", assetPath); - AssetDatabase.CreateAsset(mesh, assetPath); } } } \ No newline at end of file From 4d2047d5ff7d081c0738e01266c80685fbbb8bc3 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 17 May 2022 16:38:31 +0900 Subject: [PATCH 09/19] VrmMeshIntegratorWizard --- .../Editor/MeshUtility/GameObjectType.cs | 14 ++ .../UniGLTF/Runtime/UniGLTF/IO/UnityPath.cs | 9 +- .../FirstPerson/VRMFirstPersonValidator.cs | 10 +- .../VRMMeshIntegratorUtility.cs | 74 +++++++++ .../VRMMeshIntegratorUtility.cs.meta | 2 +- .../VrmMeshIntegratorWizard.cs | 146 +++++++++--------- .../SkinnedMeshUtility/VrmPrefabUtility.cs | 31 ++-- .../VRM/Runtime/FirstPerson/VRMFirstPerson.cs | 6 + .../VRMMeshIntegratorUtility.cs | 45 ------ 9 files changed, 190 insertions(+), 147 deletions(-) create mode 100644 Assets/VRM/Editor/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs rename Assets/VRM/{Runtime => Editor}/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs.meta (83%) delete mode 100644 Assets/VRM/Runtime/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs diff --git a/Assets/UniGLTF/Editor/MeshUtility/GameObjectType.cs b/Assets/UniGLTF/Editor/MeshUtility/GameObjectType.cs index 9f1d09db0..9199406e5 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/GameObjectType.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/GameObjectType.cs @@ -13,6 +13,20 @@ namespace UniGLTF.MeshUtility public static class GameObjectTypeUtility { + public static Object GetPrefab(this GameObject instance) + { + if (!string.IsNullOrEmpty(AssetDatabase.GetAssetPath(instance))) + { + return instance; + } + +#if UNITY_2018_2_OR_NEWER + return PrefabUtility.GetCorrespondingObjectFromSource(instance); +#else + return PrefabUtility.GetPrefabParent(go); +#endif + } + public static GameObjectType GetGameObjectType(this GameObject go) { if (go == null) diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/UnityPath.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/UnityPath.cs index 11cccb200..ff74aeedf 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/UnityPath.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/UnityPath.cs @@ -343,8 +343,13 @@ namespace UniGLTF } public static UnityPath FromAsset(UnityEngine.Object asset) - { - return new UnityPath(AssetDatabase.GetAssetPath(asset)); + { + var assetPath = AssetDatabase.GetAssetPath(asset); + if (string.IsNullOrEmpty(assetPath)) + { + throw new System.ArgumentNullException(); + } + return new UnityPath(assetPath); } public void ImportAsset() diff --git a/Assets/VRM/Editor/FirstPerson/VRMFirstPersonValidator.cs b/Assets/VRM/Editor/FirstPerson/VRMFirstPersonValidator.cs index 048159d81..d9ab8fe0d 100644 --- a/Assets/VRM/Editor/FirstPerson/VRMFirstPersonValidator.cs +++ b/Assets/VRM/Editor/FirstPerson/VRMFirstPersonValidator.cs @@ -25,11 +25,11 @@ namespace VRM return false; } - if (!r.Renderer.EnableForExport()) - { - validation = Validation.Error($"{name}.Renderer is not active", ValidationContext.Create(extended)); - return false; - } + // if (!r.Renderer.EnableForExport()) + // { + // validation = Validation.Error($"{name}.Renderer is not active", ValidationContext.Create(extended)); + // return false; + // } validation = default; return true; diff --git a/Assets/VRM/Editor/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs b/Assets/VRM/Editor/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs new file mode 100644 index 000000000..ee054a596 --- /dev/null +++ b/Assets/VRM/Editor/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs @@ -0,0 +1,74 @@ +using System.Collections.Generic; +using System.Linq; +using UniGLTF; +using UniGLTF.MeshUtility; +using UnityEditor; +using UnityEngine; + +namespace VRM +{ + /// + /// Meshを統合し、統合後のMeshのBlendShapeの変化をVRMのBlendShapeClipに反映する + /// + public static class VRMMeshIntegratorUtility + { + public static void FollowBlendshapeRendererChange(List results, GameObject root, string assetFolder) + { + var proxy = root.GetComponent(); + if (proxy == null || proxy.BlendShapeAvatar == null) + { + return; + } + var result = results.FirstOrDefault(x => x.SourceSkinnedMeshRenderers.Count > 0); + if (result == null) + { + return; + } + + var rendererDict = new Dictionary(); + foreach (var x in result.SourceSkinnedMeshRenderers) + { + rendererDict.Add(x.transform.RelativePathFrom(root.transform), x); + } + var dstPath = result.IntegratedRenderer.transform.RelativePathFrom(root.transform); + + // copy + var clips = new List(); + foreach (var src in proxy.BlendShapeAvatar.Clips) + { + if (src == null) continue; + + var clip = BlendShapeClip.Instantiate(src); + clips.Add(clip); + for (var i = 0; i < clip.Values.Length; ++i) + { + var val = clip.Values[i]; + if (rendererDict.ContainsKey(val.RelativePath)) + { + var srcRenderer = rendererDict[val.RelativePath]; + var name = srcRenderer.sharedMesh.GetBlendShapeName(val.Index); + var newIndex = result.IntegratedRenderer.sharedMesh.GetBlendShapeIndex(name); + + val.RelativePath = dstPath; + val.Index = newIndex; + } + + clip.Values[i] = val; + } + + var assetPath = $"{assetFolder}/{clip.name}.asset"; + Debug.Log($"write: {assetPath}"); + AssetDatabase.CreateAsset(clip, assetPath); + } + + { + // create blendshape avatar & replace + var blendShapeAvatar = BlendShapeAvatar.CreateInstance(); + blendShapeAvatar.Clips.AddRange(clips); + var assetPath = $"{assetFolder}/blendshape.asset"; + AssetDatabase.CreateAsset(blendShapeAvatar, assetPath); + proxy.BlendShapeAvatar = blendShapeAvatar; + } + } + } +} \ No newline at end of file diff --git a/Assets/VRM/Runtime/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs.meta b/Assets/VRM/Editor/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs.meta similarity index 83% rename from Assets/VRM/Runtime/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs.meta rename to Assets/VRM/Editor/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs.meta index 49f2e8d74..84182f709 100644 --- a/Assets/VRM/Runtime/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs.meta +++ b/Assets/VRM/Editor/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 8eebeb093136b7f429c0e9e7295816b3 +guid: fb47e24fc1463584fa0b6b685d75f25e MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs b/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs index 86f2fcd86..3797ba473 100644 --- a/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs +++ b/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs @@ -221,90 +221,103 @@ namespace VRM void OnWizardUpdate() { - // helpString = "Set target gameobject `in scene`. Prefab not supported."; } - /// - /// Prefab に対する操作として実装されている - /// + /// 2022.05 仕様変更 + /// + /// * scene or prefab どっちでも動作する + /// * backup するのではなく 変更した copy を作成する。元は変えない + /// * 実行すると mesh, blendshape, blendShape を新規に作成する + /// * scene のときは新しいヒエラルキーが出現する + /// * prefab のときは新しいヒエラルキーを prefab 保存して、scene の方を削除して終了する + /// void Integrate() { - var prefabPath = AssetDatabase.GetAssetPath(m_root); - Debug.Log(prefabPath); - var path = EditorUtility.SaveFilePanel("save prefab", Path.GetDirectoryName(prefabPath), m_root.name, "prefab"); - if (string.IsNullOrEmpty(path)) + String folder = "Assets"; + var prefab = m_root.GetPrefab(); + if (prefab != null) { - return; + folder = AssetDatabase.GetAssetPath(prefab); + Debug.Log(folder); } - var assetPath = UniGLTF.UnityPath.FromFullpath(path); - if (!assetPath.IsUnderAssetsFolder) + // 新規で作成されるアセットはすべてこのフォルダの中に作る。上書きチェックはしない + var assetFolder = EditorUtility.SaveFolderPanel("select asset save folder", Path.GetDirectoryName(folder), "VrmIntegrated"); + var unityPath = UniGLTF.UnityPath.FromFullpath(assetFolder); + if (!unityPath.IsUnderAssetsFolder) { - Debug.LogWarning($"{path} is not asset path"); + EditorUtility.DisplayDialog("asset folder", "Target folder must be in the `Assets` folder", "cancel"); return; } + assetFolder = unityPath.Value; + var copy = GameObject.Instantiate(m_root); + + // 統合 var excludes = m_excludes.Where(x => x.Exclude).Select(x => x.Mesh); + var results = Integrate(copy, excludes, m_separateByBlendShape); - // Backup Exists - VrmPrefabUtility.BackupVrmPrefab(m_root); + // 統合前のMeshを非表示にして、統合した結果をヒエラルキーに追加する + DeactivateOldRendererAndAddIntegrated(copy, results); - Undo.RecordObject(m_root, "Mesh Integration"); - var instance = VrmPrefabUtility.InstantiatePrefab(m_root); - var clips = new List(); - var proxy = instance.GetComponent(); - if (proxy != null && proxy.BlendShapeAvatar != null) + // write mesh asset + foreach (var result in results) { - clips.AddRange(proxy.BlendShapeAvatar.Clips); - } - foreach (var clip in clips) - { - Undo.RecordObject(clip, "Mesh Integration"); + var childAssetPath = $"{assetFolder}/{result.IntegratedRenderer.gameObject.name}{ASSET_SUFFIX}"; + Debug.LogFormat("CreateAsset: {0}", childAssetPath); + AssetDatabase.CreateAsset(result.IntegratedRenderer.sharedMesh, childAssetPath); } - _Integrate(instance, excludes, assetPath, clips); + // 統合した結果を反映した BlendShapeClip を作成して置き換える + VRMMeshIntegratorUtility.FollowBlendshapeRendererChange(results, copy, assetFolder); - // destroy source renderers - UnityEngine.Object.DestroyImmediate(instance); - } - - void _Integrate(GameObject instance, IEnumerable excludes, UniGLTF.UnityPath assetPath, List clips) - { - // Execute - var results = new List(); - if (m_separateByBlendShape) + // reset firstperson + var firstperson = copy.GetComponent(); + if (firstperson != null) { - var withoutBlendShape = MeshIntegratorUtility.Integrate(instance, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithoutBlendShape, excludes: excludes); - if (withoutBlendShape.IntegratedRenderer != null) + firstperson.Reset(); + } + + if (prefab != null) + { + // prefab + var prefabPath = $"{assetFolder}/VrmIntegrated.prefab"; + Debug.Log(prefabPath); + PrefabUtility.SaveAsPrefabAsset(copy, prefabPath, out bool success); + if (!success) { - results.Add(withoutBlendShape); + throw new System.Exception($"PrefabUtility.SaveAsPrefabAsset: {prefabPath}"); } - var onlyBlendShape = MeshIntegratorUtility.Integrate(instance, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithBlendShape, excludes: excludes); - if (onlyBlendShape.IntegratedRenderer != null) - { - results.Add(onlyBlendShape); - VRMMeshIntegratorUtility.FollowBlendshapeRendererChange(clips, onlyBlendShape, instance); - } + // destroy scene + UnityEngine.Object.DestroyImmediate(copy); } else { - var integrated = MeshIntegratorUtility.Integrate(instance, onlyBlendShapeRenderers: MeshEnumerateOption.All, excludes: excludes); - if (integrated.IntegratedRenderer != null) - { - results.Add(integrated); - } + // do nothing. keep scene } - - DeactivateOldRendererAndAddIntegrated(instance, results, assetPath, - UniGLTF.UnityPath.FromUnityPath(AssetDatabase.GetAssetPath(m_root)).Equals(assetPath)); } - static void DeactivateOldRendererAndAddIntegrated(GameObject instance, List results, UniGLTF.UnityPath assetPath, - bool applyToPrefab) + static List Integrate(GameObject root, IEnumerable excludes, bool separateByBlendShape) { - // TODO: add integrated + var results = new List(); + if (separateByBlendShape) + { + results.Add(MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithoutBlendShape, excludes: excludes)); + results.Add(MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithBlendShape, excludes: excludes)); + } + else + { + results.Add(MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.All, excludes: excludes)); + } + return results; + } + /// + /// 古いMeshを disable にし、新しい統合済み mesh を追加する + /// + static void DeactivateOldRendererAndAddIntegrated(GameObject root, List results) + { // disable source renderer foreach (var result in results) { @@ -321,31 +334,12 @@ namespace VRM } } + // Add integrated foreach (var result in results) { - if (result.IntegratedRenderer == null) continue; - - // Add integrated - result.IntegratedRenderer.transform.SetParent(instance.transform, false); - - // save as asset mesh - var childAssetPath = assetPath.Parent.Child($"{result.IntegratedRenderer.gameObject.name}{ASSET_SUFFIX}"); - Debug.LogFormat("CreateAsset: {0}", childAssetPath); - childAssetPath.CreateAsset(result.IntegratedRenderer.sharedMesh); - Undo.RegisterCreatedObjectUndo(result.IntegratedRenderer.gameObject, "Integrate Renderers"); - } - - // Apply to Prefab - if (applyToPrefab) - { - VrmPrefabUtility.ApplyChangesToPrefab(instance); - } - else - { - PrefabUtility.SaveAsPrefabAsset(instance, assetPath.Value, out bool success); - if (!success) + if (result.IntegratedRenderer != null) { - throw new System.Exception($"PrefabUtility.SaveAsPrefabAsset: {assetPath}"); + result.IntegratedRenderer.transform.SetParent(root.transform, false); } } } diff --git a/Assets/VRM/Editor/SkinnedMeshUtility/VrmPrefabUtility.cs b/Assets/VRM/Editor/SkinnedMeshUtility/VrmPrefabUtility.cs index 574c7121c..0f203752b 100644 --- a/Assets/VRM/Editor/SkinnedMeshUtility/VrmPrefabUtility.cs +++ b/Assets/VRM/Editor/SkinnedMeshUtility/VrmPrefabUtility.cs @@ -2,6 +2,7 @@ using System.Linq; using UniGLTF; using UnityEditor; using UnityEngine; +using UniGLTF.MeshUtility; namespace VRM { @@ -31,7 +32,7 @@ namespace VRM public static void ApplyChangesToPrefab(GameObject instance) { - var prefab = GetPrefab(instance); + var prefab = instance.GetPrefab(); if (prefab == null) { return; @@ -46,15 +47,6 @@ namespace VRM PrefabUtility.SaveAsPrefabAssetAndConnect(instance, path, InteractionMode.AutomatedAction); } - static Object GetPrefab(GameObject instance) - { -#if UNITY_2018_2_OR_NEWER - return PrefabUtility.GetCorrespondingObjectFromSource(instance); -#else - return PrefabUtility.GetPrefabParent(go); -#endif - } - /// /// VRM prefab を ${prefab_dir}/MeshIntegratorBackup/ に複製する。 /// @@ -64,18 +56,21 @@ namespace VRM /// /// が複製される。 /// - /// - public static void BackupVrmPrefab(GameObject rootPrefab) + /// + public static void BackupVrmPrefab(GameObject go) { - var proxy = rootPrefab.GetComponent(); + var prefab = go.GetGameObjectType() == GameObjectType.AssetPrefab ? go : PrefabUtility.GetCorrespondingObjectFromSource(go); + var prefabPath = UnityPath.FromAsset(prefab); + + var proxy = go.GetComponent(); var srcAvatar = proxy.BlendShapeAvatar; - var dstAvatar = (BlendShapeAvatar)BackupAsset(srcAvatar, rootPrefab); + var dstAvatar = (BlendShapeAvatar)BackupAsset(srcAvatar, prefabPath); - var clipMapper = srcAvatar.Clips.ToDictionary(x => x, x => (BlendShapeClip)BackupAsset(x, rootPrefab)); + var clipMapper = srcAvatar.Clips.ToDictionary(x => x, x => (BlendShapeClip)BackupAsset(x, prefabPath)); dstAvatar.Clips = clipMapper.Values.ToList(); - var dstPrefab = BackupAsset(rootPrefab, rootPrefab); + var dstPrefab = BackupAsset(prefab, prefabPath); var dstInstance = InstantiatePrefab(dstPrefab); dstInstance.GetComponent().BlendShapeAvatar = dstAvatar; ApplyChangesToPrefab(dstInstance); @@ -89,12 +84,12 @@ namespace VRM /// /// /// - private static T BackupAsset(T asset, GameObject rootPrefab) where T : UnityEngine.Object + private static T BackupAsset(T asset, UnityPath prefabPath) where T : UnityEngine.Object { var srcAssetPath = UnityPath.FromAsset(asset); var assetName = srcAssetPath.FileName; - var backupPath = UnityPath.FromAsset(rootPrefab).Parent.Child(BACKUP_DIR); + var backupPath = prefabPath.Parent.Child(BACKUP_DIR); backupPath.EnsureFolder(); var dstAssetPath = backupPath.Child(assetName); diff --git a/Assets/VRM/Runtime/FirstPerson/VRMFirstPerson.cs b/Assets/VRM/Runtime/FirstPerson/VRMFirstPerson.cs index d326b9959..1b600df6b 100644 --- a/Assets/VRM/Runtime/FirstPerson/VRMFirstPerson.cs +++ b/Assets/VRM/Runtime/FirstPerson/VRMFirstPerson.cs @@ -91,6 +91,12 @@ namespace VRM var rendererComponents = transform.GetComponentsInChildren(); foreach (var renderer in rendererComponents) { + // renderer が !enabled/!activeSelf なのがロード中なのか否か区別がつかないような気がするので + // チェックしない。 + // if(!renderer.enabled) + // { + // continue; + // } var flags = new RendererFirstPersonFlags { Renderer = renderer, diff --git a/Assets/VRM/Runtime/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs b/Assets/VRM/Runtime/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs deleted file mode 100644 index 066b55fbd..000000000 --- a/Assets/VRM/Runtime/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using UniGLTF; -using UniGLTF.MeshUtility; -using UnityEngine; - -namespace VRM -{ - /// - /// Meshを統合し、統合後のMeshのBlendShapeの変化をVRMのBlendShapeClipに反映する - /// - public static class VRMMeshIntegratorUtility - { - public static void FollowBlendshapeRendererChange(List clips, MeshIntegrationResult result, GameObject root) - { - if (clips == null || result == null || result.IntegratedRenderer == null || root == null) return; - - var rendererDict = result.SourceSkinnedMeshRenderers - .ToDictionary(x => x.transform.RelativePathFrom(root.transform), x => x); - - var dstPath = result.IntegratedRenderer.transform.RelativePathFrom(root.transform); - - foreach (var clip in clips) - { - if (clip == null) continue; - - for (var i = 0; i < clip.Values.Length; ++i) - { - var val = clip.Values[i]; - if (rendererDict.ContainsKey(val.RelativePath)) - { - var srcRenderer = rendererDict[val.RelativePath]; - var name = srcRenderer.sharedMesh.GetBlendShapeName(val.Index); - var newIndex = result.IntegratedRenderer.sharedMesh.GetBlendShapeIndex(name); - - val.RelativePath = dstPath; - val.Index = newIndex; - } - - clip.Values[i] = val; - } - } - } - } -} \ No newline at end of file From b69b3a14d2d25020e380bb923faf9dbab5df6d8b Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 18 May 2022 13:43:42 +0900 Subject: [PATCH 10/19] remove unused --- .../MeshUtility/StaticMeshIntegrator.cs | 122 ------------------ .../MeshUtility/StaticMeshIntegrator.cs.meta | 11 -- 2 files changed, 133 deletions(-) delete mode 100644 Assets/UniGLTF/Runtime/MeshUtility/StaticMeshIntegrator.cs delete mode 100644 Assets/UniGLTF/Runtime/MeshUtility/StaticMeshIntegrator.cs.meta diff --git a/Assets/UniGLTF/Runtime/MeshUtility/StaticMeshIntegrator.cs b/Assets/UniGLTF/Runtime/MeshUtility/StaticMeshIntegrator.cs deleted file mode 100644 index 342dae79c..000000000 --- a/Assets/UniGLTF/Runtime/MeshUtility/StaticMeshIntegrator.cs +++ /dev/null @@ -1,122 +0,0 @@ -using System.Collections.Generic; -using UnityEngine; -using System.IO; -using System.Linq; -#if UNITY_EDITOR -using UnityEditor; -#endif - - -namespace UniGLTF.MeshUtility -{ - public static class StaticMeshIntegrator - { - const string ASSET_SUFFIX = ".mesh.asset"; - - class Integrator - { - List m_positions = new List(); - List m_normals = new List(); - List m_uv = new List(); - /* - List m_uv2 = new List(); // ToDo - List m_uv3 = new List(); // ToDo - List m_uv4 = new List(); // ToDo - List m_colors = new List(); // ToDo - */ - - List m_subMeshes = new List(); - - List m_materials = new List(); - public List Materials - { - get { return m_materials; } - } - - public void Push(Matrix4x4 localToRoot, Mesh mesh, Material[] materials) - { - var offset = m_positions.Count; - - var hasNormal = m_normals.Count == m_positions.Count; - var hasUv = m_uv.Count == m_positions.Count; - - // attributes - m_positions.AddRange(mesh.vertices.Select(x => localToRoot.MultiplyPoint(x))); - if(mesh.normals!=null && mesh.normals.Length == mesh.vertexCount) - { - if (!hasNormal) for (int i = m_normals.Count; i < m_positions.Count; ++i) m_normals.Add(Vector3.zero); - m_normals.AddRange(mesh.normals.Select(x => localToRoot.MultiplyVector(x))); - } - if (mesh.uv != null && mesh.uv.Length == mesh.vertexCount) - { - if (!hasUv) for (int i = m_uv.Count; i < m_positions.Count; ++i) m_uv.Add(Vector2.zero); - m_uv.AddRange(mesh.uv); - } - - // indices - for (int i = 0; i < mesh.subMeshCount; ++i) - { - m_subMeshes.Add(mesh.GetIndices(i).Select(x => offset + x).ToArray()); - } - - // materials - m_materials.AddRange(materials); - } - - public Mesh ToMesh() - { - var mesh = new Mesh(); - mesh.name = MeshIntegratorUtility.INTEGRATED_MESH_NAME; - - mesh.vertices = m_positions.ToArray(); - if (m_normals.Count > 0) - { - if (m_normals.Count < m_positions.Count) for (int i = m_normals.Count; i < m_positions.Count; ++i) m_normals.Add(Vector3.zero); - mesh.normals = m_normals.ToArray(); - } - if (m_uv.Count > 0) - { - if (m_uv.Count < m_positions.Count) for (int i = m_uv.Count; i < m_positions.Count; ++i) m_uv.Add(Vector2.zero); - mesh.uv = m_uv.ToArray(); - } - - mesh.subMeshCount = m_subMeshes.Count; - for(int i=0; i(); - var filter = t.GetComponent(); - if (renderer != null && filter != null && filter.sharedMesh != null - && renderer.sharedMaterials!=null && renderer.sharedMaterials.Length == filter.sharedMesh.subMeshCount) - { - integrator.Push(root.worldToLocalMatrix * t.localToWorldMatrix, filter.sharedMesh, renderer.sharedMaterials); - } - } - - return new MeshWithMaterials - { - Mesh = integrator.ToMesh(), - Materials = integrator.Materials.ToArray(), - }; - } - - } -} diff --git a/Assets/UniGLTF/Runtime/MeshUtility/StaticMeshIntegrator.cs.meta b/Assets/UniGLTF/Runtime/MeshUtility/StaticMeshIntegrator.cs.meta deleted file mode 100644 index b9b730e00..000000000 --- a/Assets/UniGLTF/Runtime/MeshUtility/StaticMeshIntegrator.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5d049a3daed1255499aaec8b6d1a2afe -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: From 735e17dd7a68b5aaffb0fde0533280cc04ac41bb Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 18 May 2022 13:45:31 +0900 Subject: [PATCH 11/19] name --- .../Runtime/MeshUtility/MeshIntegrator.cs | 28 ++++++++++++----- .../MeshUtility/MeshIntegratorUtility.cs | 13 ++------ .../VRMMeshIntegratorUtility.cs | 30 +++++++++++++++++-- 3 files changed, 51 insertions(+), 20 deletions(-) diff --git a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs index f4ddfdd20..30fc53a90 100644 --- a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs +++ b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs @@ -6,8 +6,9 @@ namespace UniGLTF.MeshUtility { public class MeshIntegrator { - public const string INTEGRATED_MESH_NAME = "MeshesIntegrated"; - public const string INTEGRATED_MESH_BLENDSHAPE_NAME = "MeshesBlendShapeIntegrated"; + public const string INTEGRATED_MESH_WITHOUT_BLENDSHAPE_NAME = "Integrated(WithoutBlendShape)"; + public const string INTEGRATED_MESH_WITH_BLENDSHAPE_NAME = "Integrated(WithBlendShape)"; + public const string INTEGRATED_MESH_ALL_NAME = "Integrated(All)"; struct SubMesh { @@ -252,34 +253,47 @@ namespace UniGLTF.MeshUtility } mesh.bindposes = BindPoses.ToArray(); + // blendshape switch (onlyBlendShapeRenderers) { case MeshEnumerateOption.OnlyWithBlendShape: { AddBlendShapesToMesh(mesh); - mesh.name = INTEGRATED_MESH_BLENDSHAPE_NAME; + mesh.name = INTEGRATED_MESH_WITH_BLENDSHAPE_NAME; break; } - case MeshEnumerateOption.OnlyWithoutBlendShape: + case MeshEnumerateOption.All: { - mesh.name = INTEGRATED_MESH_NAME; + AddBlendShapesToMesh(mesh); + mesh.name = INTEGRATED_MESH_ALL_NAME; + break; + } + + case MeshEnumerateOption.OnlyWithoutBlendShape: + { + mesh.name = INTEGRATED_MESH_WITHOUT_BLENDSHAPE_NAME; break; } } + // meshName var meshNode = new GameObject(); switch (onlyBlendShapeRenderers) { case MeshEnumerateOption.OnlyWithBlendShape: { - meshNode.name = "MeshIntegrator(BlendShape)"; + meshNode.name = INTEGRATED_MESH_WITH_BLENDSHAPE_NAME; break; } case MeshEnumerateOption.OnlyWithoutBlendShape: + { + meshNode.name = INTEGRATED_MESH_WITHOUT_BLENDSHAPE_NAME; + break; + } case MeshEnumerateOption.All: { - meshNode.name = "MeshIntegrator"; + meshNode.name = INTEGRATED_MESH_ALL_NAME; break; } } diff --git a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs index 5c914a144..49958e176 100644 --- a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs +++ b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs @@ -9,10 +9,6 @@ namespace UniGLTF.MeshUtility { const string ASSET_SUFFIX = ".mesh.asset"; - public static string INTEGRATED_MESH_NAME => MeshIntegrator.INTEGRATED_MESH_NAME; - public static string INTEGRATED_MESH_BLENDSHAPE_NAME => MeshIntegrator.INTEGRATED_MESH_BLENDSHAPE_NAME; - - /// /// go を root としたヒエラルキーから Renderer を集めて、統合された Mesh 作成する /// @@ -174,14 +170,11 @@ namespace UniGLTF.MeshUtility } foreach (var normalMesh in copy.GetComponentsInChildren()) { - if (normalMesh.sharedMesh.name != MeshIntegratorUtility.INTEGRATED_MESH_NAME) + if (normalMesh.gameObject.GetComponent()) { - if (normalMesh.gameObject.GetComponent()) - { - GameObject.DestroyImmediate(normalMesh.gameObject.GetComponent()); - } - GameObject.DestroyImmediate(normalMesh); + GameObject.DestroyImmediate(normalMesh.gameObject.GetComponent()); } + GameObject.DestroyImmediate(normalMesh); } // Add integrated diff --git a/Assets/VRM/Editor/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs b/Assets/VRM/Editor/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs index ee054a596..9ae4132af 100644 --- a/Assets/VRM/Editor/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs +++ b/Assets/VRM/Editor/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using System.Text; using UniGLTF; using UniGLTF.MeshUtility; using UnityEditor; @@ -32,14 +33,18 @@ namespace VRM } var dstPath = result.IntegratedRenderer.transform.RelativePathFrom(root.transform); - // copy + // copy modify and write + var clipAssetPathList = new List(); + var sb = new StringBuilder(); var clips = new List(); foreach (var src in proxy.BlendShapeAvatar.Clips) { if (src == null) continue; + // copy var clip = BlendShapeClip.Instantiate(src); - clips.Add(clip); + + // modify for (var i = 0; i < clip.Values.Length; ++i) { var val = clip.Values[i]; @@ -48,6 +53,10 @@ namespace VRM var srcRenderer = rendererDict[val.RelativePath]; var name = srcRenderer.sharedMesh.GetBlendShapeName(val.Index); var newIndex = result.IntegratedRenderer.sharedMesh.GetBlendShapeIndex(name); + if (newIndex == -1) + { + throw new KeyNotFoundException($"blendshape:{name} not found"); + } val.RelativePath = dstPath; val.Index = newIndex; @@ -56,10 +65,19 @@ namespace VRM clip.Values[i] = val; } + // write var assetPath = $"{assetFolder}/{clip.name}.asset"; - Debug.Log($"write: {assetPath}"); + sb.AppendLine($"write: {assetPath}"); AssetDatabase.CreateAsset(clip, assetPath); + + clipAssetPathList.Add(assetPath); + clips.Add(clip); } + Debug.Log(sb.ToString()); + + // reload + // AssetDatabase.Refresh(); + // var clips = clipAssetPathList.Select(x => AssetDatabase.LoadAssetAtPath(x)).ToList(); { // create blendshape avatar & replace @@ -67,6 +85,12 @@ namespace VRM blendShapeAvatar.Clips.AddRange(clips); var assetPath = $"{assetFolder}/blendshape.asset"; AssetDatabase.CreateAsset(blendShapeAvatar, assetPath); + + // reload + // AssetDatabase.Refresh(); + // blendShapeAvatar = AssetDatabase.LoadAssetAtPath(assetPath); + + // assign proxy.BlendShapeAvatar = blendShapeAvatar; } } From 22aca72ed2fa72e500bc41f3c870a0f7718bb3f8 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 18 May 2022 13:53:40 +0900 Subject: [PATCH 12/19] fix --- .../SkinnedMeshUtility/VRMMeshIntegratorUtility.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Assets/VRM/Editor/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs b/Assets/VRM/Editor/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs index 9ae4132af..d09a33e46 100644 --- a/Assets/VRM/Editor/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs +++ b/Assets/VRM/Editor/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs @@ -20,7 +20,7 @@ namespace VRM { return; } - var result = results.FirstOrDefault(x => x.SourceSkinnedMeshRenderers.Count > 0); + var result = results.FirstOrDefault(x => x.IntegratedRenderer.sharedMesh.blendShapeCount > 0); if (result == null) { return; @@ -43,6 +43,7 @@ namespace VRM // copy var clip = BlendShapeClip.Instantiate(src); + clip.Prefab = null; // modify for (var i = 0; i < clip.Values.Length; ++i) @@ -61,7 +62,6 @@ namespace VRM val.RelativePath = dstPath; val.Index = newIndex; } - clip.Values[i] = val; } @@ -81,17 +81,17 @@ namespace VRM { // create blendshape avatar & replace - var blendShapeAvatar = BlendShapeAvatar.CreateInstance(); - blendShapeAvatar.Clips.AddRange(clips); + var copy = BlendShapeAvatar.CreateInstance(); + copy.Clips.AddRange(clips); var assetPath = $"{assetFolder}/blendshape.asset"; - AssetDatabase.CreateAsset(blendShapeAvatar, assetPath); + AssetDatabase.CreateAsset(copy, assetPath); // reload // AssetDatabase.Refresh(); // blendShapeAvatar = AssetDatabase.LoadAssetAtPath(assetPath); // assign - proxy.BlendShapeAvatar = blendShapeAvatar; + proxy.BlendShapeAvatar = copy; } } } From 81422e22be53c92ca9d253eb8ddf1d4849d676c8 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 18 May 2022 14:28:24 +0900 Subject: [PATCH 13/19] remove DeactivateOldRendererAndAddIntegrated --- .../VrmMeshIntegratorWizard.cs | 57 ++++++++----------- 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs b/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs index 3797ba473..e61489a8b 100644 --- a/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs +++ b/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs @@ -227,6 +227,7 @@ namespace VRM /// /// * scene or prefab どっちでも動作する /// * backup するのではなく 変更した copy を作成する。元は変えない + /// * copy 先の統合前の renderer を disable で残さず destroy する /// * 実行すると mesh, blendshape, blendShape を新規に作成する /// * scene のときは新しいヒエラルキーが出現する /// * prefab のときは新しいヒエラルキーを prefab 保存して、scene の方を削除して終了する @@ -257,9 +258,6 @@ namespace VRM var excludes = m_excludes.Where(x => x.Exclude).Select(x => x.Mesh); var results = Integrate(copy, excludes, m_separateByBlendShape); - // 統合前のMeshを非表示にして、統合した結果をヒエラルキーに追加する - DeactivateOldRendererAndAddIntegrated(copy, results); - // write mesh asset foreach (var result in results) { @@ -268,9 +266,31 @@ namespace VRM AssetDatabase.CreateAsset(result.IntegratedRenderer.sharedMesh, childAssetPath); } + // 統合した結果をヒエラルキーに追加する + foreach (var result in results) + { + if (result.IntegratedRenderer != null) + { + result.IntegratedRenderer.transform.SetParent(copy.transform, false); + } + } + // 統合した結果を反映した BlendShapeClip を作成して置き換える VRMMeshIntegratorUtility.FollowBlendshapeRendererChange(results, copy, assetFolder); + // 用が済んだ 統合前 の renderer を削除する + foreach (var result in results) + { + foreach (var renderer in result.SourceMeshRenderers) + { + GameObject.DestroyImmediate(renderer); + } + foreach (var renderer in result.SourceSkinnedMeshRenderers) + { + GameObject.DestroyImmediate(renderer); + } + } + // reset firstperson var firstperson = copy.GetComponent(); if (firstperson != null) @@ -313,37 +333,6 @@ namespace VRM return results; } - /// - /// 古いMeshを disable にし、新しい統合済み mesh を追加する - /// - static void DeactivateOldRendererAndAddIntegrated(GameObject root, List results) - { - // disable source renderer - foreach (var result in results) - { - foreach (var renderer in result.SourceSkinnedMeshRenderers) - { - Undo.RecordObject(renderer.gameObject, "Deactivate old renderer"); - renderer.gameObject.SetActive(false); - } - - foreach (var renderer in result.SourceMeshRenderers) - { - Undo.RecordObject(renderer.gameObject, "Deactivate old renderer"); - renderer.gameObject.SetActive(false); - } - } - - // Add integrated - foreach (var result in results) - { - if (result.IntegratedRenderer != null) - { - result.IntegratedRenderer.transform.SetParent(root.transform, false); - } - } - } - void OnWizardCreate() { Integrate(); From 7eb564feea7a80edd9f1fa9cba630aff3ec54681 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 18 May 2022 15:19:55 +0900 Subject: [PATCH 14/19] prefab only --- Assets/VRM/Editor/BlendShape/PreviewEditor.cs | 16 +++++ .../SerializedBlendShapeClipEditor.cs | 59 +++++++++++-------- .../VRMMeshIntegratorUtility.cs | 29 +++++---- .../VrmMeshIntegratorWizard.cs | 50 ++++++++++------ .../VRM/Runtime/BlendShape/BlendShapeClip.cs | 13 +++- 5 files changed, 110 insertions(+), 57 deletions(-) diff --git a/Assets/VRM/Editor/BlendShape/PreviewEditor.cs b/Assets/VRM/Editor/BlendShape/PreviewEditor.cs index c12f8d6d3..179f2fe32 100644 --- a/Assets/VRM/Editor/BlendShape/PreviewEditor.cs +++ b/Assets/VRM/Editor/BlendShape/PreviewEditor.cs @@ -4,6 +4,7 @@ using UnityEditorInternal; using System; using System.Linq; using System.Collections.Generic; +using System.IO; namespace VRM { @@ -107,6 +108,21 @@ namespace VRM var prefabPath = parent.Parent.Child(parent.FileNameWithoutExtension + ".prefab"); prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(prefabPath.Value); } + // once more, with string-based method. search same folder *.prefab + if (prefab == null) + { + var parent = UniGLTF.UnityPath.FromUnityPath(assetPath).Parent; + foreach (var file in Directory.EnumerateFiles(parent.FullPath)) + { + var ext = Path.GetExtension(file).ToLower(); + if (ext == ".prefab") + { + var prefabPath = UniGLTF.UnityPath.FromFullpath(file); + prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(prefabPath.Value); + break; + } + } + } return prefab; } diff --git a/Assets/VRM/Editor/BlendShape/SerializedBlendShapeClipEditor.cs b/Assets/VRM/Editor/BlendShape/SerializedBlendShapeClipEditor.cs index 17112291f..2923b5f9e 100644 --- a/Assets/VRM/Editor/BlendShape/SerializedBlendShapeClipEditor.cs +++ b/Assets/VRM/Editor/BlendShape/SerializedBlendShapeClipEditor.cs @@ -134,38 +134,41 @@ namespace VRM // v0.45 Added. Binary flag EditorGUILayout.PropertyField(m_isBinaryProp, true); - EditorGUILayout.Space(); - //m_mode = EditorGUILayout.Popup("SourceType", m_mode, MODES); - m_mode = GUILayout.Toolbar(m_mode, MODES); - switch (m_mode) + if (m_targetObject.m_prefab != null) { - case 0: - { - ClipGUI(); - } - break; - - case 1: - { - if (GUILayout.Button("Clear")) + EditorGUILayout.Space(); + //m_mode = EditorGUILayout.Popup("SourceType", m_mode, MODES); + m_mode = GUILayout.Toolbar(m_mode, MODES); + switch (m_mode) + { + case 0: { - m_changed = true; - m_valuesProp.arraySize = 0; + ClipGUI(); } - m_ValuesList.DoLayoutList(); - } - break; + break; - case 2: - { - if (GUILayout.Button("Clear")) + case 1: { - m_changed = true; - m_materialsProp.arraySize = 0; + if (GUILayout.Button("Clear")) + { + m_changed = true; + m_valuesProp.arraySize = 0; + } + m_ValuesList.DoLayoutList(); } - m_MaterialValuesList.DoLayoutList(); - } - break; + break; + + case 2: + { + if (GUILayout.Button("Clear")) + { + m_changed = true; + m_materialsProp.arraySize = 0; + } + m_MaterialValuesList.DoLayoutList(); + } + break; + } } m_serializedObject.ApplyModifiedProperties(); @@ -231,6 +234,10 @@ namespace VRM // すべてのSkinnedMeshRendererを列挙する foreach (var renderer in m_items.Select(x => x.SkinnedMeshRenderer)) { + if(renderer==null) + { + continue; + } var mesh = renderer.sharedMesh; if (mesh != null && mesh.blendShapeCount > 0) { diff --git a/Assets/VRM/Editor/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs b/Assets/VRM/Editor/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs index d09a33e46..055e561c6 100644 --- a/Assets/VRM/Editor/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs +++ b/Assets/VRM/Editor/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs @@ -13,17 +13,18 @@ namespace VRM /// public static class VRMMeshIntegratorUtility { - public static void FollowBlendshapeRendererChange(List results, GameObject root, string assetFolder) + public static List FollowBlendshapeRendererChange(List results, GameObject root, string assetFolder) { + var clips = new List(); var proxy = root.GetComponent(); if (proxy == null || proxy.BlendShapeAvatar == null) { - return; + return clips; } var result = results.FirstOrDefault(x => x.IntegratedRenderer.sharedMesh.blendShapeCount > 0); if (result == null) { - return; + return clips; } var rendererDict = new Dictionary(); @@ -36,19 +37,19 @@ namespace VRM // copy modify and write var clipAssetPathList = new List(); var sb = new StringBuilder(); - var clips = new List(); foreach (var src in proxy.BlendShapeAvatar.Clips) { if (src == null) continue; // copy - var clip = BlendShapeClip.Instantiate(src); - clip.Prefab = null; + var copy = ScriptableObject.CreateInstance(); + copy.CopyFrom(src); + copy.Prefab = null; // modify - for (var i = 0; i < clip.Values.Length; ++i) + for (var i = 0; i < copy.Values.Length; ++i) { - var val = clip.Values[i]; + var val = copy.Values[i]; if (rendererDict.ContainsKey(val.RelativePath)) { var srcRenderer = rendererDict[val.RelativePath]; @@ -62,16 +63,16 @@ namespace VRM val.RelativePath = dstPath; val.Index = newIndex; } - clip.Values[i] = val; + copy.Values[i] = val; } // write - var assetPath = $"{assetFolder}/{clip.name}.asset"; + var assetPath = $"{assetFolder}/{copy.name}.asset"; sb.AppendLine($"write: {assetPath}"); - AssetDatabase.CreateAsset(clip, assetPath); + AssetDatabase.CreateAsset(copy, assetPath); clipAssetPathList.Add(assetPath); - clips.Add(clip); + clips.Add(copy); } Debug.Log(sb.ToString()); @@ -81,7 +82,7 @@ namespace VRM { // create blendshape avatar & replace - var copy = BlendShapeAvatar.CreateInstance(); + var copy = ScriptableObject.CreateInstance(); copy.Clips.AddRange(clips); var assetPath = $"{assetFolder}/blendshape.asset"; AssetDatabase.CreateAsset(copy, assetPath); @@ -93,6 +94,8 @@ namespace VRM // assign proxy.BlendShapeAvatar = copy; } + + return clips; } } } \ No newline at end of file diff --git a/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs b/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs index e61489a8b..cb468d539 100644 --- a/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs +++ b/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs @@ -26,6 +26,7 @@ namespace VRM None, NoTarget, HasParent, + NotPrefab, } [SerializeField] @@ -100,7 +101,6 @@ namespace VRM private void OnEnable() { Clear(HelpMessage.Ready, ValidationError.None); - m_root = Selection.activeGameObject; OnValidate(); } @@ -165,12 +165,19 @@ namespace VRM void OnValidate() { + isValid = false; if (m_root == null) { Clear(HelpMessage.SetTarget, ValidationError.NoTarget); return; } + if (m_root.GetGameObjectType() != GameObjectType.AssetPrefab) + { + Clear(HelpMessage.SetTarget, ValidationError.NotPrefab); + return; + } + if (m_root.transform.parent != null) { Clear(HelpMessage.InvalidTarget, ValidationError.HasParent); @@ -225,7 +232,7 @@ namespace VRM /// 2022.05 仕様変更 /// - /// * scene or prefab どっちでも動作する + /// * prefab 専用 /// * backup するのではなく 変更した copy を作成する。元は変えない /// * copy 先の統合前の renderer を disable で残さず destroy する /// * 実行すると mesh, blendshape, blendShape を新規に作成する @@ -234,6 +241,11 @@ namespace VRM /// void Integrate() { + if (m_root.GetGameObjectType() != GameObjectType.AssetPrefab) + { + throw new Exception("for prefab only"); + } + String folder = "Assets"; var prefab = m_root.GetPrefab(); if (prefab != null) @@ -276,7 +288,7 @@ namespace VRM } // 統合した結果を反映した BlendShapeClip を作成して置き換える - VRMMeshIntegratorUtility.FollowBlendshapeRendererChange(results, copy, assetFolder); + var clips = VRMMeshIntegratorUtility.FollowBlendshapeRendererChange(results, copy, assetFolder); // 用が済んだ 統合前 の renderer を削除する foreach (var result in results) @@ -298,23 +310,27 @@ namespace VRM firstperson.Reset(); } - if (prefab != null) + // prefab + var prefabPath = $"{assetFolder}/VrmIntegrated.prefab"; + Debug.Log(prefabPath); + PrefabUtility.SaveAsPrefabAsset(copy, prefabPath, out bool success); + if (!success) { - // prefab - var prefabPath = $"{assetFolder}/VrmIntegrated.prefab"; - Debug.Log(prefabPath); - PrefabUtility.SaveAsPrefabAsset(copy, prefabPath, out bool success); - if (!success) - { - throw new System.Exception($"PrefabUtility.SaveAsPrefabAsset: {prefabPath}"); - } - - // destroy scene - UnityEngine.Object.DestroyImmediate(copy); + throw new System.Exception($"PrefabUtility.SaveAsPrefabAsset: {prefabPath}"); } - else + + // destroy scene + UnityEngine.Object.DestroyImmediate(copy); + + var prefabReference = AssetDatabase.LoadAssetAtPath(prefabPath); + foreach (var clip in clips) { - // do nothing. keep scene + var so = new SerializedObject(clip); + so.Update(); + // clip.Prefab = copy; + var prop = so.FindProperty("m_prefab"); + prop.objectReferenceValue = prefabReference; + so.ApplyModifiedProperties(); } } diff --git a/Assets/VRM/Runtime/BlendShape/BlendShapeClip.cs b/Assets/VRM/Runtime/BlendShape/BlendShapeClip.cs index ab560ca8e..038f16c9e 100644 --- a/Assets/VRM/Runtime/BlendShape/BlendShapeClip.cs +++ b/Assets/VRM/Runtime/BlendShape/BlendShapeClip.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using UnityEngine; @@ -79,7 +80,7 @@ namespace VRM /// Preview 用のObject参照 /// [SerializeField] - GameObject m_prefab; + public GameObject m_prefab; public GameObject Prefab { set { m_prefab = value; } @@ -142,5 +143,15 @@ namespace VRM /// [SerializeField] public bool IsBinary; + + public void CopyFrom(BlendShapeClip src) + { + IsBinary = src.IsBinary; + MaterialValues = src.MaterialValues.ToArray(); + Values = src.Values.ToArray(); + Preset = src.Preset; + name = src.name; + Prefab = src.Prefab; + } } } From e5142dff17dc7fef4893c48f2d57116c94f41f62 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 18 May 2022 15:33:54 +0900 Subject: [PATCH 15/19] prefab search for preview --- Assets/VRM/Editor/BlendShape/PreviewEditor.cs | 36 +----------- .../VRM/Runtime/BlendShape/BlendShapeClip.cs | 56 +++++++++++++++---- 2 files changed, 45 insertions(+), 47 deletions(-) diff --git a/Assets/VRM/Editor/BlendShape/PreviewEditor.cs b/Assets/VRM/Editor/BlendShape/PreviewEditor.cs index 179f2fe32..6a27374ff 100644 --- a/Assets/VRM/Editor/BlendShape/PreviewEditor.cs +++ b/Assets/VRM/Editor/BlendShape/PreviewEditor.cs @@ -89,41 +89,7 @@ namespace VRM protected virtual GameObject GetPrefab() { - var assetPath = AssetDatabase.GetAssetPath(target); - if (string.IsNullOrEmpty(assetPath)) - { - return null; - } - - var prefab = AssetDatabase.LoadAssetAtPath(assetPath); - // search prefab if nothing - if (prefab == null && 0 < (target as BlendShapeAvatar).Clips.Count) - { - prefab = (target as BlendShapeAvatar).Clips[0].Prefab; - } - // once more, with string-based method - if (prefab == null) - { - var parent = UniGLTF.UnityPath.FromUnityPath(assetPath).Parent; - var prefabPath = parent.Parent.Child(parent.FileNameWithoutExtension + ".prefab"); - prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(prefabPath.Value); - } - // once more, with string-based method. search same folder *.prefab - if (prefab == null) - { - var parent = UniGLTF.UnityPath.FromUnityPath(assetPath).Parent; - foreach (var file in Directory.EnumerateFiles(parent.FullPath)) - { - var ext = Path.GetExtension(file).ToLower(); - if (ext == ".prefab") - { - var prefabPath = UniGLTF.UnityPath.FromFullpath(file); - prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(prefabPath.Value); - break; - } - } - } - return prefab; + return BlendShapeClip.VrmPrefabSearch(target); } protected virtual void OnEnable() diff --git a/Assets/VRM/Runtime/BlendShape/BlendShapeClip.cs b/Assets/VRM/Runtime/BlendShape/BlendShapeClip.cs index 038f16c9e..a2ffc30b3 100644 --- a/Assets/VRM/Runtime/BlendShape/BlendShapeClip.cs +++ b/Assets/VRM/Runtime/BlendShape/BlendShapeClip.cs @@ -1,6 +1,10 @@ using System; +using System.IO; using System.Linq; using UnityEngine; +#if UNITY_EDITOR +using UnityEditor; +#endif namespace VRM @@ -76,6 +80,45 @@ namespace VRM public class BlendShapeClip : ScriptableObject { #if UNITY_EDITOR + /// + /// Inspector preview 用の prefab をがんばってサーチする + /// + /// + /// + public static GameObject VrmPrefabSearch(UnityEngine.Object target) + { + var assetPath = AssetDatabase.GetAssetPath(target); + if (string.IsNullOrEmpty(assetPath)) + { + return null; + } + + var prefab = AssetDatabase.LoadAssetAtPath(assetPath); + // once more, with string-based method + if (prefab == null) + { + var parent = UniGLTF.UnityPath.FromUnityPath(assetPath).Parent; + var prefabPath = parent.Parent.Child(parent.FileNameWithoutExtension + ".prefab"); + prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(prefabPath.Value); + } + // once more, with string-based method. search same folder *.prefab + if (prefab == null) + { + var parent = UniGLTF.UnityPath.FromUnityPath(assetPath).Parent; + foreach (var file in Directory.EnumerateFiles(parent.FullPath)) + { + var ext = Path.GetExtension(file).ToLower(); + if (ext == ".prefab") + { + var prefabPath = UniGLTF.UnityPath.FromFullpath(file); + prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(prefabPath.Value); + break; + } + } + } + return prefab; + } + /// /// Preview 用のObject参照 /// @@ -88,18 +131,7 @@ namespace VRM { if (m_prefab == null) { - var assetPath = UnityEditor.AssetDatabase.GetAssetPath(this); - if (!string.IsNullOrEmpty(assetPath)) - { - // if asset is subasset of prefab - m_prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(assetPath); - if (m_prefab == null) - { - var parent = UniGLTF.UnityPath.FromAsset(this).Parent; - var prefabPath = parent.Parent.Child(parent.FileNameWithoutExtension + ".prefab"); - m_prefab = UnityEditor.AssetDatabase.LoadAssetAtPath(prefabPath.Value); - } - } + m_prefab = VrmPrefabSearch(this); } return m_prefab; } From 852b1860fdba6f732bd15cd36370c88816b57eed Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 18 May 2022 15:53:38 +0900 Subject: [PATCH 16/19] =?UTF-8?q?=E4=B8=8D=E8=A6=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SerializedBlendShapeClipEditor.cs | 55 +++++++++---------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/Assets/VRM/Editor/BlendShape/SerializedBlendShapeClipEditor.cs b/Assets/VRM/Editor/BlendShape/SerializedBlendShapeClipEditor.cs index 2923b5f9e..8bf3dddb4 100644 --- a/Assets/VRM/Editor/BlendShape/SerializedBlendShapeClipEditor.cs +++ b/Assets/VRM/Editor/BlendShape/SerializedBlendShapeClipEditor.cs @@ -134,41 +134,38 @@ namespace VRM // v0.45 Added. Binary flag EditorGUILayout.PropertyField(m_isBinaryProp, true); - if (m_targetObject.m_prefab != null) + EditorGUILayout.Space(); + //m_mode = EditorGUILayout.Popup("SourceType", m_mode, MODES); + m_mode = GUILayout.Toolbar(m_mode, MODES); + switch (m_mode) { - EditorGUILayout.Space(); - //m_mode = EditorGUILayout.Popup("SourceType", m_mode, MODES); - m_mode = GUILayout.Toolbar(m_mode, MODES); - switch (m_mode) - { - case 0: - { - ClipGUI(); - } - break; + case 0: + { + ClipGUI(); + } + break; - case 1: + case 1: + { + if (GUILayout.Button("Clear")) { - if (GUILayout.Button("Clear")) - { - m_changed = true; - m_valuesProp.arraySize = 0; - } - m_ValuesList.DoLayoutList(); + m_changed = true; + m_valuesProp.arraySize = 0; } - break; + m_ValuesList.DoLayoutList(); + } + break; - case 2: + case 2: + { + if (GUILayout.Button("Clear")) { - if (GUILayout.Button("Clear")) - { - m_changed = true; - m_materialsProp.arraySize = 0; - } - m_MaterialValuesList.DoLayoutList(); + m_changed = true; + m_materialsProp.arraySize = 0; } - break; - } + m_MaterialValuesList.DoLayoutList(); + } + break; } m_serializedObject.ApplyModifiedProperties(); @@ -234,7 +231,7 @@ namespace VRM // すべてのSkinnedMeshRendererを列挙する foreach (var renderer in m_items.Select(x => x.SkinnedMeshRenderer)) { - if(renderer==null) + if (renderer == null) { continue; } From cb315c661d86af68279118a5c6250438b993bf12 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 18 May 2022 15:57:21 +0900 Subject: [PATCH 17/19] comment --- .../VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs b/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs index cb468d539..2f81c5571 100644 --- a/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs +++ b/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs @@ -236,8 +236,7 @@ namespace VRM /// * backup するのではなく 変更した copy を作成する。元は変えない /// * copy 先の統合前の renderer を disable で残さず destroy する /// * 実行すると mesh, blendshape, blendShape を新規に作成する - /// * scene のときは新しいヒエラルキーが出現する - /// * prefab のときは新しいヒエラルキーを prefab 保存して、scene の方を削除して終了する + /// * 新しいヒエラルキーを prefab に保存してから削除して終了する /// void Integrate() { From facbf1f874c2e31a5f14c055a488a9f52f8122ab Mon Sep 17 00:00:00 2001 From: ousttrue Date: Thu, 19 May 2022 16:30:08 +0900 Subject: [PATCH 18/19] =?UTF-8?q?BoneMeshRemoverValidator=20=E5=BB=83?= =?UTF-8?q?=E6=AD=A2=E3=80=82=E6=A9=9F=E8=83=BD=E3=81=8C=E3=82=88=E3=81=8F?= =?UTF-8?q?=E3=82=8F=E3=81=8B=E3=82=89=E3=81=AA=E3=81=84=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MeshUtility/BoneMeshRemoverValidator.cs | 66 ------------------- .../BoneMeshRemoverValidator.cs.meta | 11 ---- .../Editor/MeshUtility/MeshProcessDialog.cs | 3 - 3 files changed, 80 deletions(-) delete mode 100644 Assets/UniGLTF/Editor/MeshUtility/BoneMeshRemoverValidator.cs delete mode 100644 Assets/UniGLTF/Editor/MeshUtility/BoneMeshRemoverValidator.cs.meta diff --git a/Assets/UniGLTF/Editor/MeshUtility/BoneMeshRemoverValidator.cs b/Assets/UniGLTF/Editor/MeshUtility/BoneMeshRemoverValidator.cs deleted file mode 100644 index 29d4b7c24..000000000 --- a/Assets/UniGLTF/Editor/MeshUtility/BoneMeshRemoverValidator.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; - -namespace UniGLTF.MeshUtility -{ - public class BoneMeshRemoverValidator - { - private Animator _cAnimator = null; - private Transform _cEraseRoot = null; - private SkinnedMeshRenderer _pSkinnedMesh; - private Animator _pAnimator; - private Transform _pEraseRoot; - - public void Validate(SkinnedMeshRenderer _skinnedMesh, List _eraseBones) - { - // any better way we can detect component change? - if (_skinnedMesh != _pSkinnedMesh || _cAnimator != _pAnimator || _cEraseRoot != _pEraseRoot) - { - BoneMeshEraserValidate(_skinnedMesh, _eraseBones); - } - _pSkinnedMesh = _skinnedMesh; - _pAnimator = _cAnimator; - _pEraseRoot = _cEraseRoot; - } - - void BoneMeshEraserValidate(SkinnedMeshRenderer skinnedMeshRenderer, List eraseBones) - { - eraseBones.Clear(); - if (skinnedMeshRenderer == null) - { - return; - } - - if (_cEraseRoot == null) - { - if (_cAnimator != null) - { - _cEraseRoot = _cAnimator.GetBoneTransform(HumanBodyBones.Head); - //Debug.LogFormat("head: {0}", EraseRoot); - } - } - - eraseBones.AddRange(skinnedMeshRenderer.bones.Select(x => - { - var eb = new BoneMeshEraser.EraseBone - { - Bone = x, - }; - - if (_cEraseRoot != null) - { - // 首の子孫を消去 - if (eb.Bone.Ancestor().Any(y => y == _cEraseRoot)) - { - //Debug.LogFormat("erase {0}", x); - eb.Erase = true; - } - } - - return eb; - })); - } - } -} diff --git a/Assets/UniGLTF/Editor/MeshUtility/BoneMeshRemoverValidator.cs.meta b/Assets/UniGLTF/Editor/MeshUtility/BoneMeshRemoverValidator.cs.meta deleted file mode 100644 index 48f27b214..000000000 --- a/Assets/UniGLTF/Editor/MeshUtility/BoneMeshRemoverValidator.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: fb28fac2e7b5e684fb023a88862106f0 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs index 63c0c6e99..b1fc04feb 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs @@ -12,8 +12,6 @@ namespace UniGLTF.MeshUtility private GameObject _exportTarget; - public BoneMeshRemoverValidator _boneMeshRemoverValidator = new BoneMeshRemoverValidator(); - [SerializeField] public bool _separateByBlendShape = true; @@ -92,7 +90,6 @@ namespace UniGLTF.MeshUtility { _boneMeshEraserEditor.OnInspectorGUI(); } - _boneMeshRemoverValidator.Validate(_skinnedMeshRenderer, _eraseBones); if (TabBoneMeshRemover.TryExecutable(_exportTarget, _skinnedMeshRenderer, out string msg)) { processed = TabBoneMeshRemover.OnGUI(_exportTarget, _skinnedMeshRenderer, _eraseBones); From 3054eff5d76a5fc8d70569b0cb6c8d62222b1e04 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Thu, 19 May 2022 16:38:00 +0900 Subject: [PATCH 19/19] fix --- .../Editor/MeshUtility/GameObjectType.cs | 2 +- .../VRMMeshIntegratorUtility.cs | 8 --- .../SkinnedMeshUtility/VrmPrefabUtility.cs | 50 ------------------- .../VRM/Runtime/BlendShape/BlendShapeClip.cs | 2 +- 4 files changed, 2 insertions(+), 60 deletions(-) diff --git a/Assets/UniGLTF/Editor/MeshUtility/GameObjectType.cs b/Assets/UniGLTF/Editor/MeshUtility/GameObjectType.cs index 9199406e5..04acaa8d2 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/GameObjectType.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/GameObjectType.cs @@ -42,7 +42,7 @@ namespace UniGLTF.MeshUtility } else { - throw new System.Exception("unknown"); + throw new System.NotSupportedException("Unknown prefab status. The target does not exist in a valid scene and is not a prefab."); } } diff --git a/Assets/VRM/Editor/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs b/Assets/VRM/Editor/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs index 055e561c6..af74ab1bd 100644 --- a/Assets/VRM/Editor/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs +++ b/Assets/VRM/Editor/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs @@ -76,10 +76,6 @@ namespace VRM } Debug.Log(sb.ToString()); - // reload - // AssetDatabase.Refresh(); - // var clips = clipAssetPathList.Select(x => AssetDatabase.LoadAssetAtPath(x)).ToList(); - { // create blendshape avatar & replace var copy = ScriptableObject.CreateInstance(); @@ -87,10 +83,6 @@ namespace VRM var assetPath = $"{assetFolder}/blendshape.asset"; AssetDatabase.CreateAsset(copy, assetPath); - // reload - // AssetDatabase.Refresh(); - // blendShapeAvatar = AssetDatabase.LoadAssetAtPath(assetPath); - // assign proxy.BlendShapeAvatar = copy; } diff --git a/Assets/VRM/Editor/SkinnedMeshUtility/VrmPrefabUtility.cs b/Assets/VRM/Editor/SkinnedMeshUtility/VrmPrefabUtility.cs index 0f203752b..dd834276a 100644 --- a/Assets/VRM/Editor/SkinnedMeshUtility/VrmPrefabUtility.cs +++ b/Assets/VRM/Editor/SkinnedMeshUtility/VrmPrefabUtility.cs @@ -46,55 +46,5 @@ namespace VRM PrefabUtility.SaveAsPrefabAssetAndConnect(instance, path, InteractionMode.AutomatedAction); } - - /// - /// VRM prefab を ${prefab_dir}/MeshIntegratorBackup/ に複製する。 - /// - /// * prefab - /// * BlendShapeAvatar - /// * BlendShapeClip - /// - /// が複製される。 - /// - /// - public static void BackupVrmPrefab(GameObject go) - { - var prefab = go.GetGameObjectType() == GameObjectType.AssetPrefab ? go : PrefabUtility.GetCorrespondingObjectFromSource(go); - var prefabPath = UnityPath.FromAsset(prefab); - - var proxy = go.GetComponent(); - - var srcAvatar = proxy.BlendShapeAvatar; - var dstAvatar = (BlendShapeAvatar)BackupAsset(srcAvatar, prefabPath); - - var clipMapper = srcAvatar.Clips.ToDictionary(x => x, x => (BlendShapeClip)BackupAsset(x, prefabPath)); - dstAvatar.Clips = clipMapper.Values.ToList(); - - var dstPrefab = BackupAsset(prefab, prefabPath); - var dstInstance = InstantiatePrefab(dstPrefab); - dstInstance.GetComponent().BlendShapeAvatar = dstAvatar; - ApplyChangesToPrefab(dstInstance); - Object.DestroyImmediate(dstInstance); - } - - /// - /// asset を ${prefab_dir}/MeshIntegratorBackup/ にコピーし、コピーしたアセットをロードして返す - /// - /// - /// - /// - /// - private static T BackupAsset(T asset, UnityPath prefabPath) where T : UnityEngine.Object - { - var srcAssetPath = UnityPath.FromAsset(asset); - var assetName = srcAssetPath.FileName; - - var backupPath = prefabPath.Parent.Child(BACKUP_DIR); - backupPath.EnsureFolder(); - var dstAssetPath = backupPath.Child(assetName); - - AssetDatabase.CopyAsset(srcAssetPath.Value, dstAssetPath.Value); - return dstAssetPath.LoadAsset(); - } } } diff --git a/Assets/VRM/Runtime/BlendShape/BlendShapeClip.cs b/Assets/VRM/Runtime/BlendShape/BlendShapeClip.cs index a2ffc30b3..481383512 100644 --- a/Assets/VRM/Runtime/BlendShape/BlendShapeClip.cs +++ b/Assets/VRM/Runtime/BlendShape/BlendShapeClip.cs @@ -123,7 +123,7 @@ namespace VRM /// Preview 用のObject参照 /// [SerializeField] - public GameObject m_prefab; + GameObject m_prefab; public GameObject Prefab { set { m_prefab = value; }