diff --git a/Scripts/BlendShape/Editor/BlendShapeAvatarEditor.cs b/Scripts/BlendShape/Editor/BlendShapeAvatarEditor.cs index 7f76f52f0..afbf100d0 100644 --- a/Scripts/BlendShape/Editor/BlendShapeAvatarEditor.cs +++ b/Scripts/BlendShape/Editor/BlendShapeAvatarEditor.cs @@ -11,12 +11,48 @@ using UnityEngine; namespace VRM { [CustomEditor(typeof(BlendShapeAvatar))] - public class BlendShapeAvatarEditor : Editor + public class BlendShapeAvatarEditor : PreviewEditor { ReorderableList m_clipList; - void OnEnable() + BlendShapeClipSelector m_selector; + + SerializedBlendShapeEditor m_clipEditor; + + protected override PreviewSceneManager.BakeValue GetBakeValue() { + var clip = m_selector.Selected; + var value = new PreviewSceneManager.BakeValue(); + if (clip != null) + { + value.BlendShapeBindings = clip.Values; + value.MaterialValueBindings = clip.MaterialValues; + value.Weight = 1.0f; + } + return value; + } + + void OnSelected(BlendShapeClip clip) + { + if (PreviewSceneManager == null) + { + m_clipEditor = null; + } + else if (clip != null) + { + m_clipEditor = new SerializedBlendShapeEditor(clip, PreviewSceneManager); + } + else + { + m_clipEditor = null; + } + Bake(); + } + + protected override void OnEnable() + { + m_selector = new BlendShapeClipSelector((BlendShapeAvatar)target, OnSelected); + var prop = serializedObject.FindProperty("Clips"); m_clipList = new ReorderableList(serializedObject, prop); @@ -58,16 +94,43 @@ namespace VRM }; //m_clipList.onCanRemoveCallback += list => true; + base.OnEnable(); + + OnSelected(m_selector.Selected); } - void OnDisable() - { - } + int m_mode; + static readonly string[] MODES = new string[]{ + "Editor", + "List" + }; public override void OnInspectorGUI() { serializedObject.Update(); - m_clipList.DoLayoutList(); + + base.OnInspectorGUI(); + + m_mode = GUILayout.Toolbar(m_mode, MODES); + switch (m_mode) + { + case 0: + m_selector.SelectGUI(); + if (m_clipEditor != null) + { + Separator(); + m_clipEditor.Draw(); + } + break; + + case 1: + m_clipList.DoLayoutList(); + break; + + default: + throw new NotImplementedException(); + } + serializedObject.ApplyModifiedProperties(); } } diff --git a/Scripts/BlendShape/Editor/BlendShapeClipEditor.cs b/Scripts/BlendShape/Editor/BlendShapeClipEditor.cs index 440076e86..8b0f67b70 100644 --- a/Scripts/BlendShape/Editor/BlendShapeClipEditor.cs +++ b/Scripts/BlendShape/Editor/BlendShapeClipEditor.cs @@ -14,6 +14,15 @@ namespace VRM SerializedBlendShapeEditor m_serializedEditor; BlendShapeClip m_target; + protected override PreviewSceneManager.BakeValue GetBakeValue() + { + return new PreviewSceneManager.BakeValue + { + BlendShapeBindings = m_target.Values, + MaterialValueBindings = m_target.MaterialValues, + Weight = 1.0f, + }; + } SerializedProperty m_thumbnailProp; SerializedProperty m_isBinaryProp; @@ -23,33 +32,15 @@ namespace VRM return m_target.Prefab; } - void OnPrefabChanged() - { - m_target.Prefab = Prefab; - Bake(m_target.Values, m_target.MaterialValues, 1.0f); - } - protected override void OnEnable() { m_target = (BlendShapeClip)target; - PrefabChanged += OnPrefabChanged; base.OnEnable(); - - Bake(m_target.Values, m_target.MaterialValues, 1.0f); - - } - - protected override void OnDisable() - { - base.OnDisable(); - PrefabChanged -= OnPrefabChanged; } float m_previewSlider = 1.0f; - - static Texture2D SaveResizedImage(RenderTexture rt, UnityPath path, int size) { var tex = new Texture2D(rt.width, rt.height, TextureFormat.RGB24, false); @@ -152,7 +143,12 @@ namespace VRM var result = m_serializedEditor.Draw(); if ((changed || result.Changed) && PreviewSceneManager != null) { - PreviewSceneManager.Bake(result.BlendShapeBindings, result.MaterialValueBindings, m_previewSlider); + PreviewSceneManager.Bake(new PreviewSceneManager.BakeValue + { + BlendShapeBindings = result.BlendShapeBindings, + MaterialValueBindings = result.MaterialValueBindings, + Weight = m_previewSlider + }); } } diff --git a/Scripts/BlendShape/Editor/BlendShapeClipSelector.cs b/Scripts/BlendShape/Editor/BlendShapeClipSelector.cs index b37d7c21d..d8ce3beb3 100644 --- a/Scripts/BlendShape/Editor/BlendShapeClipSelector.cs +++ b/Scripts/BlendShape/Editor/BlendShapeClipSelector.cs @@ -67,10 +67,12 @@ namespace VRM SelectedIndex = GUILayout.SelectionGrid(SelectedIndex, array, 4); } + /* if (GUILayout.Button("Add BlendShapeClip")) { - //m_avatar.AddBlendShapeClip(); + m_avatar.AddBlendShapeClip(); } + */ } public void DuplicateWarn() diff --git a/Scripts/BlendShape/Editor/PreviewEditor.cs b/Scripts/BlendShape/Editor/PreviewEditor.cs index b00967fed..b1615a1cb 100644 --- a/Scripts/BlendShape/Editor/PreviewEditor.cs +++ b/Scripts/BlendShape/Editor/PreviewEditor.cs @@ -13,7 +13,7 @@ namespace VRM /// * https://github.com/Unity-Technologies/UnityCsReference/blob/11bcfd801fccd2a52b09bb6fd636c1ddcc9f1705/Editor/Mono/Inspector/ModelInspector.cs /// /// - public class PreviewEditor : Editor + public abstract class PreviewEditor : Editor { /// /// PreviewRenderUtilityを管理する。 @@ -66,38 +66,26 @@ namespace VRM { m_scene.gameObject.SetActive(false); } - RaisePrefabChanged(); + + Bake(); } } } - protected event Action PrefabChanged; - void RaisePrefabChanged() - { - var handler = PrefabChanged; - if (handler == null) return; - handler(); - } + + protected abstract PreviewSceneManager.BakeValue GetBakeValue(); /// - /// シーンにBlendShapeとMaterialMorphを適用する + /// Preview シーンに BlendShape と MaterialValue を適用する /// - /// - /// - /// - protected void Bake(IEnumerable values, IEnumerable materialValues, float weight) + protected void Bake() { if (m_scene != null) { //Debug.Log("Bake"); - m_scene.Bake(values, materialValues, weight); + m_scene.Bake(GetBakeValue()); } } - protected void Bake(BlendShapeClip clip, float weight) - { - Bake(Enumerable.Empty(), Enumerable.Empty(), weight); - } - protected virtual GameObject GetPrefab() { var assetPath = AssetDatabase.GetAssetPath(target); @@ -119,6 +107,7 @@ namespace VRM protected virtual void OnEnable() { m_renderer = new PreviewFaceRenderer(); + Prefab = GetPrefab(); } diff --git a/Scripts/BlendShape/Editor/SerializedBlendShapeClipEditor.cs b/Scripts/BlendShape/Editor/SerializedBlendShapeClipEditor.cs index bda504b6e..0390b5c3d 100644 --- a/Scripts/BlendShape/Editor/SerializedBlendShapeClipEditor.cs +++ b/Scripts/BlendShape/Editor/SerializedBlendShapeClipEditor.cs @@ -31,6 +31,8 @@ namespace VRM #region MaterialValueBind const int MaterialValueBindingHeight = 90; ReorderableList m_MaterialValuesList; + + SerializedProperty m_materialsProp; #endregion #region Editor values @@ -85,13 +87,13 @@ namespace VRM } }; - var materialValuesProp = serializedObject.FindProperty("MaterialValues"); - m_MaterialValuesList = new ReorderableList(serializedObject, materialValuesProp); + m_materialsProp = serializedObject.FindProperty("MaterialValues"); + m_MaterialValuesList = new ReorderableList(serializedObject, m_materialsProp); m_MaterialValuesList.elementHeight = MaterialValueBindingHeight; m_MaterialValuesList.drawElementCallback = (rect, index, isActive, isFocused) => { - var element = materialValuesProp.GetArrayElementAtIndex(index); + var element = m_materialsProp.GetArrayElementAtIndex(index); rect.height -= 4; rect.y += 2; if (BlendShapeClipEditorHelper.DrawMaterialValueBinding(rect, element, previewSceneManager)) @@ -120,7 +122,7 @@ namespace VRM m_serializedObject.Update(); - // ReadonlyのBlendShapeClip参照 + // Readonly のBlendShapeClip参照 GUI.enabled = false; EditorGUILayout.ObjectField("Current clip", m_targetObject, typeof(BlendShapeClip), false); @@ -145,14 +147,22 @@ namespace VRM case 1: { - //EditorGUILayout.LabelField("BlendShapeBindings", EditorStyles.boldLabel); + if (GUILayout.Button("Clear")) + { + m_changed = true; + m_valuesProp.arraySize = 0; + } m_ValuesList.DoLayoutList(); } break; case 2: { - //EditorGUILayout.LabelField("MaterialValueBindings", EditorStyles.boldLabel); + if (GUILayout.Button("Clear")) + { + m_changed = true; + m_materialsProp.arraySize = 0; + } m_MaterialValuesList.DoLayoutList(); } break; @@ -170,24 +180,6 @@ namespace VRM void ClipGUI() { - // Key重複の警告 - - /* - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button("Clear")) - { - ClearBlendShape(); - } - - if (clip != null && GUILayout.Button("Apply")) - { - string maxWeightString; - clip.Values = GetBindings(out maxWeightString); - EditorUtility.SetDirty(clip); - } - EditorGUILayout.EndHorizontal(); - */ - var changed = BlendShapeBindsGUI(); if (changed) { diff --git a/Scripts/BlendShape/PreviewSceneManager.cs b/Scripts/BlendShape/PreviewSceneManager.cs index 2703b35e0..0bf80978f 100644 --- a/Scripts/BlendShape/PreviewSceneManager.cs +++ b/Scripts/BlendShape/PreviewSceneManager.cs @@ -206,25 +206,34 @@ namespace VRM } #if UNITY_EDITOR - Bounds m_bounds; - public void Bake( - IEnumerable values = null, - IEnumerable materialValues = null, - float weight = 1.0f) + + public struct BakeValue { - //Debug.LogFormat("Bake"); + public IEnumerable BlendShapeBindings; + public IEnumerable MaterialValueBindings; + public float Weight; + } + + Bounds m_bounds; + public void Bake(BakeValue bake) + { + // + // Bake BlendShape + // m_bounds = default(Bounds); if (m_meshes != null) { foreach (var x in m_meshes) { - x.Bake(values, weight); + x.Bake(bake.BlendShapeBindings, bake.Weight); m_bounds.Expand(x.Mesh.bounds.size); } } - // Udpate Material - if (materialValues != null && m_materialMap != null) + // + // Update Material + // + if (bake.MaterialValueBindings != null && m_materialMap != null) { // clear //Debug.LogFormat("clear material"); @@ -236,7 +245,7 @@ namespace VRM } } - foreach (var x in materialValues) + foreach (var x in bake.MaterialValueBindings) { MaterialItem item; if (m_materialMap.TryGetValue(x.MaterialName, out item)) @@ -245,13 +254,12 @@ namespace VRM PropItem prop; if (item.PropMap.TryGetValue(x.ValueName, out prop)) { - var value = x.BaseValue + (x.TargetValue - x.BaseValue) * weight; + var value = x.BaseValue + (x.TargetValue - x.BaseValue) * bake.Weight; item.Material.SetColor(x.ValueName, value); } } } } - } #endif