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; + } } }