From b890201581cf01642f499584b3dcdab3e2c1a1cc Mon Sep 17 00:00:00 2001 From: ousttrue Date: Mon, 27 Nov 2023 20:23:16 +0900 Subject: [PATCH] PrefabUtility.UnpackPrefabInstance --- .../Editor/MeshUtility/MeshUtilityDialog.cs | 34 ++++++----- .../Editor/MeshUtility/MeshUtilityMessages.cs | 56 ++++++++++--------- .../Runtime/Extensions/UnityExtensions.cs | 37 +++++++++++- 3 files changed, 87 insertions(+), 40 deletions(-) diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshUtilityDialog.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshUtilityDialog.cs index 07faa5bfd..d940c312a 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshUtilityDialog.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshUtilityDialog.cs @@ -155,15 +155,6 @@ namespace UniGLTF.MeshUtility // m_excludes.AddRange(excludes); // } - /// - /// Scene と Prefab で挙動をスイッチする。 - /// - /// - Scene: ヒエラルキーを操作する。Asset の 書き出しはしない。UNDO はする。TODO: 明示的な Asset の書き出し。 - /// - Prefab: 対象をコピーして処理する。Undo は実装しない。結果を Asset として書き出し、処理後にコピーは削除する。 - /// - /// - bool TargetIsPrefab => _exportTarget != null && _exportTarget.scene.name == null; - protected virtual void DialogMessage() { EditorGUILayout.HelpBox(MeshUtilityMessages.MESH_UTILITY.Msg(), MessageType.Info); @@ -172,7 +163,6 @@ namespace UniGLTF.MeshUtility private void OnGUI() { var modified = false; - _scrollPos = EditorGUILayout.BeginScrollView(_scrollPos); EditorGUIUtility.labelWidth = 200; LanguageGetter.OnGuiSelectLang(); @@ -187,11 +177,23 @@ namespace UniGLTF.MeshUtility MeshIntegration.UpdateMeshIntegrationList(_exportTarget); modified = true; } + if (_exportTarget == null) + { + return; + } + + _scrollPos = EditorGUILayout.BeginScrollView(_scrollPos); // GameObject or Prefab ? - if (TargetIsPrefab) + switch (_exportTarget.GetPrefabType()) { - EditorGUILayout.HelpBox(MeshUtilityMessages.PREFAB_TARGET.Msg(), MessageType.Warning); + case UnityExtensions.PrefabType.PrefabAsset: + EditorGUILayout.HelpBox(MeshUtilityMessages.PREFAB_ASSET.Msg(), MessageType.Warning); + break; + + case UnityExtensions.PrefabType.PrefabInstance: + EditorGUILayout.HelpBox(MeshUtilityMessages.PREFAB_INSTANCE.Msg(), MessageType.Warning); + break; } // tab bar @@ -255,7 +257,7 @@ namespace UniGLTF.MeshUtility GUI.enabled = true; if (pressed) { - if (TargetIsPrefab) + if (_exportTarget.GetPrefabType() == UnityExtensions.PrefabType.PrefabAsset) { /// [prefab] /// @@ -283,6 +285,7 @@ namespace UniGLTF.MeshUtility assetFolder = unityPath.Value; var copy = GameObject.Instantiate(_exportTarget); + PrefabUtility.UnpackPrefabInstance(copy, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction); var (results, created) = MeshUtility.Process(copy); @@ -294,6 +297,11 @@ namespace UniGLTF.MeshUtility else { Undo.RegisterFullObjectHierarchyUndo(_exportTarget, "MeshUtility"); + + if (_exportTarget.GetPrefabType() == UnityExtensions.PrefabType.PrefabInstance) + { + PrefabUtility.UnpackPrefabInstance(_exportTarget, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction); + } var (results, created) = MeshUtility.Process(_exportTarget); foreach (var go in created) { diff --git a/Assets/UniGLTF/Editor/MeshUtility/MeshUtilityMessages.cs b/Assets/UniGLTF/Editor/MeshUtility/MeshUtilityMessages.cs index c48251e22..a516e0c96 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/MeshUtilityMessages.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/MeshUtilityMessages.cs @@ -44,36 +44,36 @@ Separate the mesh attached to the SkinnedMeshRenderer under the target object wi [LangMsg(Languages.en, "Divide by the presence or absence of `blendshape`")] MESH_SEPARATOR_BY_BLENDSHAPE, -// [LangMsg(Languages.ja, @"ターゲットオブジェクト下の SkinnedMeshRenderer または MeshFilter にアタッチされたメッシュを統合します。 + // [LangMsg(Languages.ja, @"ターゲットオブジェクト下の SkinnedMeshRenderer または MeshFilter にアタッチされたメッシュを統合します。 -// * Asset: Assets/MeshIntegrated.mesh が作成されます(上書きされるので注意してください)。 -// * Scene: コピーされたヒエラルキーでは、統合された Mesh は除去されます。新しく MeshIntegrator ノードが追加されます。 -// * VRMではBlendShapeClipの統合など追加の処理が必要です。`VRM0-MeshIntegratorWizard` を使ってください。 -// ")] -// [LangMsg(Languages.en, @"Integrates the attached mesh into the SkinnedMeshRenderer or MeshFilter under the target object. + // * Asset: Assets/MeshIntegrated.mesh が作成されます(上書きされるので注意してください)。 + // * Scene: コピーされたヒエラルキーでは、統合された Mesh は除去されます。新しく MeshIntegrator ノードが追加されます。 + // * VRMではBlendShapeClipの統合など追加の処理が必要です。`VRM0-MeshIntegratorWizard` を使ってください。 + // ")] + // [LangMsg(Languages.en, @"Integrates the attached mesh into the SkinnedMeshRenderer or MeshFilter under the target object. -// * 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 `VRM0-MeshIntegratorWizard` integration feature. -// ")] -// MESH_INTEGRATOR, + // * 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 `VRM0-MeshIntegratorWizard` 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 を保持する三角形を除去します。 + // [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. + // * 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. -// ")] + // * 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. + // ")] -// BONE_MESH_ERASER, + // BONE_MESH_ERASER, [LangMsg(Languages.ja, "Skinned Meshを選んでください")] [LangMsg(Languages.en, "Select a skinned mesh")] @@ -103,8 +103,12 @@ Separate the mesh attached to the SkinnedMeshRenderer under the target object wi [LangMsg(Languages.en, "Because BlendShapeClip causes inconsistency , use `VRM0 -> MeshIntegrator` instead")] VRM_DETECTED, - [LangMsg(Languages.ja, "対象は, Prefab です。実行時に書き出しファイルの指定があります。")] - [LangMsg(Languages.en, "The target is prefab. A temporary file is specified during execution.")] - PREFAB_TARGET, + [LangMsg(Languages.ja, "対象は, Prefab Asset です。実行時に書き出しファイルの指定があります。")] + [LangMsg(Languages.en, "The target is prefab asset. A temporary file is specified during execution.")] + PREFAB_ASSET, + + [LangMsg(Languages.ja, "対象は, Prefab Instance です。Unpack されます。")] + [LangMsg(Languages.en, "The target is prefab asset. A temporary file is specified during execution.")] + PREFAB_INSTANCE, } } \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/Extensions/UnityExtensions.cs b/Assets/UniGLTF/Runtime/Extensions/UnityExtensions.cs index 58321b08f..17bbb3bba 100644 --- a/Assets/UniGLTF/Runtime/Extensions/UnityExtensions.cs +++ b/Assets/UniGLTF/Runtime/Extensions/UnityExtensions.cs @@ -449,5 +449,40 @@ namespace UniGLTF } return true; } + + public enum PrefabType + { + PrefabAsset, + PrefabInstance, + NotPrefab, + } + + /// + /// Scene と Prefab で挙動をスイッチする。 + /// + /// - Scene: ヒエラルキーを操作する。Asset の 書き出しはしない。UNDO はする。TODO: 明示的な Asset の書き出し。 + /// - Prefab: 対象をコピーして処理する。Undo は実装しない。結果を Asset として書き出し、処理後にコピーは削除する。 + /// + /// + public static PrefabType GetPrefabType(this GameObject go) + { + if (go == null) + { + throw new ArgumentNullException(); + } + if (!go.scene.IsValid()) + { + return PrefabType.PrefabAsset; + } + +#if UNITY_EDITOR + if (PrefabUtility.GetOutermostPrefabInstanceRoot(go) != null) + { + return PrefabType.PrefabInstance; + } +#endif + + return PrefabType.NotPrefab; + } } -} +} \ No newline at end of file