using UnityEditorInternal;
using UnityEngine;
using UnityEngine.U2D.IK;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor.U2D.Animation;
namespace UnityEditor.U2D.IK
{
///
/// Custom Inspector for IKManager2D.
///
[CustomEditor(typeof(IKManager2D))]
[CanEditMultipleObjects]
class IKManager2DEditor : Editor
{
class Contents
{
public static readonly GUIContent findAllSolversLabel = new GUIContent("Find Solvers", "Find all applicable solvers handled by this manager");
public static readonly GUIContent weightLabel = new GUIContent("Weight", "Blend between Forward and Inverse Kinematics");
public static readonly string listHeaderLabel = "IK Solvers";
public static readonly string createSolverString = "Create Solver";
public static readonly string restoreDefaultPoseString = "Restore Default Pose";
public static readonly GUIContent gizmoColorTooltip = new GUIContent("","Customizes the IK Chain's Gizmo color");
public static int showGizmoPropertyWidth = 20;
public static int solverPropertyWidth = 100;
public static int solverColorPropertyWidth = 40;
public static readonly GUIContent gizmoVisibilityToolTip = new GUIContent("",L10n.Tr("Show/Hide Gizmo"));
public readonly GUIStyle visibilityToggleStyle;
public Contents()
{
visibilityToggleStyle = new GUIStyle();
visibilityToggleStyle.fixedWidth = EditorGUIUtility.singleLineHeight;
visibilityToggleStyle.onNormal.background = EditorIconUtility.LoadIconResource("Visibility_Tool", EditorIconUtility.LightIconPath, EditorIconUtility.DarkIconPath);
visibilityToggleStyle.normal.background = EditorIconUtility.LoadIconResource("Visibility_Hidded", EditorIconUtility.LightIconPath, EditorIconUtility.DarkIconPath);
}
}
static Contents s_Contents;
ReorderableList m_ReorderableList;
Solver2D m_SelectedSolver;
Editor m_SelectedSolverEditor;
SerializedProperty m_SolversProperty;
SerializedProperty m_SolverEditorDataProperty;
SerializedProperty m_WeightProperty;
List m_SolverTypes;
IKManager2D m_Manager;
void OnEnable()
{
m_Manager = target as IKManager2D;
m_SolverTypes = GetDerivedTypes();
m_SolversProperty = serializedObject.FindProperty("m_Solvers");
m_SolverEditorDataProperty = serializedObject.FindProperty("m_SolverEditorData");
m_WeightProperty = serializedObject.FindProperty("m_Weight");
SetupReorderableList();
}
void SetupReorderableList()
{
m_ReorderableList = new ReorderableList(serializedObject, m_SolversProperty, true, true, true, true);
m_ReorderableList.drawHeaderCallback = (Rect rect) =>
{
GUI.Label(rect, Contents.listHeaderLabel);
};
m_ReorderableList.elementHeightCallback = (int index) =>
{
return EditorGUIUtility.singleLineHeight + 6;
};
m_ReorderableList.drawElementCallback = (Rect rect, int index, bool isactive, bool isfocused) =>
{
rect.y += 2f;
rect.height = EditorGUIUtility.singleLineHeight;
SerializedProperty element = m_SolversProperty.GetArrayElementAtIndex(index);
SerializedProperty elementData = m_SolverEditorDataProperty.GetArrayElementAtIndex(index);
var width = rect.width;
rect.width = width > Contents.showGizmoPropertyWidth ? Contents.showGizmoPropertyWidth : width;
var showGizmoProperty = elementData.FindPropertyRelative("showGizmo");
showGizmoProperty.boolValue = GUI.Toggle(rect, showGizmoProperty.boolValue, Contents.gizmoVisibilityToolTip, s_Contents.visibilityToggleStyle);
rect.x += rect.width;
width -= rect.width;
rect.width = width > Contents.solverPropertyWidth ? width - Contents.solverColorPropertyWidth : Contents.solverPropertyWidth;
EditorGUI.PropertyField(rect, element, GUIContent.none);
rect.x += rect.width;
width -= 100;
rect.width = width > Contents.solverColorPropertyWidth ? Contents.solverColorPropertyWidth : width;
EditorGUI.PropertyField(rect, elementData.FindPropertyRelative("color"), Contents.gizmoColorTooltip);
};
m_ReorderableList.onAddCallback = (ReorderableList list) =>
{
var menu = new GenericMenu();
foreach (Type type in m_SolverTypes)
{
Solver2DMenuAttribute attribute = Attribute.GetCustomAttribute(type, typeof(Solver2DMenuAttribute)) as Solver2DMenuAttribute;
if (attribute != null)
menu.AddItem(new GUIContent(attribute.menuPath), false, OnSelectMenu, type);
else
menu.AddItem(new GUIContent(type.Name), false, OnSelectMenu, type);
}
menu.ShowAsContext();
};
m_ReorderableList.onRemoveCallback = (ReorderableList list) =>
{
Solver2D solver = m_Manager.solvers[list.index];
if (solver)
{
Undo.RegisterCompleteObjectUndo(m_Manager, Undo.GetCurrentGroupName());
m_Manager.RemoveSolver(solver);
GameObject solverGO = solver.gameObject;
if (solverGO.transform.childCount == 0)
Undo.DestroyObjectImmediate(solverGO);
else
Undo.DestroyObjectImmediate(solver);
EditorUtility.SetDirty(m_Manager);
}
else
{
ReorderableList.defaultBehaviours.DoRemoveButton(list);
}
};
}
void OnSelectMenu(object param)
{
var solverType = param as Type;
var solverGO = new GameObject(GameObjectUtility.GetUniqueNameForSibling(m_Manager.transform, "New " + solverType.Name));
solverGO.transform.SetParent(m_Manager.transform);
solverGO.transform.localPosition = Vector3.zero;
solverGO.transform.rotation = Quaternion.identity;
solverGO.transform.localScale = Vector3.one;
var solver = solverGO.AddComponent(solverType) as Solver2D;
Undo.RegisterCreatedObjectUndo(solverGO, Contents.createSolverString);
Undo.RegisterCompleteObjectUndo(m_Manager, Contents.createSolverString);
m_Manager.AddSolver(solver);
EditorUtility.SetDirty(m_Manager);
Selection.activeGameObject = solverGO;
}
///
/// Custom Inspector OnInspectorGUI override.
///
public override void OnInspectorGUI()
{
if (s_Contents == null)
s_Contents = new Contents();
serializedObject.Update();
EditorGUILayout.Space();
m_ReorderableList.DoLayoutList();
EditorGUILayout.Space();
EditorGUILayout.PropertyField(m_WeightProperty, Contents.weightLabel);
EditorGUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
DoRestoreDefaultPoseButton();
GUILayout.FlexibleSpace();
EditorGUILayout.EndHorizontal();
serializedObject.ApplyModifiedProperties();
}
void DoRestoreDefaultPoseButton()
{
if (GUILayout.Button(Contents.restoreDefaultPoseString, GUILayout.MaxWidth(150f)))
{
foreach (var l_target in targets)
{
var manager = l_target as IKManager2D;
IKEditorManager.instance.Record(manager, Contents.restoreDefaultPoseString);
foreach(var solver in manager.solvers)
{
for(int i = 0; i < solver.chainCount; ++i)
{
var chain = solver.GetChain(i);
chain.RestoreDefaultPose(solver.constrainRotation);
if(chain.target)
{
chain.target.position = chain.effector.position;
chain.target.rotation = chain.effector.rotation;
}
}
}
IKEditorManager.instance.UpdateManagerImmediate(manager, true);
}
}
}
static List GetDerivedTypes() where T : class
{
var typeCollection = TypeCache.GetTypesDerivedFrom();
return typeCollection.ToList();
}
}
}