From 5517dc26749bda6d728bbcd3e6fc5fa53d4b518f Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 10 May 2022 15:31:41 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=E3=82=B3=E3=83=BC=E3=83=89=E6=95=B4?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Editor/MeshUtility/BoneMeshEraserGUI.cs | 23 ++++++ .../MeshUtility/BoneMeshEraserGUI.cs.meta | 11 +++ .../Editor/MeshUtility/MeshProcessDialog.cs | 73 ++----------------- .../MeshUtility/MeshProcessingMessages.cs | 55 ++++++++++++++ .../MeshProcessingMessages.cs.meta | 11 +++ Assets/UniGLTF/Editor/TopMenu.cs | 5 +- .../UniGLTF/Editor/TopMenuImplementation.cs | 13 +--- 7 files changed, 110 insertions(+), 81 deletions(-) create mode 100644 Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserGUI.cs create mode 100644 Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserGUI.cs.meta create mode 100644 Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs create mode 100644 Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs.meta diff --git a/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserGUI.cs b/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserGUI.cs new file mode 100644 index 000000000..a22cfd77e --- /dev/null +++ b/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserGUI.cs @@ -0,0 +1,23 @@ +using UnityEditor; +using UnityEngine; + +namespace UniGLTF.MeshUtility +{ + [CustomEditor(typeof(MeshProcessDialog), true)] + public class BoneMeshEraserGUI : Editor + { + public override void OnInspectorGUI() + { + serializedObject.Update(); + var skinnedMesh = serializedObject.FindProperty("_cSkinnedMesh"); + EditorGUILayout.PropertyField(skinnedMesh, new GUIContent("Skinned Mesh"), true); + var animator = serializedObject.FindProperty("_cAnimator"); + EditorGUILayout.PropertyField(animator, new GUIContent("Animator"), false); + var eraseRoot = serializedObject.FindProperty("_cEraseRoot"); + EditorGUILayout.PropertyField(eraseRoot, new GUIContent("Erase Root"), false); + var list = serializedObject.FindProperty("_eraseBones"); + EditorGUILayout.PropertyField(list, new GUIContent("Erase Bones"), true); + serializedObject.ApplyModifiedProperties(); + } + } +} diff --git a/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserGUI.cs.meta b/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserGUI.cs.meta new file mode 100644 index 000000000..eddf8f87d --- /dev/null +++ b/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserGUI.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5cdbec3de528c61448aeb739ffe1f79e +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 c42b5a8cd..eda9391d6 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs @@ -9,24 +9,6 @@ using UniGLTF.M17N; namespace UniGLTF.MeshUtility { - [CustomEditor(typeof(MeshProcessDialog), true)] - public class BoneMeshEraserGUI : Editor - { - public override void OnInspectorGUI() - { - serializedObject.Update(); - var skinnedMesh = serializedObject.FindProperty("_cSkinnedMesh"); - EditorGUILayout.PropertyField(skinnedMesh, new GUIContent("Skinned Mesh"), true); - var animator = serializedObject.FindProperty("_cAnimator"); - EditorGUILayout.PropertyField(animator, new GUIContent("Animator"), false); - var eraseRoot = serializedObject.FindProperty("_cEraseRoot"); - EditorGUILayout.PropertyField(eraseRoot, new GUIContent("Erase Root"), false); - var list = serializedObject.FindProperty("_eraseBones"); - EditorGUILayout.PropertyField(list, new GUIContent("Erase Bones"), true); - serializedObject.ApplyModifiedProperties(); - } - } - public class MeshProcessDialog : EditorWindow { enum Tabs @@ -60,55 +42,14 @@ namespace UniGLTF.MeshUtility GUIStyle _tabButtonStyle => "LargeButton"; GUI.ToolbarButtonSize _tabButtonSize => GUI.ToolbarButtonSize.Fixed; - private enum MeshProcessingMessages + + public static void OpenWindow() { - [LangMsg(Languages.ja, "ターゲットオブジェクト")] - [LangMsg(Languages.en, "TargetObject")] - TARGET_OBJECT, - - [LangMsg(Languages.ja, "BlendShapeを含むメッシュは分割されます")] - [LangMsg(Languages.en, "Meshes containing BlendShape will be split")] - MESH_SEPARATOR, - - [LangMsg(Languages.ja, "メッシュを統合します。BlendShapeを含むメッシュは独立して統合されます")] - [LangMsg(Languages.en, "Generate a single mesh. Meshes w/ BlendShape will be grouped into another one")] - MESH_INTEGRATOR, - - [LangMsg(Languages.ja, "静的メッシュを一つに統合します")] - [LangMsg(Languages.en, "Integrate static meshes into one")] - STATIC_MESH_INTEGRATOR, - - [LangMsg(Languages.ja, "ボーン(Erase Rootのヒエラルキー)に関連するメッシュを削除します")] - [LangMsg(Languages.en, "Eliminate meshes associated with the bones in EraseRoot hierarchy")] - BONE_MESH_ERASER, - - [LangMsg(Languages.ja, "Skinned Meshを選んでください")] - [LangMsg(Languages.en, "Select a skinned mesh")] - SELECT_SKINNED_MESH, - - [LangMsg(Languages.ja, "Erase Rootを選んでください")] - [LangMsg(Languages.en, "Select a erase root")] - SELECT_ERASE_ROOT, - - [LangMsg(Languages.ja, "GameObjectを選んでください")] - [LangMsg(Languages.en, "Select a GameObject first")] - NO_GAMEOBJECT_SELECTED, - - [LangMsg(Languages.ja, "GameObjectにスキンメッシュが含まれていません")] - [LangMsg(Languages.en, "No skinned mesh is contained")] - NO_SKINNED_MESH, - - [LangMsg(Languages.ja, "GameObjectに静的メッシュが含まれていません")] - [LangMsg(Languages.en, "No static mesh is contained")] - NO_STATIC_MESH, - - [LangMsg(Languages.ja, "GameObjectにスキンメッシュ・静的メッシュが含まれていません")] - [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")] - VRM_DETECTED, + var window = + (MeshProcessDialog)EditorWindow.GetWindowWithRect(typeof(MeshProcessDialog), + new Rect(0, 0, 650, 500)); + window.titleContent = new GUIContent("Mesh Processing Window"); + window.Show(); } private void OnEnable() diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs new file mode 100644 index 000000000..3e406a8cc --- /dev/null +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs @@ -0,0 +1,55 @@ +using UniGLTF.M17N; + +namespace UniGLTF.MeshUtility +{ + public enum MeshProcessingMessages + { + [LangMsg(Languages.ja, "ターゲットオブジェクト")] + [LangMsg(Languages.en, "TargetObject")] + TARGET_OBJECT, + + [LangMsg(Languages.ja, "BlendShapeを含むメッシュは分割されます")] + [LangMsg(Languages.en, "Meshes containing BlendShape will be split")] + MESH_SEPARATOR, + + [LangMsg(Languages.ja, "メッシュを統合します。BlendShapeを含むメッシュは独立して統合されます")] + [LangMsg(Languages.en, "Generate a single mesh. Meshes w/ BlendShape will be grouped into another one")] + MESH_INTEGRATOR, + + [LangMsg(Languages.ja, "静的メッシュを一つに統合します")] + [LangMsg(Languages.en, "Integrate static meshes into one")] + STATIC_MESH_INTEGRATOR, + + [LangMsg(Languages.ja, "ボーン(Erase Rootのヒエラルキー)に関連するメッシュを削除します")] + [LangMsg(Languages.en, "Eliminate meshes associated with the bones in EraseRoot hierarchy")] + BONE_MESH_ERASER, + + [LangMsg(Languages.ja, "Skinned Meshを選んでください")] + [LangMsg(Languages.en, "Select a skinned mesh")] + SELECT_SKINNED_MESH, + + [LangMsg(Languages.ja, "Erase Rootを選んでください")] + [LangMsg(Languages.en, "Select a erase root")] + SELECT_ERASE_ROOT, + + [LangMsg(Languages.ja, "GameObjectを選んでください")] + [LangMsg(Languages.en, "Select a GameObject first")] + NO_GAMEOBJECT_SELECTED, + + [LangMsg(Languages.ja, "GameObjectにスキンメッシュが含まれていません")] + [LangMsg(Languages.en, "No skinned mesh is contained")] + NO_SKINNED_MESH, + + [LangMsg(Languages.ja, "GameObjectに静的メッシュが含まれていません")] + [LangMsg(Languages.en, "No static mesh is contained")] + NO_STATIC_MESH, + + [LangMsg(Languages.ja, "GameObjectにスキンメッシュ・静的メッシュが含まれていません")] + [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")] + VRM_DETECTED, + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs.meta b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs.meta new file mode 100644 index 000000000..e3b56a221 --- /dev/null +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 575d573f28f0e4a48a2a6509e69b7f6f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Editor/TopMenu.cs b/Assets/UniGLTF/Editor/TopMenu.cs index 2a7083cf5..f41b442e6 100644 --- a/Assets/UniGLTF/Editor/TopMenu.cs +++ b/Assets/UniGLTF/Editor/TopMenu.cs @@ -26,10 +26,7 @@ namespace UniGLTF private static void ImportGltfFile() => TopMenuImplementation.ImportGltfFileToGameObject(); [MenuItem(UserMeshUtilityPrefix + "/MeshProcessing Wizard", priority = 10)] - private static void OpenMeshProcessingWindow() => TopMenuImplementation.OpenMeshProcessingWindow(); - - [MenuItem(UserMeshUtilityPrefix + "/Open Documents", priority = 11)] - private static void MeshUtilityDocs() => Application.OpenURL("https://vrm.dev/en/docs/univrm/gltf/mesh_utility/"); + private static void OpenMeshProcessingWindow() => MeshUtility.MeshProcessDialog.OpenWindow(); #if VRM_DEVELOP [MenuItem(DevelopmentMenuPrefix + "/Generate Serialization Code", priority = 20)] diff --git a/Assets/UniGLTF/Editor/TopMenuImplementation.cs b/Assets/UniGLTF/Editor/TopMenuImplementation.cs index a9ec44f1f..6a5cf2ad6 100644 --- a/Assets/UniGLTF/Editor/TopMenuImplementation.cs +++ b/Assets/UniGLTF/Editor/TopMenuImplementation.cs @@ -8,7 +8,7 @@ namespace UniGLTF { public static void ExportGameObjectToGltfFile() { - var window = (GltfExportWindow) GltfExportWindow.GetWindow(typeof(GltfExportWindow)); + var window = (GltfExportWindow)GltfExportWindow.GetWindow(typeof(GltfExportWindow)); window.titleContent = new GUIContent("Gltf Exporter"); window.Show(); } @@ -92,19 +92,10 @@ namespace UniGLTF Selection.activeObject = asset; } - public static void OpenMeshProcessingWindow() - { - var window = - (MeshUtility.MeshProcessDialog) EditorWindow.GetWindowWithRect(typeof(MeshUtility.MeshProcessDialog), - new Rect(0, 0, 650, 500)); - window.titleContent = new GUIContent("Mesh Processing Window"); - window.Show(); - } - public static void GenerateSerializationCode() { SerializerGenerator.GenerateSerializer(); DeserializerGenerator.GenerateSerializer(); } } -} \ No newline at end of file +} From cba5af786abc5d2e58a6e534d9b30bacb0f0251e Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 10 May 2022 16:34:54 +0900 Subject: [PATCH 2/3] =?UTF-8?q?=E5=87=A6=E7=90=86=E3=82=92=20static=20clas?= =?UTF-8?q?s=20=E3=81=AB=E5=88=86=E5=89=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Editor/MeshUtility/MeshProcessDialog.cs | 267 ++---------------- .../Editor/MeshUtility/TabBoneMeshRemover.cs | 116 ++++++++ .../MeshUtility/TabBoneMeshRemover.cs.meta | 11 + .../Editor/MeshUtility/TabMeshIntegrator.cs | 61 ++++ .../MeshUtility/TabMeshIntegrator.cs.meta | 11 + .../Editor/MeshUtility/TabMeshSeparator.cs | 57 ++++ .../MeshUtility/TabMeshSeparator.cs.meta | 11 + .../MeshUtility/TabStaticMeshIntegrator.cs | 47 +++ .../TabStaticMeshIntegrator.cs.meta | 11 + 9 files changed, 356 insertions(+), 236 deletions(-) create mode 100644 Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs create mode 100644 Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs.meta create mode 100644 Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs create mode 100644 Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs.meta create mode 100644 Assets/UniGLTF/Editor/MeshUtility/TabMeshSeparator.cs create mode 100644 Assets/UniGLTF/Editor/MeshUtility/TabMeshSeparator.cs.meta create mode 100644 Assets/UniGLTF/Editor/MeshUtility/TabStaticMeshIntegrator.cs create mode 100644 Assets/UniGLTF/Editor/MeshUtility/TabStaticMeshIntegrator.cs.meta diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs index eda9391d6..ef15a9d84 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs @@ -1,5 +1,3 @@ -using System; -using System.IO; using System.Linq; using System.Reflection; using UnityEngine; @@ -37,7 +35,6 @@ namespace UniGLTF.MeshUtility private BoneMeshEraser.EraseBone[] _eraseBones; private MethodInfo _processFunction; - private bool _isInvokeSuccess = false; GUIStyle _tabButtonStyle => "LargeButton"; GUI.ToolbarButtonSize _tabButtonSize => GUI.ToolbarButtonSize.Fixed; @@ -68,23 +65,53 @@ namespace UniGLTF.MeshUtility LanguageGetter.OnGuiSelectLang(); _tab = TabBar.OnGUI(_tab, _tabButtonStyle, _tabButtonSize); - + var processed = false; switch (_tab) { case Tabs.MeshSeparator: EditorGUILayout.LabelField(MeshProcessingMessages.MESH_SEPARATOR.Msg()); + OnGUI_ExportTarget(); + processed = TabMeshSeparator.OnGUI(_exportTarget); break; case Tabs.MeshIntegrator: EditorGUILayout.LabelField(MeshProcessingMessages.MESH_INTEGRATOR.Msg()); + OnGUI_ExportTarget(); + processed = TabMeshIntegrator.OnGUI(_exportTarget); break; case Tabs.StaticMeshIntegrator: EditorGUILayout.LabelField(MeshProcessingMessages.STATIC_MESH_INTEGRATOR.Msg()); + OnGUI_ExportTarget(); + processed = TabStaticMeshIntegrator.OnGUI(_exportTarget); break; case Tabs.BoneMeshEraser: EditorGUILayout.LabelField(MeshProcessingMessages.BONE_MESH_ERASER.Msg()); + OnGUI_ExportTarget(); + if (_boneMeshEraserEditor) + { + _boneMeshEraserEditor.OnInspectorGUI(); + } + // any better way we can detect component change? + if (_cSkinnedMesh != _pSkinnedMesh || _cAnimator != _pAnimator || _cEraseRoot != _pEraseRoot) + { + BoneMeshEraserValidate(); + } + _pSkinnedMesh = _cSkinnedMesh; + _pAnimator = _cAnimator; + _pEraseRoot = _cEraseRoot; + processed = TabBoneMeshRemover.OnGUI(_exportTarget, _cSkinnedMesh, _cEraseRoot, _eraseBones); break; } + EditorGUILayout.EndScrollView(); + if (processed) + { + Close(); + GUIUtility.ExitGUI(); + } + } + + private void OnGUI_ExportTarget() + { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(MeshProcessingMessages.TARGET_OBJECT.Msg(), GUILayout.MaxWidth(146.0f)); _exportTarget = (GameObject)EditorGUILayout.ObjectField(_exportTarget, typeof(GameObject), true); @@ -93,175 +120,6 @@ namespace UniGLTF.MeshUtility { _exportTarget = Selection.activeObject as GameObject; } - - if (_tab == Tabs.BoneMeshEraser) - { - if (_boneMeshEraserEditor) - { - _boneMeshEraserEditor.OnInspectorGUI(); - } - // any better way we can detect component change? - if (_cSkinnedMesh != _pSkinnedMesh || _cAnimator != _pAnimator || _cEraseRoot != _pEraseRoot) - { - BoneMeshEraserValidate(); - } - _pSkinnedMesh = _cSkinnedMesh; - _pAnimator = _cAnimator; - _pEraseRoot = _cEraseRoot; - } - - // Create Other Buttons - { - GUILayout.BeginVertical(); - { - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - - if (GUILayout.Button("Process", GUILayout.MinWidth(100))) - { - switch (_tab) - { - case Tabs.MeshSeparator: - _isInvokeSuccess = InvokeWizardUpdate("MeshSeparator"); - break; - case Tabs.MeshIntegrator: - _isInvokeSuccess = InvokeWizardUpdate("MeshIntegrator"); - break; - case Tabs.StaticMeshIntegrator: - _isInvokeSuccess = InvokeWizardUpdate("StaticMeshIntegrator"); - break; - case Tabs.BoneMeshEraser: - _isInvokeSuccess = InvokeWizardUpdate("BoneMeshRemover"); - break; - } - if (_isInvokeSuccess) - { - Close(); - GUIUtility.ExitGUI(); - } - } - GUI.enabled = true; - - GUILayout.EndHorizontal(); - } - GUILayout.EndVertical(); - } - EditorGUILayout.EndScrollView(); - } - - private bool InvokeWizardUpdate(string processFuntion) - { - const BindingFlags kInstanceInvokeFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy; - _processFunction = GetType().GetMethod(processFuntion, kInstanceInvokeFlags); - if (_processFunction != null) - { - return (Boolean)_processFunction.Invoke(this, null); - } - else - { - Debug.LogError("This function has not been implemented in script"); - return false; - } - } - - private bool GameObjectNull() - { - EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_GAMEOBJECT_SELECTED.Msg(), "ok"); - return false; - } - - private bool MeshSeparator() - { - if (_exportTarget == null) return GameObjectNull(); - var go = _exportTarget; - - if (go.GetComponentsInChildren().Length > 0) - { - // copy - var outputObject = GameObject.Instantiate(go); - outputObject.name = outputObject.name + "_mesh_separation"; - // 改変と asset の作成 - var list = MeshUtility.SeparationProcessing(outputObject); - foreach (var (src, with, without) in list) - { - // asset の永続化 - MeshUtility.SaveMesh(src, with, MeshUtility.BlendShapeLogic.WithBlendShape); - MeshUtility.SaveMesh(src, without, MeshUtility.BlendShapeLogic.WithoutBlendShape); - } - return true; - } - else - { - EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_SKINNED_MESH.Msg(), "ok"); - return false; - } - } - - private bool MeshIntegrator() - { - if (_exportTarget == null) return GameObjectNull(); - var go = _exportTarget; - - Component[] allComponents = go.GetComponents(typeof(Component)); - var keyWord = "VRMMeta"; - - foreach (var component in allComponents) - { - if (component == null) continue; - var sourceString = component.ToString(); - if (sourceString.Contains(keyWord)) - { - EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.VRM_DETECTED.Msg(), "ok"); - return false; - } - } - - if (go.GetComponentsInChildren().Length > 0 || go.GetComponentsInChildren().Length > 0) - { - MeshUtility.MeshIntegrator(go); - return true; - } - else - { - EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_MESH.Msg(), "ok"); - return false; - } - } - - private bool StaticMeshIntegrator() - { - if (_exportTarget == null) return GameObjectNull(); - var go = _exportTarget; - if (go.GetComponentsInChildren().Length > 0) - { - MeshUtility.IntegrateSelected(go); - return true; - } - else - { - EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_STATIC_MESH.Msg(), "ok"); - return false; - } - } - - private bool BoneMeshRemover() - { - if (_exportTarget == null) return GameObjectNull(); - var go = _exportTarget; - - if (_cSkinnedMesh == null) - { - EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.SELECT_SKINNED_MESH.Msg(), "ok"); - return false; - } - else if (_cEraseRoot == null) - { - EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.SELECT_ERASE_ROOT.Msg(), "ok"); - return false; - } - BoneMeshRemove(go); - - return true; } private void BoneMeshEraserValidate() @@ -302,68 +160,5 @@ namespace UniGLTF.MeshUtility }) .ToArray(); } - - private void BoneMeshRemove(GameObject go) - { - var renderer = Remove(go); - var outputObject = GameObject.Instantiate(go); - outputObject.name = outputObject.name + "_bone_mesh_erase"; - if (renderer == null) - { - return; - } - - // save mesh to Assets - var assetPath = string.Format("{0}{1}", go.name, MeshUtility.ASSET_SUFFIX); - var prefab = MeshUtility.GetPrefab(go); - if (prefab != null) - { - var prefabPath = AssetDatabase.GetAssetPath(prefab); - assetPath = string.Format("{0}/{1}{2}", - Path.GetDirectoryName(prefabPath), - Path.GetFileNameWithoutExtension(prefabPath), - MeshUtility.ASSET_SUFFIX - ); - } - - Debug.LogFormat("CreateAsset: {0}", assetPath); - AssetDatabase.CreateAsset(renderer.sharedMesh, assetPath); - - // destroy BoneMeshEraser in the source - foreach (var skinnedMesh in go.GetComponentsInChildren()) - { - if (skinnedMesh.gameObject.name == BoneMeshEraserWizard.BONE_MESH_ERASER_NAME) - { - GameObject.DestroyImmediate(skinnedMesh.gameObject); - } - } - // destroy the original mesh in the copied GameObject - foreach (var skinnedMesh in outputObject.GetComponentsInChildren()) - { - if (skinnedMesh.sharedMesh == _cSkinnedMesh.sharedMesh) - { - GameObject.DestroyImmediate(skinnedMesh); - } - } - } - - private SkinnedMeshRenderer Remove(GameObject go) - { - var bones = _cSkinnedMesh.bones; - var eraseBones = _eraseBones - .Where(x => x.Erase) - .Select(x => Array.IndexOf(bones, x.Bone)) - .ToArray(); - - var meshNode = new GameObject(BoneMeshEraserWizard.BONE_MESH_ERASER_NAME); - meshNode.transform.SetParent(go.transform, false); - - var erased = meshNode.AddComponent(); - erased.sharedMesh = BoneMeshEraser.CreateErasedMesh(_cSkinnedMesh.sharedMesh, eraseBones); - erased.sharedMaterials = _cSkinnedMesh.sharedMaterials; - erased.bones = _cSkinnedMesh.bones; - - return erased; - } } } \ No newline at end of file diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs b/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs new file mode 100644 index 000000000..b4400fa2f --- /dev/null +++ b/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs @@ -0,0 +1,116 @@ +using System; +using System.IO; +using System.Linq; +using UniGLTF.M17N; +using UnityEditor; +using UnityEngine; + +namespace UniGLTF.MeshUtility +{ + public static class TabBoneMeshRemover + { + public static bool OnGUI(GameObject _exportTarget, SkinnedMeshRenderer _cSkinnedMesh, Transform _cEraseRoot, BoneMeshEraser.EraseBone[] _eraseBones) + { + var _isInvokeSuccess = false; + GUILayout.BeginVertical(); + { + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + if (GUILayout.Button("Process", GUILayout.MinWidth(100))) + { + _isInvokeSuccess = TabBoneMeshRemover.Execute(_exportTarget, _cSkinnedMesh, _cEraseRoot, _eraseBones); + } + GUILayout.EndHorizontal(); + } + GUILayout.EndVertical(); + return _isInvokeSuccess; + } + + public static bool Execute(GameObject _exportTarget, SkinnedMeshRenderer _cSkinnedMesh, Transform _cEraseRoot, BoneMeshEraser.EraseBone[] _eraseBones) + { + if (_exportTarget == null) + { + EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_GAMEOBJECT_SELECTED.Msg(), "ok"); + return false; + } + var go = _exportTarget; + + if (_cSkinnedMesh == null) + { + EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.SELECT_SKINNED_MESH.Msg(), "ok"); + return false; + } + else if (_cEraseRoot == null) + { + EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.SELECT_ERASE_ROOT.Msg(), "ok"); + return false; + } + BoneMeshRemove(go, _cSkinnedMesh, _eraseBones); + + return true; + } + + private static void BoneMeshRemove(GameObject go, SkinnedMeshRenderer _cSkinnedMesh, BoneMeshEraser.EraseBone[] _eraseBones) + { + var renderer = Remove(go, _cSkinnedMesh, _eraseBones); + var outputObject = GameObject.Instantiate(go); + outputObject.name = outputObject.name + "_bone_mesh_erase"; + if (renderer == null) + { + return; + } + + // save mesh to Assets + var assetPath = string.Format("{0}{1}", go.name, MeshUtility.ASSET_SUFFIX); + var prefab = MeshUtility.GetPrefab(go); + if (prefab != null) + { + var prefabPath = AssetDatabase.GetAssetPath(prefab); + assetPath = string.Format("{0}/{1}{2}", + Path.GetDirectoryName(prefabPath), + Path.GetFileNameWithoutExtension(prefabPath), + MeshUtility.ASSET_SUFFIX + ); + } + + Debug.LogFormat("CreateAsset: {0}", assetPath); + AssetDatabase.CreateAsset(renderer.sharedMesh, assetPath); + + // destroy BoneMeshEraser in the source + foreach (var skinnedMesh in go.GetComponentsInChildren()) + { + if (skinnedMesh.gameObject.name == BoneMeshEraserWizard.BONE_MESH_ERASER_NAME) + { + GameObject.DestroyImmediate(skinnedMesh.gameObject); + } + } + // destroy the original mesh in the copied GameObject + foreach (var skinnedMesh in outputObject.GetComponentsInChildren()) + { + if (skinnedMesh.sharedMesh == _cSkinnedMesh.sharedMesh) + { + GameObject.DestroyImmediate(skinnedMesh); + } + } + } + + private static SkinnedMeshRenderer Remove(GameObject go, SkinnedMeshRenderer _cSkinnedMesh, BoneMeshEraser.EraseBone[] _eraseBones) + { + var bones = _cSkinnedMesh.bones; + var eraseBones = _eraseBones + .Where(x => x.Erase) + .Select(x => Array.IndexOf(bones, x.Bone)) + .ToArray(); + + var meshNode = new GameObject(BoneMeshEraserWizard.BONE_MESH_ERASER_NAME); + meshNode.transform.SetParent(go.transform, false); + + var erased = meshNode.AddComponent(); + erased.sharedMesh = BoneMeshEraser.CreateErasedMesh(_cSkinnedMesh.sharedMesh, eraseBones); + erased.sharedMaterials = _cSkinnedMesh.sharedMaterials; + erased.bones = _cSkinnedMesh.bones; + + return erased; + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs.meta b/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs.meta new file mode 100644 index 000000000..29e107335 --- /dev/null +++ b/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4094f82d7ee108a4997d80a692116033 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs b/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs new file mode 100644 index 000000000..9befa651b --- /dev/null +++ b/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs @@ -0,0 +1,61 @@ +using UniGLTF.M17N; +using UnityEditor; +using UnityEngine; + +namespace UniGLTF.MeshUtility +{ + public static class TabMeshIntegrator + { + public static bool OnGUI(GameObject _exportTarget) + { + var _isInvokeSuccess = false; + GUILayout.BeginVertical(); + { + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + if (GUILayout.Button("Process", GUILayout.MinWidth(100))) + { + _isInvokeSuccess = TabMeshIntegrator.Execute(_exportTarget); + } + GUILayout.EndHorizontal(); + } + GUILayout.EndVertical(); + return _isInvokeSuccess; + } + + static bool Execute(GameObject _exportTarget) + { + if (_exportTarget == null) + { + EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_GAMEOBJECT_SELECTED.Msg(), "ok"); + return false; + } + var go = _exportTarget; + + var allComponents = go.GetComponents(typeof(Component)); + var keyWord = "VRMMeta"; + + foreach (var component in allComponents) + { + if (component == null) continue; + var sourceString = component.ToString(); + if (sourceString.Contains(keyWord)) + { + EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.VRM_DETECTED.Msg(), "ok"); + return false; + } + } + + if (go.GetComponentsInChildren().Length > 0 || go.GetComponentsInChildren().Length > 0) + { + MeshUtility.MeshIntegrator(go); + return true; + } + else + { + EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_MESH.Msg(), "ok"); + return false; + } + } + } +} diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs.meta b/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs.meta new file mode 100644 index 000000000..5c60a51fe --- /dev/null +++ b/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 65a227dcf3cb5f34085bd6829894fb64 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabMeshSeparator.cs b/Assets/UniGLTF/Editor/MeshUtility/TabMeshSeparator.cs new file mode 100644 index 000000000..0966be00e --- /dev/null +++ b/Assets/UniGLTF/Editor/MeshUtility/TabMeshSeparator.cs @@ -0,0 +1,57 @@ +using UniGLTF.M17N; +using UnityEditor; +using UnityEngine; + +namespace UniGLTF.MeshUtility +{ + public static class TabMeshSeparator + { + public static bool OnGUI(GameObject _exportTarget) + { + var _isInvokeSuccess = false; + GUILayout.BeginVertical(); + { + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + if (GUILayout.Button("Process", GUILayout.MinWidth(100))) + { + _isInvokeSuccess = TabMeshSeparator.Execute(_exportTarget); + } + GUILayout.EndHorizontal(); + } + GUILayout.EndVertical(); + return _isInvokeSuccess; + } + + static bool Execute(GameObject _exportTarget) + { + if (_exportTarget == null) + { + EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_GAMEOBJECT_SELECTED.Msg(), "ok"); + return false; + } + + var go = _exportTarget; + if (go.GetComponentsInChildren().Length > 0) + { + // copy + var outputObject = GameObject.Instantiate(go); + outputObject.name = outputObject.name + "_mesh_separation"; + // 改変と asset の作成 + var list = MeshUtility.SeparationProcessing(outputObject); + foreach (var (src, with, without) in list) + { + // asset の永続化 + MeshUtility.SaveMesh(src, with, MeshUtility.BlendShapeLogic.WithBlendShape); + MeshUtility.SaveMesh(src, without, MeshUtility.BlendShapeLogic.WithoutBlendShape); + } + return true; + } + else + { + EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_SKINNED_MESH.Msg(), "ok"); + return false; + } + } + } +} diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabMeshSeparator.cs.meta b/Assets/UniGLTF/Editor/MeshUtility/TabMeshSeparator.cs.meta new file mode 100644 index 000000000..8fb9a175b --- /dev/null +++ b/Assets/UniGLTF/Editor/MeshUtility/TabMeshSeparator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8921d732b66ae134db97faa11eaa9b17 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabStaticMeshIntegrator.cs b/Assets/UniGLTF/Editor/MeshUtility/TabStaticMeshIntegrator.cs new file mode 100644 index 000000000..4d837d2e7 --- /dev/null +++ b/Assets/UniGLTF/Editor/MeshUtility/TabStaticMeshIntegrator.cs @@ -0,0 +1,47 @@ +using UniGLTF.M17N; +using UnityEditor; +using UnityEngine; + +namespace UniGLTF.MeshUtility +{ + public static class TabStaticMeshIntegrator + { + public static bool OnGUI(GameObject _exportTarget) + { + var _isInvokeSuccess = false; + GUILayout.BeginVertical(); + { + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + if (GUILayout.Button("Process", GUILayout.MinWidth(100))) + { + _isInvokeSuccess = TabStaticMeshIntegrator.Execute(_exportTarget); + } + GUILayout.EndHorizontal(); + } + GUILayout.EndVertical(); + return _isInvokeSuccess; + } + + static bool Execute(GameObject _exportTarget) + { + if (_exportTarget == null) + { + EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_GAMEOBJECT_SELECTED.Msg(), "ok"); + return false; + } + var go = _exportTarget; + + if (go.GetComponentsInChildren().Length > 0) + { + MeshUtility.IntegrateSelected(go); + return true; + } + else + { + EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_STATIC_MESH.Msg(), "ok"); + return false; + } + } + } +} diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabStaticMeshIntegrator.cs.meta b/Assets/UniGLTF/Editor/MeshUtility/TabStaticMeshIntegrator.cs.meta new file mode 100644 index 000000000..4c0e30384 --- /dev/null +++ b/Assets/UniGLTF/Editor/MeshUtility/TabStaticMeshIntegrator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9701e1f6aaed8d14283243a7a50be2df +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 0541e364b850b7f23e9ed192126de2a02250448f Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 10 May 2022 18:26:34 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=E3=82=B3=E3=83=BC=E3=83=89=E6=95=B4?= =?UTF-8?q?=E7=90=86=E3=80=82=E3=83=A1=E3=83=83=E3=82=BB=E3=83=BC=E3=82=B8?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0=E3=80=82StaticMeshIntegrator=20=E5=81=9C?= =?UTF-8?q?=E6=AD=A2=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Editor/MeshUtility/BoneMeshEraserGUI.cs | 4 -- .../Editor/MeshUtility/MeshProcessDialog.cs | 56 +++++++++---------- .../MeshUtility/MeshProcessingMessages.cs | 45 ++++++++++++--- .../UniGLTF/Editor/MeshUtility/MeshUtility.cs | 10 ++++ .../Editor/MeshUtility/TabBoneMeshRemover.cs | 13 ++--- .../Editor/MeshUtility/TabMeshIntegrator.cs | 40 +++++++------ .../Editor/MeshUtility/TabMeshSeparator.cs | 34 +++++------ .../MeshUtility/TabStaticMeshIntegrator.cs | 10 ++-- 8 files changed, 123 insertions(+), 89 deletions(-) diff --git a/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserGUI.cs b/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserGUI.cs index a22cfd77e..897bfad0e 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserGUI.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/BoneMeshEraserGUI.cs @@ -11,10 +11,6 @@ namespace UniGLTF.MeshUtility serializedObject.Update(); var skinnedMesh = serializedObject.FindProperty("_cSkinnedMesh"); EditorGUILayout.PropertyField(skinnedMesh, new GUIContent("Skinned Mesh"), true); - var animator = serializedObject.FindProperty("_cAnimator"); - EditorGUILayout.PropertyField(animator, new GUIContent("Animator"), false); - var eraseRoot = serializedObject.FindProperty("_cEraseRoot"); - EditorGUILayout.PropertyField(eraseRoot, new GUIContent("Erase Root"), false); var list = serializedObject.FindProperty("_eraseBones"); EditorGUILayout.PropertyField(list, new GUIContent("Erase Bones"), true); serializedObject.ApplyModifiedProperties(); diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs index ef15a9d84..d7c352b6c 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessDialog.cs @@ -13,7 +13,7 @@ namespace UniGLTF.MeshUtility { MeshSeparator, MeshIntegrator, - StaticMeshIntegrator, + // StaticMeshIntegrator, BoneMeshEraser, } private Tabs _tab; @@ -27,10 +27,10 @@ namespace UniGLTF.MeshUtility [SerializeField] private SkinnedMeshRenderer _cSkinnedMesh = null; - [SerializeField] + private Animator _cAnimator = null; - [SerializeField] private Transform _cEraseRoot = null; + [SerializeField] private BoneMeshEraser.EraseBone[] _eraseBones; @@ -43,8 +43,7 @@ namespace UniGLTF.MeshUtility public static void OpenWindow() { var window = - (MeshProcessDialog)EditorWindow.GetWindowWithRect(typeof(MeshProcessDialog), - new Rect(0, 0, 650, 500)); + (MeshProcessDialog)EditorWindow.GetWindow(typeof(MeshProcessDialog)); window.titleContent = new GUIContent("Mesh Processing Window"); window.Show(); } @@ -64,28 +63,40 @@ namespace UniGLTF.MeshUtility // lang LanguageGetter.OnGuiSelectLang(); + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField(MeshProcessingMessages.TARGET_OBJECT.Msg(), GUILayout.MaxWidth(146.0f)); + _exportTarget = (GameObject)EditorGUILayout.ObjectField(_exportTarget, typeof(GameObject), true); + EditorGUILayout.EndHorizontal(); + if (_exportTarget == null && MeshUtility.IsGameObjectSelected()) + { + _exportTarget = Selection.activeObject as GameObject; + } + } + + // tab _tab = TabBar.OnGUI(_tab, _tabButtonStyle, _tabButtonSize); var processed = false; switch (_tab) { case Tabs.MeshSeparator: - EditorGUILayout.LabelField(MeshProcessingMessages.MESH_SEPARATOR.Msg()); - OnGUI_ExportTarget(); + EditorGUILayout.HelpBox(MeshProcessingMessages.MESH_SEPARATOR.Msg(), MessageType.Info); processed = TabMeshSeparator.OnGUI(_exportTarget); break; + case Tabs.MeshIntegrator: - EditorGUILayout.LabelField(MeshProcessingMessages.MESH_INTEGRATOR.Msg()); - OnGUI_ExportTarget(); + EditorGUILayout.HelpBox(MeshProcessingMessages.MESH_INTEGRATOR.Msg(), MessageType.Info); processed = TabMeshIntegrator.OnGUI(_exportTarget); break; - case Tabs.StaticMeshIntegrator: - EditorGUILayout.LabelField(MeshProcessingMessages.STATIC_MESH_INTEGRATOR.Msg()); - OnGUI_ExportTarget(); - processed = TabStaticMeshIntegrator.OnGUI(_exportTarget); - break; + + // MeshIntegrator と機能が重複しているのと正常に動作しなかった + // case Tabs.StaticMeshIntegrator: + // EditorGUILayout.HelpBox(MeshProcessingMessages.STATIC_MESH_INTEGRATOR.Msg(), MessageType.Info); + // processed = TabStaticMeshIntegrator.OnGUI(_exportTarget); + // break; + case Tabs.BoneMeshEraser: - EditorGUILayout.LabelField(MeshProcessingMessages.BONE_MESH_ERASER.Msg()); - OnGUI_ExportTarget(); + EditorGUILayout.HelpBox(MeshProcessingMessages.BONE_MESH_ERASER.Msg(), MessageType.Info); if (_boneMeshEraserEditor) { _boneMeshEraserEditor.OnInspectorGUI(); @@ -98,7 +109,7 @@ namespace UniGLTF.MeshUtility _pSkinnedMesh = _cSkinnedMesh; _pAnimator = _cAnimator; _pEraseRoot = _cEraseRoot; - processed = TabBoneMeshRemover.OnGUI(_exportTarget, _cSkinnedMesh, _cEraseRoot, _eraseBones); + processed = TabBoneMeshRemover.OnGUI(_exportTarget, _cSkinnedMesh, _eraseBones); break; } EditorGUILayout.EndScrollView(); @@ -110,17 +121,6 @@ namespace UniGLTF.MeshUtility } } - private void OnGUI_ExportTarget() - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField(MeshProcessingMessages.TARGET_OBJECT.Msg(), GUILayout.MaxWidth(146.0f)); - _exportTarget = (GameObject)EditorGUILayout.ObjectField(_exportTarget, typeof(GameObject), true); - EditorGUILayout.EndHorizontal(); - if (_exportTarget == null && MeshUtility.IsGameObjectSelected()) - { - _exportTarget = Selection.activeObject as GameObject; - } - } private void BoneMeshEraserValidate() { diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs index 3e406a8cc..3fe4dcfdb 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshProcessingMessages.cs @@ -8,20 +8,47 @@ namespace UniGLTF.MeshUtility [LangMsg(Languages.en, "TargetObject")] TARGET_OBJECT, - [LangMsg(Languages.ja, "BlendShapeを含むメッシュは分割されます")] - [LangMsg(Languages.en, "Meshes containing BlendShape will be split")] + [LangMsg(Languages.ja, @"ターゲットオブジェクト下の SkinnedMeshRenderer にアタッチされたメッシュを、 BlendShape の有無で分割します。 + +* Asset: 新しい Mesh Asset が元と同じフォルダに作成されます。例: Original -> Original_WithBlendShape.mesh & Original_WithoutBlendShape.mesh +* Scene: コピーされたヒエラルキーでは、分割された Mesh は BlendShape のある Mesh で置き換えられて、BlendShape の無い Mesh を使った SkinnedMeshRenderer が追加されます。 +")] + [LangMsg(Languages.en, @"Separate the mesh attached to the SkinnedMeshRenderer under the target object with or without BlendShape. + +* Asset: A new Mesh Asset will be created in the same folder as the original. Example: Original-> Original_WithBlendShape.mesh & Original_WithoutBlendShape.mesh +* Scene: In the copied hierarchy, the split Mesh is replaced with a Mesh that holds the BlendShape, and a SkinnedMeshRenderer with a Mesh without BlendShape is added. +")] MESH_SEPARATOR, - [LangMsg(Languages.ja, "メッシュを統合します。BlendShapeを含むメッシュは独立して統合されます")] - [LangMsg(Languages.en, "Generate a single mesh. Meshes w/ BlendShape will be grouped into another one")] + [LangMsg(Languages.ja, @"ターゲットオブジェクト下の SkinnedMeshRenderer または MeshFilter にアタッチされたメッシュをを統合します。BlendShape の有無で2つ作成されます。 + +* Asset: Assets/MeshIntegrated.mesh が作成されます(上書きされるので注意してください)。 +* Scene: コピーされたヒエラルキーでは、統合された Mesh は除去されます。新しく MeshIntegrator ノードが追加されます。 +* VRMではBlendShapeClipの統合など追加の処理が必要でる。VRMの統合機能を使ってください。 +")] + [LangMsg(Languages.en, @"Integrates the attached mesh into the SkinnedMeshRenderer or MeshFilter under the target object. A mesh that holds BlendShape and a mesh that does not hold BlendShape are created. + +* Asset: Assets/MeshIntegrated.mesh is created (note that it will be overwritten). +* Scene: In the copied hierarchy, the integrated mesh is removed. A new MeshIntegrator node is added. +* VRM requires additional processing such as BlendShapeClip integration. Use the VRM integration feature. +")] MESH_INTEGRATOR, - [LangMsg(Languages.ja, "静的メッシュを一つに統合します")] - [LangMsg(Languages.en, "Integrate static meshes into one")] - STATIC_MESH_INTEGRATOR, + // [LangMsg(Languages.ja, "静的メッシュを一つに統合します")] + // [LangMsg(Languages.en, "Integrate static meshes into one")] + // STATIC_MESH_INTEGRATOR, + + [LangMsg(Languages.ja, @"指定された SkinnedMeshRenderer から、指定されたボーンに対する Weight を保持する三角形を除去します。 + +* Asset: 元の Mesh と同じフォルダに、三角形を除去した Mesh を保存します。 +* Scene: コピーされたヒエラルキーでは、三角形が除去された Mesh に差し替えられます。 +")] + [LangMsg(Languages.en, @"Removes the triangle that holds the weight for the specified bone from the specified SkinnedMeshRenderer. + +* Assets: Save the mesh with the triangles removed in the same folder as the original mesh. +* Scene: In the copied hierarchy, it will be replaced with a Mesh with the triangles removed. +")] - [LangMsg(Languages.ja, "ボーン(Erase Rootのヒエラルキー)に関連するメッシュを削除します")] - [LangMsg(Languages.en, "Eliminate meshes associated with the bones in EraseRoot hierarchy")] BONE_MESH_ERASER, [LangMsg(Languages.ja, "Skinned Meshを選んでください")] diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshUtility.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshUtility.cs index b8b888c62..fd45864d8 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshUtility.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshUtility.cs @@ -264,6 +264,10 @@ namespace UniGLTF.MeshUtility return Selection.activeObject != null && Selection.activeObject is GameObject; } + /// + /// from dialog + /// + /// public static void IntegrateSelected(GameObject go) { var meshWithMaterials = StaticMeshIntegrator.Integrate(go.transform); @@ -319,6 +323,11 @@ namespace UniGLTF.MeshUtility renderer.sharedMaterials = meshWithMaterials.Materials; } #endif + + /// + /// from dialog + /// + /// public static void MeshIntegrator(GameObject go) { MeshIntegratorUtility.Integrate(go, onlyBlendShapeRenderers: true); @@ -330,6 +339,7 @@ namespace UniGLTF.MeshUtility var normalMeshes = outputObject.GetComponentsInChildren(); // destroy integrated meshes in the source + // ? foreach (var skinnedMesh in go.GetComponentsInChildren()) { if (skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_NAME || diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs b/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs index b4400fa2f..c0dc39b59 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/TabBoneMeshRemover.cs @@ -9,7 +9,7 @@ namespace UniGLTF.MeshUtility { public static class TabBoneMeshRemover { - public static bool OnGUI(GameObject _exportTarget, SkinnedMeshRenderer _cSkinnedMesh, Transform _cEraseRoot, BoneMeshEraser.EraseBone[] _eraseBones) + public static bool OnGUI(GameObject _exportTarget, SkinnedMeshRenderer _cSkinnedMesh, BoneMeshEraser.EraseBone[] _eraseBones) { var _isInvokeSuccess = false; GUILayout.BeginVertical(); @@ -18,7 +18,7 @@ namespace UniGLTF.MeshUtility GUILayout.FlexibleSpace(); if (GUILayout.Button("Process", GUILayout.MinWidth(100))) { - _isInvokeSuccess = TabBoneMeshRemover.Execute(_exportTarget, _cSkinnedMesh, _cEraseRoot, _eraseBones); + _isInvokeSuccess = TabBoneMeshRemover.Execute(_exportTarget, _cSkinnedMesh, _eraseBones); } GUILayout.EndHorizontal(); } @@ -26,7 +26,7 @@ namespace UniGLTF.MeshUtility return _isInvokeSuccess; } - public static bool Execute(GameObject _exportTarget, SkinnedMeshRenderer _cSkinnedMesh, Transform _cEraseRoot, BoneMeshEraser.EraseBone[] _eraseBones) + public static bool Execute(GameObject _exportTarget, SkinnedMeshRenderer _cSkinnedMesh, BoneMeshEraser.EraseBone[] _eraseBones) { if (_exportTarget == null) { @@ -40,13 +40,8 @@ namespace UniGLTF.MeshUtility EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.SELECT_SKINNED_MESH.Msg(), "ok"); return false; } - else if (_cEraseRoot == null) - { - EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.SELECT_ERASE_ROOT.Msg(), "ok"); - return false; - } - BoneMeshRemove(go, _cSkinnedMesh, _eraseBones); + BoneMeshRemove(go, _cSkinnedMesh, _eraseBones); return true; } diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs b/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs index 9befa651b..839d425a8 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs @@ -23,6 +23,22 @@ namespace UniGLTF.MeshUtility return _isInvokeSuccess; } + static string VRM_META = "VRMMeta"; + static bool HasVrm(GameObject go) + { + var allComponents = go.GetComponents(typeof(Component)); + foreach (var component in allComponents) + { + if (component == null) continue; + var sourceString = component.ToString(); + if (sourceString.Contains(VRM_META)) + { + return true; + } + } + return false; + } + static bool Execute(GameObject _exportTarget) { if (_exportTarget == null) @@ -32,30 +48,20 @@ namespace UniGLTF.MeshUtility } var go = _exportTarget; - var allComponents = go.GetComponents(typeof(Component)); - var keyWord = "VRMMeta"; - - foreach (var component in allComponents) + if (HasVrm(go)) { - if (component == null) continue; - var sourceString = component.ToString(); - if (sourceString.Contains(keyWord)) - { - EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.VRM_DETECTED.Msg(), "ok"); - return false; - } + EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.VRM_DETECTED.Msg(), "ok"); + return false; } - if (go.GetComponentsInChildren().Length > 0 || go.GetComponentsInChildren().Length > 0) - { - MeshUtility.MeshIntegrator(go); - return true; - } - else + if (go.GetComponentsInChildren().Length == 0 && go.GetComponentsInChildren().Length == 0) { EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_MESH.Msg(), "ok"); return false; } + + MeshUtility.MeshIntegrator(go); + return true; } } } diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabMeshSeparator.cs b/Assets/UniGLTF/Editor/MeshUtility/TabMeshSeparator.cs index 0966be00e..bef557520 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/TabMeshSeparator.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/TabMeshSeparator.cs @@ -4,6 +4,9 @@ using UnityEngine; namespace UniGLTF.MeshUtility { + /// + /// BlendShape の有無で Mesh を分割する + /// public static class TabMeshSeparator { public static bool OnGUI(GameObject _exportTarget) @@ -32,26 +35,25 @@ namespace UniGLTF.MeshUtility } var go = _exportTarget; - if (go.GetComponentsInChildren().Length > 0) - { - // copy - var outputObject = GameObject.Instantiate(go); - outputObject.name = outputObject.name + "_mesh_separation"; - // 改変と asset の作成 - var list = MeshUtility.SeparationProcessing(outputObject); - foreach (var (src, with, without) in list) - { - // asset の永続化 - MeshUtility.SaveMesh(src, with, MeshUtility.BlendShapeLogic.WithBlendShape); - MeshUtility.SaveMesh(src, without, MeshUtility.BlendShapeLogic.WithoutBlendShape); - } - return true; - } - else + if (go.GetComponentsInChildren().Length == 0) { EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_SKINNED_MESH.Msg(), "ok"); return false; } + + // copy + var outputObject = GameObject.Instantiate(go); + outputObject.name = outputObject.name + "_mesh_separation"; + + // 改変と asset の作成 + var list = MeshUtility.SeparationProcessing(outputObject); + foreach (var (src, with, without) in list) + { + // asset の永続化 + MeshUtility.SaveMesh(src, with, MeshUtility.BlendShapeLogic.WithBlendShape); + MeshUtility.SaveMesh(src, without, MeshUtility.BlendShapeLogic.WithoutBlendShape); + } + return true; } } } diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabStaticMeshIntegrator.cs b/Assets/UniGLTF/Editor/MeshUtility/TabStaticMeshIntegrator.cs index 4d837d2e7..9cdfd3e3f 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/TabStaticMeshIntegrator.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/TabStaticMeshIntegrator.cs @@ -32,16 +32,14 @@ namespace UniGLTF.MeshUtility } var go = _exportTarget; - if (go.GetComponentsInChildren().Length > 0) - { - MeshUtility.IntegrateSelected(go); - return true; - } - else + if (go.GetComponentsInChildren().Length == 0) { EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_STATIC_MESH.Msg(), "ok"); return false; } + + MeshUtility.IntegrateSelected(go); + return true; } } }