diff --git a/Assets/VRM/Editor/SpringBone/VRMSpringBoneColliderGroupEditor.cs b/Assets/VRM/Editor/SpringBone/VRMSpringBoneColliderGroupEditor.cs index 9c2576196..fee110aa3 100644 --- a/Assets/VRM/Editor/SpringBone/VRMSpringBoneColliderGroupEditor.cs +++ b/Assets/VRM/Editor/SpringBone/VRMSpringBoneColliderGroupEditor.cs @@ -16,30 +16,6 @@ namespace VRM m_target = (VRMSpringBoneColliderGroup)target; } - private void OnSceneGUI() - { - Undo.RecordObject(m_target, "VRMSpringBoneColliderGroupEditor"); - - Handles.matrix = m_target.transform.localToWorldMatrix; - Gizmos.color = Color.green; - - bool changed = false; - - foreach (var x in m_target.Colliders) - { - var offset = Handles.PositionHandle(x.Offset, Quaternion.identity); - if (offset != x.Offset) - { - changed = true; - x.Offset = offset; - } - } - - if (changed) - { - EditorUtility.SetDirty(m_target); - } - } override public void OnInspectorGUI() { diff --git a/Assets/VRM10/Editor/Components/SpringBone/SpringBoneEditor.cs b/Assets/VRM10/Editor/Components/SpringBone/SpringBoneEditor.cs deleted file mode 100644 index 36faf4958..000000000 --- a/Assets/VRM10/Editor/Components/SpringBone/SpringBoneEditor.cs +++ /dev/null @@ -1,54 +0,0 @@ -using UnityEditor; -using UnityEditor.IMGUI.Controls; -using UnityEngine; - -namespace UniVRM10 -{ - /// - /// TreeView でアクティブな SpringBone, ColliderGroup を管理して、 - /// アクティブな SpringBone と ColliderGroup を SceneHandle で Edit する。 - /// - public static class SpringBoneEditor - { - static SpringBoneTreeView s_treeView; - static SpringBoneTreeView GetTree(Vrm10Instance target, SerializedObject so) - { - if (s_treeView == null || s_treeView.Target != target) - { - var state = new TreeViewState(); - s_treeView = new SpringBoneTreeView(state, target, so); - s_treeView.Reload(); - } - return s_treeView; - } - - public static void Disable() - { - s_treeView = null; - } - - /// - /// 2D の GUI 描画 - /// - public static void Draw2D(Vrm10Instance target, SerializedObject so) - { - var tree = GetTree(target, so); - if (GUILayout.Button("Reload")) - { - Disable(); - return; - } - - tree.Draw2D(); - } - - /// - /// 3D の Handle 描画 - /// - public static void Draw3D(Vrm10Instance target, SerializedObject so) - { - var tree = GetTree(target, so); - tree.Draw3D(); - } - } -} diff --git a/Assets/VRM10/Editor/Components/SpringBone/SpringBoneEditor.cs.meta b/Assets/VRM10/Editor/Components/SpringBone/SpringBoneEditor.cs.meta deleted file mode 100644 index 3e25de41b..000000000 --- a/Assets/VRM10/Editor/Components/SpringBone/SpringBoneEditor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 33ca35799b1168949bb4466aae13dfd4 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/VRM10/Editor/Components/SpringBone/SpringBoneTreeView.cs b/Assets/VRM10/Editor/Components/SpringBone/SpringBoneTreeView.cs index a9788ed8c..03ec1f6d6 100644 --- a/Assets/VRM10/Editor/Components/SpringBone/SpringBoneTreeView.cs +++ b/Assets/VRM10/Editor/Components/SpringBone/SpringBoneTreeView.cs @@ -1,8 +1,6 @@ using System.Collections.Generic; -using System.Linq; using UnityEditor; using UnityEditor.IMGUI.Controls; -using UnityEditorInternal; using UnityEngine; namespace UniVRM10 @@ -37,24 +35,33 @@ namespace UniVRM10 // load _map = new Dictionary(); - for (var i = 0; i < target.SpringBone.ColliderGroups.Count; ++i) + if (target != null) { - var colliderGroup = target.SpringBone.ColliderGroups[i]; - var name = colliderGroup.GUIName(i); - var id = _nextNodeID++; - var item = new TreeViewItem(id, 2, name); - _map.Add(id, colliderGroup); - _colliderGroups.AddChild(item); - } + if (target.SpringBone?.ColliderGroups != null) + { + for (var i = 0; i < target.SpringBone.ColliderGroups.Count; ++i) + { + var colliderGroup = target.SpringBone.ColliderGroups[i]; + var name = colliderGroup.GUIName(i); + var id = _nextNodeID++; + var item = new TreeViewItem(id, 2, name); + _map.Add(id, colliderGroup); + _colliderGroups.AddChild(item); + } + } - for (var i = 0; i < target.SpringBone.Springs.Count; ++i) - { - var spring = target.SpringBone.Springs[i]; - var name = spring.GUIName(i); - var id = _nextNodeID++; - var item = new TreeViewItem(id, 2, name); - _map.Add(id, spring); - _springs.AddChild(item); + if (target.SpringBone?.Springs != null) + { + for (var i = 0; i < target.SpringBone.Springs.Count; ++i) + { + var spring = target.SpringBone.Springs[i]; + var name = spring.GUIName(i); + var id = _nextNodeID++; + var item = new TreeViewItem(id, 2, name); + _map.Add(id, spring); + _springs.AddChild(item); + } + } } } @@ -107,16 +114,191 @@ namespace UniVRM10 } } - public void Draw3D() + Color s_selectedColor = new Color(0.5f, 0, 0, 0.5f); + Color s_hoverColor = new Color(0.5f, 0.5f, 0, 0.5f); + Color s_Color = new Color(0.6f, 0.6f, 0.6f, 0.5f); + + Color GetColor(MonoBehaviour target) { + if (target == Active) + { + return s_selectedColor; + } + if (target == Hover) + { + return s_hoverColor; + } + return s_Color; + } + + Vrm10InstanceSpringBone last = null; + MonoBehaviour Hover = null; + public MonoBehaviour Active = null; + + public bool Draw3D(Vrm10InstanceSpringBone springBone) + { + var lastActive = Active; + var lastHover = Hover; + + if (springBone != last) + { + Active = null; + Hover = null; + last = springBone; + } + if (_selected is SelectedColliderGroupGUI colliderGroup) { - colliderGroup.Draw3D(); + // colliderGroup.Draw3D(); } else if (_selected is SelectedSpringGUI spring) { // TODO } + + MonoBehaviour newActive = null; + + // + // collider + // + foreach (var group in springBone.ColliderGroups) + { + foreach (var collider in group.Colliders) + { + var color = GetColor(collider); + var (isActive, isHover) = DrawCollider(collider, color); + if (isActive) + { + newActive = collider; + } + if (isHover) + { + Hover = collider; + } + } + } + + // + // joint + // + foreach (var spring in springBone.Springs) + { + VRM10SpringBoneJoint head = null; + for (int i = 0; i < spring.Joints.Count; ++i) + { + var joint = spring.Joints[i]; + var color = GetColor(joint); + var (isActive, isHover) = DrawJoint(joint, color, head); + if (isActive) + { + newActive = joint; + } + if (isHover) + { + Hover = joint; + } + head = joint; + } + } + + if (Active is VRM10SpringBoneCollider activeCollider) + { + // Active な collider の移動ハンドル(Offset, Tail) + EditorGUI.BeginChangeCheck(); + Handles.matrix = activeCollider.transform.localToWorldMatrix; + var offset = Handles.PositionHandle(activeCollider.Offset, Quaternion.identity); + var tail = Vector3.zero; + if (activeCollider.ColliderType == VRM10SpringBoneColliderTypes.Capsule) + { + tail = Handles.PositionHandle(activeCollider.Tail, Quaternion.identity); + } + var offsetChanged = EditorGUI.EndChangeCheck(); + if (offsetChanged) + { + // apply + Undo.RecordObject(activeCollider, "activeCollider"); + activeCollider.Offset = offset; + if (activeCollider.ColliderType == VRM10SpringBoneColliderTypes.Capsule) + { + activeCollider.Tail = tail; + } + } + Handles.matrix = Matrix4x4.identity; + } + + if (newActive != null) + { + Selection.activeObject = newActive.gameObject; + Active = newActive; + } + if (Hover != null) + { + Handles.Label(Hover.transform.position, Hover.name); + } + + return lastActive != Active || lastHover != Hover; + } + + static bool IsLeftDown() + { + return Event.current.type == EventType.MouseDown && Event.current.button == 0; + } + + (bool IsActive, bool IsHover) DrawCollider(VRM10SpringBoneCollider collider, Color color) + { + if (Event.current.type == EventType.Repaint || Event.current.type == EventType.Layout) + { + Handles.matrix = collider.transform.localToWorldMatrix; + Handles.color = color; + switch (collider.ColliderType) + { + case VRM10SpringBoneColliderTypes.Sphere: + // Handles.color = Color.magenta; + Handles.SphereHandleCap(collider.GetInstanceID(), collider.Offset, Quaternion.identity, collider.Radius * 2, Event.current.type); + break; + + case VRM10SpringBoneColliderTypes.Capsule: + // Handles.color = Color.cyan; + Handles.SphereHandleCap(collider.GetInstanceID(), collider.Offset, Quaternion.identity, collider.Radius * 2, Event.current.type); + Handles.SphereHandleCap(collider.GetInstanceID(), collider.Tail, Quaternion.identity, collider.Radius * 2, Event.current.type); + Handles.DrawLine(collider.Offset, collider.Tail); + break; + } + Handles.matrix = Matrix4x4.identity; + } + + var isHover = HandleUtility.nearestControl == collider.GetInstanceID(); + return (IsLeftDown() && isHover, isHover); + } + + (bool IsActive, bool IsHover) DrawJoint(VRM10SpringBoneJoint joint, Color color, VRM10SpringBoneJoint head) + { + if (Event.current.type == EventType.Repaint || Event.current.type == EventType.Layout) + { + + if (head == null) + { + // 先頭 + Handles.color = color; + Handles.CubeHandleCap(joint.GetInstanceID(), joint.transform.position, joint.transform.rotation, + // head の radius + joint.m_jointRadius, Event.current.type); + } + else + { + // line + Handles.color = Color.green; + Handles.DrawLine(joint.transform.position, head.transform.position); + // joint + Handles.color = color; + Handles.SphereHandleCap(joint.GetInstanceID(), joint.transform.position, joint.transform.rotation, + // head の radius + head.m_jointRadius * 2, Event.current.type); + } + } + + var isHover = HandleUtility.nearestControl == joint.GetInstanceID(); + return (IsLeftDown() && isHover, isHover); } } } diff --git a/Assets/VRM10/Editor/Components/SpringBone/VRM10SpringBoneColliderEditor.cs b/Assets/VRM10/Editor/Components/SpringBone/VRM10SpringBoneColliderEditor.cs index b8e064bc0..adb525d6a 100644 --- a/Assets/VRM10/Editor/Components/SpringBone/VRM10SpringBoneColliderEditor.cs +++ b/Assets/VRM10/Editor/Components/SpringBone/VRM10SpringBoneColliderEditor.cs @@ -6,17 +6,12 @@ namespace UniVRM10 [CustomEditor(typeof(VRM10SpringBoneCollider))] class VRM10SpringBoneColliderEditor : Editor { - VRM10SpringBoneCollider _target; - void OnEnable() - { - _target = target as VRM10SpringBoneCollider; - } - public override void OnInspectorGUI() { - if (_target.GetInstanceID() == VRM10SpringBoneCollider.SelectedGuid) + if (VRM10Window.Active == target) { - GUI.backgroundColor = Color.red; + GUI.backgroundColor = Color.cyan; + Repaint(); } base.OnInspectorGUI(); } diff --git a/Assets/VRM10/Editor/Components/VRM10Window.cs b/Assets/VRM10/Editor/Components/VRM10Window.cs index 476a50ce6..fb1eea07d 100644 --- a/Assets/VRM10/Editor/Components/VRM10Window.cs +++ b/Assets/VRM10/Editor/Components/VRM10Window.cs @@ -10,13 +10,15 @@ namespace UniVRM10 /// public class VRM10Window : EditorWindow { - const string WINDOW_TITLE = "VRM1 Window"; - public static void Open() + public const string WINDOW_TITLE = "VRM1.0 Model Editor"; + + public static VRM10Window Open() { var window = (VRM10Window)GetWindow(typeof(VRM10Window)); window.titleContent = new GUIContent(WINDOW_TITLE); window.Show(); window.Root = UnityEditor.Selection.activeTransform?.GetComponent(); + return window; } void OnEnable() @@ -30,7 +32,7 @@ namespace UniVRM10 void OnDisable() { - SpringBoneEditor.Disable(); + s_treeView = null; SceneView.duringSceneGui -= OnSceneGUI; // Debug.Log("OnDisable"); @@ -59,64 +61,28 @@ namespace UniVRM10 } m_root = id; m_so = value != null ? new SerializedObject(value) : null; - m_constraints = null; - - if (Root != null) - { - var animator = Root.GetComponent(); - m_head = animator.GetBoneTransform(HumanBodyBones.Head); - } - } - } - - Transform m_head; - - public IVrm10Constraint[] m_constraints; - - ScrollView m_scrollView = new ScrollView(); - - enum VRMSceneUI - { - Constraints, - SpringBone, - } - static VRMSceneUI s_ui = default; - static string[] s_selection; - static string[] Selection - { - get - { - if (s_selection == null) - { - s_selection = Enum.GetNames(typeof(VRMSceneUI)); - } - return s_selection; } } /// - /// public entry point + /// Scene 上の 3D 表示 + /// + /// * Joint/Collider の Picker + /// /// - /// void OnSceneGUI(SceneView sceneView) { - switch (s_ui) - { - case VRMSceneUI.Constraints: - Tools.hidden = false; - break; - - case VRMSceneUI.SpringBone: - Tools.hidden = true; - SpringBoneEditor.Draw3D(Root, m_so); - break; - - default: - throw new NotImplementedException(); - } + Tools.hidden = true; + Draw3D(Root, m_so); } - // + /// + /// Window 上の GUI + /// + /// * 対象 VRM の保持 + /// * 選択 Joint/Collider の表示 + /// + /// private void OnGUI() { if (Root == null) @@ -131,65 +97,58 @@ namespace UniVRM10 } } - Root = (Vrm10Instance)EditorGUILayout.ObjectField("vrm1", Root, typeof(Vrm10Instance), true); + // Root + Root = (Vrm10Instance)EditorGUILayout.ObjectField("Editing Model", Root, typeof(Vrm10Instance), true); if (Root == null) { return; } - var ui = (VRMSceneUI)GUILayout.SelectionGrid((int)s_ui, Selection, 3); - if (s_ui != ui) - { - s_ui = ui; - SceneView.RepaintAll(); - } + // active + EditorGUI.BeginDisabledGroup(true); + EditorGUILayout.ObjectField("Selected Object", Active, typeof(MonoBehaviour), true); + EditorGUI.EndDisabledGroup(); - if (m_so == null) - { - m_so = new SerializedObject(Root); - } - if (m_so == null) - { - return; - } - - m_so.Update(); - switch (s_ui) - { - case VRMSceneUI.Constraints: - m_scrollView.Draw(this.position.y, DrawConstraints, Repaint); - break; - - case VRMSceneUI.SpringBone: - SpringBoneEditor.Draw2D(Root, m_so); - break; - - default: - throw new NotImplementedException(); - } - - m_so.ApplyModifiedProperties(); + // if (m_so == null) + // { + // m_so = new SerializedObject(Root); + // } + // if (m_so == null) + // { + // return; + // } + // m_so.Update(); + // SpringBoneEditor.Draw2D(Root, m_so); + // m_so.ApplyModifiedProperties(); } - void DrawConstraints() + SpringBoneTreeView s_treeView; + SpringBoneTreeView GetTree(Vrm10Instance target, SerializedObject so) { - if (Root != null) + if (s_treeView == null || s_treeView.Target != target) { - if (m_constraints == null) - { - m_constraints = Root.GetComponentsInChildren(); - } + var state = new UnityEditor.IMGUI.Controls.TreeViewState(); + s_treeView = new SpringBoneTreeView(state, target, so); + s_treeView.Reload(); } + return s_treeView; + } - using (new EditorGUI.DisabledScope(true)) + public static MonoBehaviour Active; + + /// + /// 3D の Handle 描画 + /// + public void Draw3D(Vrm10Instance target, SerializedObject so) + { + var tree = GetTree(target, so); + if (tree != null && target != null) { - if (m_constraints != null) + if (tree.Draw3D(target.SpringBone)) { - foreach (var c in m_constraints) - { - EditorGUILayout.ObjectField(c.ConstraintTarget, typeof(MonoBehaviour), true); - } + Repaint(); } + Active = tree.Active; } } } diff --git a/Assets/VRM10/Editor/EditorTool/VRM10SpringBoneColliderEditorTool.cs b/Assets/VRM10/Editor/EditorTool/VRM10SpringBoneColliderEditorTool.cs deleted file mode 100644 index 036fb4098..000000000 --- a/Assets/VRM10/Editor/EditorTool/VRM10SpringBoneColliderEditorTool.cs +++ /dev/null @@ -1,86 +0,0 @@ -using UnityEditor; -using UnityEditor.EditorTools; -using UnityEngine; - -namespace UniVRM10 -{ - [EditorTool("vrm-1.0/SpringBoneCollider", typeof(UniVRM10.VRM10SpringBoneCollider))] - class VRM10SpringBoneColliderEditorTool : EditorTool - { - static GUIContent s_cachedIcon; - public override GUIContent toolbarIcon - { - get - { - if (s_cachedIcon == null) - { - s_cachedIcon = EditorGUIUtility.IconContent("d_editcollision_32", "|vrm-1.0 SpringBoneCollider"); - } - return s_cachedIcon; - } - } - - void OnEnable() - { - ToolManager.activeToolChanged += ActiveToolDidChange; - } - - void OnDisable() - { - ToolManager.activeToolChanged -= ActiveToolDidChange; - } - - void ActiveToolDidChange() - { - if (!ToolManager.IsActiveTool(this)) - { - return; - } - } - - public override void OnToolGUI(EditorWindow window) - { - if (Selection.activeTransform == null) - { - return; - } - var collider = Selection.activeTransform.GetComponent(); - if (collider == null) - { - return; - } - - Handles.matrix = collider.transform.localToWorldMatrix; - { - Handles.Label(collider.Offset, "Head"); - EditorGUI.BeginChangeCheck(); - var offset = Handles.PositionHandle(collider.Offset, Quaternion.identity); - var offsetChanged = EditorGUI.EndChangeCheck(); - if (offsetChanged) - { - Undo.RecordObject(collider, "SpringBoneCollider"); - - var delta = offset - collider.Offset; - collider.Offset = offset; - if (collider.ColliderType == VRM10SpringBoneColliderTypes.Capsule) - { - collider.Tail += delta; - } - } - - if (collider.ColliderType == VRM10SpringBoneColliderTypes.Capsule) - { - Handles.Label(collider.Tail, "Tail"); - EditorGUI.BeginChangeCheck(); - var tail = Handles.PositionHandle(collider.Tail, Quaternion.identity); - var tailChanged = EditorGUI.EndChangeCheck(); - if (tailChanged) - { - Undo.RecordObject(collider, "SpringBoneCollider"); - collider.Tail = tail; - } - } - } - } - } -} \ No newline at end of file diff --git a/Assets/VRM10/Editor/EditorTool/VRM10SpringBoneColliderEditorTool.cs.meta b/Assets/VRM10/Editor/EditorTool/VRM10SpringBoneColliderEditorTool.cs.meta deleted file mode 100644 index 77b9d0140..000000000 --- a/Assets/VRM10/Editor/EditorTool/VRM10SpringBoneColliderEditorTool.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: eb79df70485ab8548bdd417c7fcbe04a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/VRM10/Editor/Vrm10InstanceEditor.cs b/Assets/VRM10/Editor/Vrm10InstanceEditor.cs index 8a57829f4..376d37145 100644 --- a/Assets/VRM10/Editor/Vrm10InstanceEditor.cs +++ b/Assets/VRM10/Editor/Vrm10InstanceEditor.cs @@ -115,14 +115,8 @@ namespace UniVRM10 return loaded; } - void Setup(Vrm10Instance instance) + void SetupVRM10Object(Vrm10Instance instance) { - if (instance.Vrm != null) - { - // OK - return; - } - if (!CheckHumanoid(instance.gameObject)) { // can not @@ -162,9 +156,22 @@ namespace UniVRM10 public override void OnInspectorGUI() { + if (target is Vrm10Instance instance) { - Setup(instance); + if (instance.Vrm == null) + { + SetupVRM10Object(instance); + } + + if (instance.Vrm != null) + { + EditorGUILayout.HelpBox("SpringBone gizmo etc...", MessageType.Info); + if (GUILayout.Button("Open " + VRM10Window.WINDOW_TITLE)) + { + VRM10Window.Open(); + } + } } base.OnInspectorGUI(); diff --git a/Assets/VRM10/Runtime/Components/SpringBone/VRM10SpringBoneCollider.cs b/Assets/VRM10/Runtime/Components/SpringBone/VRM10SpringBoneCollider.cs index 578784f76..e0d257405 100644 --- a/Assets/VRM10/Runtime/Components/SpringBone/VRM10SpringBoneCollider.cs +++ b/Assets/VRM10/Runtime/Components/SpringBone/VRM10SpringBoneCollider.cs @@ -38,7 +38,7 @@ namespace UniVRM10 break; case VRM10SpringBoneColliderTypes.Capsule: - Gizmos.color = Color.cyan; + Gizmos.color = new Color(1.0f, 0.1f, 0.1f); Gizmos.DrawWireSphere(Offset, Radius); Gizmos.DrawWireSphere(Tail, Radius); Gizmos.DrawLine(Offset, Tail); diff --git a/Assets/VRM10/Runtime/Components/SpringBone/VRM10SpringBoneJoint.cs b/Assets/VRM10/Runtime/Components/SpringBone/VRM10SpringBoneJoint.cs index 5a990c9ae..289087dda 100644 --- a/Assets/VRM10/Runtime/Components/SpringBone/VRM10SpringBoneJoint.cs +++ b/Assets/VRM10/Runtime/Components/SpringBone/VRM10SpringBoneJoint.cs @@ -26,9 +26,6 @@ namespace UniVRM10 [SerializeField, Range(0, 0.5f), Header("Collision")] public float m_jointRadius = 0.02f; - [SerializeField] - public Color m_gizmoColor = Color.green; - void AddJointRecursive(Transform t, VRM10SpringBoneJoint src) { var joint = t.gameObject.GetComponent(); @@ -139,38 +136,24 @@ namespace UniVRM10 return; } - Gizmos.color = m_gizmoColor; - - // draw head - // Gizmos.DrawSphere(transform.position, m_jointRadius); - var (spring, joint_index) = FindTail(vrm, this); if (spring == null) { return; } - + if (spring.Joints != null && joint_index + 1 < spring.Joints.Count) { var tail = spring.Joints[joint_index + 1]; if (tail != null) { // draw tail - Gizmos.DrawSphere(tail.transform.position, tail.m_jointRadius); + Gizmos.color = Color.yellow; + // tail の radius は head の m_jointRadius で決まる + Gizmos.DrawWireSphere(tail.transform.position, m_jointRadius); Gizmos.DrawLine(transform.position, tail.transform.position); } } - - foreach (var colliderGroup in spring.ColliderGroups) - { - foreach (var collider in colliderGroup.Colliders) - { - if (collider != null) - { - collider.OnDrawGizmosSelected(); - } - } - } } } }