using System; using System.Collections.Generic; using System.IO; using System.Linq; using UniGLTF; using UnityEditor; using UnityEditorInternal; using UnityEngine; namespace VRM { [CustomEditor(typeof(BlendShapeAvatar))] public class BlendShapeAvatarEditor : PreviewEditor { ReorderableList m_clipList; 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); PreviewSceneManager.Bake(new PreviewSceneManager.BakeValue { BlendShapeBindings = clip.Values, MaterialValueBindings = clip.MaterialValues, Weight = 1.0f }); } else { m_clipEditor = null; PreviewSceneManager.Bake(new PreviewSceneManager.BakeValue()); } } protected override void OnEnable() { m_selector = new BlendShapeClipSelector((BlendShapeAvatar)target, OnSelected); var prop = serializedObject.FindProperty("Clips"); m_clipList = new ReorderableList(serializedObject, prop); m_clipList.drawHeaderCallback = (rect) => EditorGUI.LabelField(rect, "BlendShapeClips"); m_clipList.elementHeight = BlendShapeClipDrawer.Height; m_clipList.drawElementCallback = (rect, index, isActive, isFocused) => { var element = prop.GetArrayElementAtIndex(index); rect.height -= 4; rect.y += 2; EditorGUI.PropertyField(rect, element); }; m_clipList.onAddCallback += (list) => { // OpenFile dialog, create new BlendShapeClip var dir = Path.GetDirectoryName(AssetDatabase.GetAssetPath(target)); var path = EditorUtility.SaveFilePanel( "Create BlendShapeClip", dir, string.Format("BlendShapeClip#{0}.asset", list.count), "asset"); BlendShapeClip clip = null; if (!string.IsNullOrEmpty(path)) { clip = BlendShapeAvatar.CreateBlendShapeClip(path.ToUnityRelativePath()); //clip.Prefab = AssetDatabase.LoadAssetAtPath(AssetDatabase.GetAssetPath(target)); } // Add slot prop.arraySize++; // select last item list.index = prop.arraySize - 1; // get last item var element = prop.GetArrayElementAtIndex(list.index); element.objectReferenceValue = clip; }; m_clipList.onSelectCallback += (list) => { var a = list.serializedProperty; var selected = a.GetArrayElementAtIndex(list.index); OnSelected((BlendShapeClip)selected.objectReferenceValue); }; //m_clipList.onCanRemoveCallback += list => true; base.OnEnable(); OnSelected(m_selector.Selected); } int m_mode; static readonly string[] MODES = new string[]{ "Editor", "List" }; public override void OnInspectorGUI() { serializedObject.Update(); base.OnInspectorGUI(); m_mode = GUILayout.Toolbar(m_mode, MODES); switch (m_mode) { case 0: m_selector.SelectGUI(); if (m_clipEditor != null) { Separator(); var result = m_clipEditor.Draw(); if (result.Changed) { PreviewSceneManager.Bake(new PreviewSceneManager.BakeValue { BlendShapeBindings = result.BlendShapeBindings, MaterialValueBindings = result.MaterialValueBindings, Weight = 1.0f, }); } } break; case 1: m_clipList.DoLayoutList(); break; default: throw new NotImplementedException(); } serializedObject.ApplyModifiedProperties(); } } }