diff --git a/Assets/VRM10/Editor/Components/Expression/ExpressionEditorBase.cs b/Assets/VRM10/Editor/Components/Expression/ExpressionEditorBase.cs deleted file mode 100644 index 9bc93ce57..000000000 --- a/Assets/VRM10/Editor/Components/Expression/ExpressionEditorBase.cs +++ /dev/null @@ -1,272 +0,0 @@ -using System.IO; -using UnityEditor; -using UnityEngine; - -namespace UniVRM10 -{ - /// - /// Prefabをインスタンス化してPreviewに表示する - /// - /// * https://github.com/Unity-Technologies/UnityCsReference/blob/11bcfd801fccd2a52b09bb6fd636c1ddcc9f1705/Editor/Mono/Inspector/ModelInspector.cs - /// - /// - public abstract class ExpressionEditorBase : Editor - { - /// - /// PreviewRenderUtilityを管理する。 - /// - /// * PreviewRenderUtility.m_cameraのUnityVersionによる切り分け - /// - /// - PreviewFaceRenderer m_renderer; - - /// - /// Prefabをインスタンス化したシーンを管理する。 - /// - /// * ExpressionのBake - /// * MaterialMorphの適用 - /// * Previewカメラのコントロール - /// * Previewライティングのコントロール - /// - /// - PreviewSceneManager m_scene; - protected PreviewSceneManager PreviewSceneManager - { - get { return m_scene; } - } - - /// - /// Previewシーンに表示するPrefab - /// - GameObject m_prefab; - protected GameObject Prefab - { - get { return m_prefab; } - private set - { - if (m_prefab == value) return; - - //Debug.LogFormat("Prefab = {0}", value); - m_prefab = value; - - if (m_scene != null) - { - //Debug.LogFormat("OnDestroy"); - GameObject.DestroyImmediate(m_scene.gameObject); - m_scene = null; - } - - if (m_prefab != null) - { - m_scene = UniVRM10.PreviewSceneManager.GetOrCreate(m_prefab); - if (m_scene != null) - { - m_scene.gameObject.SetActive(false); - } - - Bake(); - } - } - } - - protected abstract VRM10Expression CurrentExpression(); - - /// - /// Preview シーンに Expression を適用する - /// - protected void Bake() - { - if (m_scene != null) - { - //Debug.Log("Bake"); - m_scene.Bake(CurrentExpression(), 1.0f); - } - } - - protected abstract GameObject GetPrefab(); - - protected virtual void OnEnable() - { - m_renderer = new PreviewFaceRenderer(); - - Prefab = GetPrefab(); - } - - protected virtual void OnDisable() - { - if (m_renderer != null) - { - m_renderer.Dispose(); - m_renderer = null; - } - ClearScene(); - } - - protected virtual void OnDestroy() - { - // 2018/2019 で OnDisable/OnDestroy の呼ばれ方が違う? - ClearScene(); - } - - void ClearScene() - { - if (m_scene != null) - { - //Debug.LogFormat("OnDestroy"); - m_scene.Clean(); - GameObject.DestroyImmediate(m_scene.gameObject); - m_scene = null; - } - } - - protected static void Separator() - { - EditorGUILayout.Space(); - EditorGUILayout.BeginHorizontal(); - //GUILayout.Space(); - GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1)); - EditorGUILayout.EndHorizontal(); - EditorGUILayout.Space(); - } - - public override void OnInspectorGUI() - { - //base.OnInspectorGUI(); - - Prefab = (GameObject)EditorGUILayout.ObjectField("Preview Prefab", Prefab, typeof(GameObject), false); - - //Separator(); - } - - private static int sliderHash = "Slider".GetHashCode(); - float m_yaw = 180.0f; - float m_pitch; - Vector3 m_position = new Vector3(0, 0, -0.8f); - - // very important to override this, it tells Unity to render an ObjectPreview at the bottom of the inspector - public override bool HasPreviewGUI() { return true; } - - public RenderTexture PreviewTexture; - - // the main ObjectPreview function... it's called constantly, like other IMGUI On*GUI() functions - public override void OnPreviewGUI(Rect r, GUIStyle background) - { - // if this is happening, you have bigger problems - if (!ShaderUtil.hardwareSupportsRectRenderTexture) - { - if (Event.current.type == EventType.Repaint) - { - EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 40f), - "Mesh preview requires\nrender texture support"); - } - return; - } - - var src = r; - - var min = Mathf.Min(r.width, r.height); - r.width = min; - r.height = min; - r.x = src.x + (src.width - min) / 2; - r.y = src.y + (src.height - min) / 2; - - //previewDir = Drag2D(previewDir, r); - { - int controlId = GUIUtility.GetControlID(sliderHash, FocusType.Passive); - Event e = Event.current; - switch (e.GetTypeForControl(controlId)) - { - case EventType.MouseDown: - if (r.Contains(e.mousePosition) && (double)r.width > 50.0) - { - GUIUtility.hotControl = controlId; - e.Use(); - EditorGUIUtility.SetWantsMouseJumping(1); - break; - } - break; - - case EventType.MouseUp: - if (GUIUtility.hotControl == controlId) - GUIUtility.hotControl = 0; - EditorGUIUtility.SetWantsMouseJumping(0); - break; - - case EventType.MouseDrag: - if (GUIUtility.hotControl == controlId) - { - if (e.button == 2) - { - var shift = e.delta * (!e.shift ? 1f : 3f) / Mathf.Min(r.width, r.height); - m_position.x -= shift.x; - m_position.y += shift.y; - e.Use(); - GUI.changed = true; - } - else if ( - e.button == 0 || - e.button == 1) - { - var shift = e.delta * (!e.shift ? 1f : 3f) / Mathf.Min(r.width, r.height) * 140f; - m_yaw += shift.x; - m_pitch += shift.y; - m_pitch = Mathf.Clamp(m_pitch, -90f, 90f); - e.Use(); - GUI.changed = true; - } - break; - } - break; - - case EventType.ScrollWheel: - //Debug.LogFormat("wheel: {0}", current.delta); - if (r.Contains(e.mousePosition)) - { - if (e.delta.y > 0) - { - m_position.z *= 1.1f; - Repaint(); - } - else if (e.delta.y < 0) - { - m_position.z *= 0.9f; - Repaint(); - } - } - break; - } - //return scrollPosition; - } - //Debug.LogFormat("{0}", previewDir); - - if (Event.current.type != EventType.Repaint) - { - // if we don't need to update yet, then don't - return; - } - - if (m_renderer != null && m_scene != null) - { - PreviewTexture = m_renderer.Render(r, background, m_scene, m_yaw, m_pitch, m_position) as RenderTexture; - if (PreviewTexture != null) - { - // draw the RenderTexture in the ObjectPreview pane - GUI.DrawTexture(r, PreviewTexture, ScaleMode.StretchToFill, false); - } - } - } - - public static VRM10Expression CreateExpression(string path) - { - //Debug.LogFormat("{0}", path); - var clip = ScriptableObject.CreateInstance(); - clip.ExpressionName = Path.GetFileNameWithoutExtension(path); - AssetDatabase.CreateAsset(clip, path); - AssetDatabase.ImportAsset(path); - return clip; - //Clips.Add(clip); - //EditorUtility.SetDirty(this); - //AssetDatabase.SaveAssets(); - } - } -} diff --git a/Assets/VRM10/Editor/Components/Expression/ExpressionEditorBase.cs.meta b/Assets/VRM10/Editor/Components/Expression/ExpressionEditorBase.cs.meta deleted file mode 100644 index 9e2ce3b38..000000000 --- a/Assets/VRM10/Editor/Components/Expression/ExpressionEditorBase.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6a64fbc26ee3c274fbfd9bce32f0b5dd -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/VRM10/Editor/Components/Expression/VRM10ExpressionEditor.cs b/Assets/VRM10/Editor/Components/Expression/VRM10ExpressionEditor.cs index 1e2fad39a..b5421ee8e 100644 --- a/Assets/VRM10/Editor/Components/Expression/VRM10ExpressionEditor.cs +++ b/Assets/VRM10/Editor/Components/Expression/VRM10ExpressionEditor.cs @@ -8,28 +8,265 @@ using UnityEngine; namespace UniVRM10 { [CustomEditor(typeof(VRM10Expression))] - public class ExpressionEditor : ExpressionEditorBase + public class ExpressionEditor : Editor { + /// + /// PreviewRenderUtilityを管理する。 + /// + /// * PreviewRenderUtility.m_cameraのUnityVersionによる切り分け + /// + /// + PreviewFaceRenderer m_renderer; + + /// + /// Prefabをインスタンス化したシーンを管理する。 + /// + /// * ExpressionのBake + /// * MaterialMorphの適用 + /// * Previewカメラのコントロール + /// * Previewライティングのコントロール + /// + /// + PreviewSceneManager m_scene; + PreviewSceneManager PreviewSceneManager + { + get { return m_scene; } + } + + /// + /// Previewシーンに表示するPrefab + /// + GameObject m_prefab; + GameObject Prefab + { + get { return m_prefab; } + set + { + if (m_prefab == value) return; + + //Debug.LogFormat("Prefab = {0}", value); + m_prefab = value; + + if (m_scene != null) + { + //Debug.LogFormat("OnDestroy"); + GameObject.DestroyImmediate(m_scene.gameObject); + m_scene = null; + } + + if (m_prefab != null) + { + m_scene = UniVRM10.PreviewSceneManager.GetOrCreate(m_prefab); + if (m_scene != null) + { + m_scene.gameObject.SetActive(false); + } + + Bake(); + } + } + } + + /// + /// Preview シーンに Expression を適用する + /// + void Bake() + { + if (m_scene != null) + { + //Debug.Log("Bake"); + m_scene.Bake(CurrentExpression(), 1.0f); + } + } + + void OnEnable() + { + m_target = (VRM10Expression)target; + m_renderer = new PreviewFaceRenderer(); + Prefab = GetPrefab(); + } + + void OnDisable() + { + if (m_renderer != null) + { + m_renderer.Dispose(); + m_renderer = null; + } + ClearScene(); + } + + void OnDestroy() + { + // 2018/2019 で OnDisable/OnDestroy の呼ばれ方が違う? + ClearScene(); + } + + void ClearScene() + { + if (m_scene != null) + { + //Debug.LogFormat("OnDestroy"); + m_scene.Clean(); + GameObject.DestroyImmediate(m_scene.gameObject); + m_scene = null; + } + } + + static void Separator() + { + EditorGUILayout.Space(); + EditorGUILayout.BeginHorizontal(); + //GUILayout.Space(); + GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.Height(1)); + EditorGUILayout.EndHorizontal(); + EditorGUILayout.Space(); + } + + private static int sliderHash = "Slider".GetHashCode(); + float m_yaw = 180.0f; + float m_pitch; + Vector3 m_position = new Vector3(0, 0, -0.8f); + + // very important to override this, it tells Unity to render an ObjectPreview at the bottom of the inspector + public override bool HasPreviewGUI() { return true; } + + public RenderTexture PreviewTexture; + + // the main ObjectPreview function... it's called constantly, like other IMGUI On*GUI() functions + public override void OnPreviewGUI(Rect r, GUIStyle background) + { + // if this is happening, you have bigger problems + if (!ShaderUtil.hardwareSupportsRectRenderTexture) + { + if (Event.current.type == EventType.Repaint) + { + EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 40f), + "Mesh preview requires\nrender texture support"); + } + return; + } + + var src = r; + + var min = Mathf.Min(r.width, r.height); + r.width = min; + r.height = min; + r.x = src.x + (src.width - min) / 2; + r.y = src.y + (src.height - min) / 2; + + //previewDir = Drag2D(previewDir, r); + { + int controlId = GUIUtility.GetControlID(sliderHash, FocusType.Passive); + Event e = Event.current; + switch (e.GetTypeForControl(controlId)) + { + case EventType.MouseDown: + if (r.Contains(e.mousePosition) && (double)r.width > 50.0) + { + GUIUtility.hotControl = controlId; + e.Use(); + EditorGUIUtility.SetWantsMouseJumping(1); + break; + } + break; + + case EventType.MouseUp: + if (GUIUtility.hotControl == controlId) + GUIUtility.hotControl = 0; + EditorGUIUtility.SetWantsMouseJumping(0); + break; + + case EventType.MouseDrag: + if (GUIUtility.hotControl == controlId) + { + if (e.button == 2) + { + var shift = e.delta * (!e.shift ? 1f : 3f) / Mathf.Min(r.width, r.height); + m_position.x -= shift.x; + m_position.y += shift.y; + e.Use(); + GUI.changed = true; + } + else if ( + e.button == 0 || + e.button == 1) + { + var shift = e.delta * (!e.shift ? 1f : 3f) / Mathf.Min(r.width, r.height) * 140f; + m_yaw += shift.x; + m_pitch += shift.y; + m_pitch = Mathf.Clamp(m_pitch, -90f, 90f); + e.Use(); + GUI.changed = true; + } + break; + } + break; + + case EventType.ScrollWheel: + //Debug.LogFormat("wheel: {0}", current.delta); + if (r.Contains(e.mousePosition)) + { + if (e.delta.y > 0) + { + m_position.z *= 1.1f; + Repaint(); + } + else if (e.delta.y < 0) + { + m_position.z *= 0.9f; + Repaint(); + } + } + break; + } + //return scrollPosition; + } + //Debug.LogFormat("{0}", previewDir); + + if (Event.current.type != EventType.Repaint) + { + // if we don't need to update yet, then don't + return; + } + + if (m_renderer != null && m_scene != null) + { + PreviewTexture = m_renderer.Render(r, background, m_scene, m_yaw, m_pitch, m_position) as RenderTexture; + if (PreviewTexture != null) + { + // draw the RenderTexture in the ObjectPreview pane + GUI.DrawTexture(r, PreviewTexture, ScaleMode.StretchToFill, false); + } + } + } + + public static VRM10Expression CreateExpression(string path) + { + //Debug.LogFormat("{0}", path); + var clip = ScriptableObject.CreateInstance(); + clip.ExpressionName = Path.GetFileNameWithoutExtension(path); + AssetDatabase.CreateAsset(clip, path); + AssetDatabase.ImportAsset(path); + return clip; + //Clips.Add(clip); + //EditorUtility.SetDirty(this); + //AssetDatabase.SaveAssets(); + } + SerializedExpressionEditor m_serializedEditor; VRM10Expression m_target; - protected override VRM10Expression CurrentExpression() + VRM10Expression CurrentExpression() { return m_target; } - protected override GameObject GetPrefab() + GameObject GetPrefab() { return m_target.Prefab; } - protected override void OnEnable() - { - m_target = (VRM10Expression)target; - - base.OnEnable(); - } - float m_previewSlider = 1.0f; static Texture2D SaveResizedImage(RenderTexture rt, UnityPath path, int size) @@ -88,7 +325,8 @@ namespace UniVRM10 var changed = false; EditorGUILayout.BeginVertical(); - base.OnInspectorGUI(); + + Prefab = (GameObject)EditorGUILayout.ObjectField("Preview Prefab", Prefab, typeof(GameObject), false); EditorGUILayout.LabelField("Preview Weight"); var previewSlider = EditorGUILayout.Slider(m_previewSlider, 0, 1.0f); @@ -118,6 +356,8 @@ namespace UniVRM10 { PreviewSceneManager.Bake(bakeValue, m_previewSlider); } + + serializedObject.ApplyModifiedProperties(); } } }