Firstborn/Assets/Kevin Iglesias/IKHelperTool/Scripts/IKHelperToolCustomInspector.cs

380 lines
13 KiB
C#
Raw Normal View History

///////////////////////////////////////////////////////////////////////////
// IK Helper Tool 1.1 - Custom Inspector //
// Kevin Iglesias - https://www.keviniglesias.com/ //
// Contact Support: support@keviniglesias.com //
// Documentation: //
// https://www.keviniglesias.com/assets/IKHelperTool/Documentation.pdf //
///////////////////////////////////////////////////////////////////////////
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
namespace KevinIglesias {
[CustomEditor(typeof(IKHelperTool))]
public class IKHelperToolCustomInspector : Editor
{
public override void OnInspectorGUI()
{
var iKScript = target as IKHelperTool;
if(iKScript.stateIKs == null)
{
iKScript.stateIKs = new List<StateIK>();
}
List <StateIK> iStateIKs = new List<StateIK>(iKScript.stateIKs);
GUILayout.Space(5);
GUIContent buttonContent = null;
//Edit Mode Button
GUILayout.BeginHorizontal();
GUILayout.Space(30);
GUI.enabled = EditorApplication.isPlaying;
if(iKScript.editingIK)
{
buttonContent = new GUIContent("[Editing Mode ON]\nAnimation stopped.", "Click to return to normal speed.");
if(GUILayout.Button(buttonContent))
{
iKScript.animator.speed = iKScript.animatorSpeed;
iKScript.editingIK = false;
}
}else{
buttonContent = new GUIContent("[Editing Mode OFF]\n(Only in Play mode)", "Easily edit your attachment (Play mode only).");
if(GUILayout.Button(buttonContent))
{
iKScript.animatorSpeed = iKScript.animator.speed;
iKScript.animator.speed = 0f;
iKScript.editingIK = true;
}
}
GUILayout.EndHorizontal();
GUI.enabled = true;
//Separator line
GUILayout.BeginHorizontal();
GUILayout.Space(30);
IKHelperUtils.DrawUILine(Color.black, 1, 5);
GUILayout.EndHorizontal();
//IK States
for(int i = 0; i < iKScript.stateIKs.Count; i++)
{
//[X] Remove IK Button
GUILayout.BeginHorizontal();
GUILayout.Space(30);
buttonContent = new GUIContent("[X]", "Remove this IK State");
if(GUILayout.Button(buttonContent, GUILayout.Width(30)))
{
EditorGUI.BeginChangeCheck();
GUI.changed = true;
if(EditorGUI.EndChangeCheck())
{
Undo.RegisterUndo(target, "Removed State IK");
}
iKScript.stateIKs.RemoveAt(i);
break;
}
//Open State Button (ID and Name)
string stateName = "ID: "+i.ToString("00")+" - "+iKScript.stateIKs[i].iKName;
Color previousColor = GUI.color;
if(iKScript.playing && iKScript.stateIKs[i].isActive)
{
stateName = stateName+" (PLAYING)";
if(iKScript.stateIKs[i].incomplete)
{
GUI.color = IKColors.incompleteIKColor;
}else{
GUI.color = IKColors.workingIKColor;
}
}
if(iKScript.stateIKs[i].open)
{
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
if(GUILayout.Button("▼ "+stateName))
{
iKScript.stateIKs[i].open = !iKScript.stateIKs[i].open;
}
GUI.color = previousColor;
GUILayout.EndHorizontal();
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
//Rename field
GUILayout.BeginHorizontal();
GUILayout.Space(60);
EditorGUI.BeginChangeCheck();
string iName = EditorGUILayout.TextField("", iKScript.stateIKs[i].iKName);
if(EditorGUI.EndChangeCheck()) {
Undo.RegisterUndo(target, "IK State rename");
iKScript.stateIKs[i].iKName = iName;
}
GUILayout.EndHorizontal();
//Single IK / Sequence IK Buttons
GUILayout.BeginHorizontal();
GUILayout.Space(60);
GUI.enabled = iKScript.stateIKs[i].isSequence;
buttonContent = new GUIContent("Single IK", "Use only 1 IK per animation (default)");
if(GUILayout.Button(buttonContent))
{
iKScript.stateIKs[i].isSequence = !iKScript.stateIKs[i].isSequence;
}
if(iKScript.stateIKs[i].IKs.Count <= 0)
{
iKScript.stateIKs[i].IKs.Add(new IKAttachment());
}
GUI.enabled = !iKScript.stateIKs[i].isSequence;
buttonContent = new GUIContent("Sequence of IK", "Use more than 1 IK in the same animation");
if(GUILayout.Button(buttonContent))
{
iKScript.stateIKs[i].isSequence = !iKScript.stateIKs[i].isSequence;
}
GUILayout.EndHorizontal();
//IK Attachments
GUI.enabled = true;
List<IKAttachment> iIKAttachments = new List<IKAttachment>(iKScript.stateIKs[i].IKs);
for(int k = 0; k < iKScript.stateIKs[i].IKs.Count; k++)
{
int incompleteFields = 0;
//Open State Button (ID and Name)
string ikName = "Attachment ID: "+k.ToString("00");
if(iKScript.playing && iKScript.stateIKs[i].isActive && iKScript.stateIKs[i].activeAttachment == k)
{
ikName = ikName+" [PLAYING] "+(iKScript.stateIKs[i].IKs[k].weight*100f).ToString("00")+"%";
}
GUILayout.BeginHorizontal();
GUILayout.Space(60);
EditorGUILayout.LabelField(ikName, EditorStyles.boldLabel);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Space(60);
//Remove IK Attachment (IK Sequence only)
if(iKScript.stateIKs[i].isSequence)
{
if(k > 0)
{
buttonContent = new GUIContent("[X]", "Remove this IK Attachment");
if(GUILayout.Button(buttonContent, GUILayout.Width(30)))
{
EditorGUI.BeginChangeCheck();
GUI.changed = true;
if(EditorGUI.EndChangeCheck())
{
Undo.RegisterUndo(target, "Removed IK Attachment");
}
iKScript.stateIKs[i].IKs.RemoveAt(k);
break;
}
}
}
if(iKScript.stateIKs[i].IKs[k].iKAttachment == null)
{
GUI.color = IKColors.incompleteIKColor;
incompleteFields = 2;
}
//IK Attachment Transform field (Game Object)
EditorGUI.BeginChangeCheck();
Transform iIKAttachment = EditorGUILayout.ObjectField("", iKScript.stateIKs[i].IKs[k].iKAttachment, typeof(Transform)) as Transform;
if(EditorGUI.EndChangeCheck()) {
Undo.RegisterUndo(target, "Change IK Attachment");
iKScript.stateIKs[i].IKs[k].iKAttachment = iIKAttachment;
}
GUILayout.EndHorizontal();
GUI.color = previousColor;
if(!iKScript.stateIKs[i].IKs[k].useLocation)
{
if(!iKScript.stateIKs[i].IKs[k].useRotation)
{
GUI.color = IKColors.incompleteIKColor;
}
incompleteFields++;
}
//Enable follow IK Attachment Location
GUILayout.BeginHorizontal();
GUILayout.Space(60);
EditorGUI.BeginChangeCheck();
bool iUseLocation = EditorGUILayout.Toggle("Use Location", iKScript.stateIKs[i].IKs[k].useLocation);
if(EditorGUI.EndChangeCheck()) {
Undo.RegisterUndo(target, "Change IK Use Location");
iKScript.stateIKs[i].IKs[k].useLocation = iUseLocation;
}
GUILayout.EndHorizontal();
GUI.color = previousColor;
if(!iKScript.stateIKs[i].IKs[k].useRotation)
{
if(!iKScript.stateIKs[i].IKs[k].useLocation)
{
GUI.color = IKColors.incompleteIKColor;
}
incompleteFields++;
}
//Enable follow IK Attachment Rotation
GUILayout.BeginHorizontal();
GUILayout.Space(60);
EditorGUI.BeginChangeCheck();
bool iUseRotation = EditorGUILayout.Toggle("Use Rotation", iKScript.stateIKs[i].IKs[k].useRotation);
if(EditorGUI.EndChangeCheck()) {
Undo.RegisterUndo(target, "Change IK Use Rotation");
iKScript.stateIKs[i].IKs[k].useRotation = iUseRotation;
}
GUILayout.EndHorizontal();
GUI.color = previousColor;
if(incompleteFields >= 2)
{
iKScript.stateIKs[i].incomplete = true;
}else{
iKScript.stateIKs[i].incomplete = false;
}
//Copy IK Attachment Transform values in Play Mode
GUI.enabled = true;
GUILayout.BeginHorizontal();
GUILayout.Space(60);
if(EditorApplication.isPlaying)
{
if(IKHelperUtils.IKClipboard && IKHelperUtils.IKClipBoardId == k)
{
buttonContent = new GUIContent("IK "+k.ToString("00")+" copied!", "Copy changes made in Play Mode");
}else{
buttonContent = new GUIContent("Copy IK Position/Rotation", "Copy changes made in Play Mode");
}
if(GUILayout.Button(buttonContent))
{
IKHelperUtils.copiedPos = iKScript.stateIKs[i].IKs[k].iKAttachment.localPosition;
IKHelperUtils.copiedRot = iKScript.stateIKs[i].IKs[k].iKAttachment.localEulerAngles;
IKHelperUtils.IKClipboard = true;
IKHelperUtils.IKClipBoardId = k;
}
}else{
//Paste IK Attachment Transform values from Play Mode
GUI.enabled = IKHelperUtils.IKClipboard;
buttonContent = new GUIContent("Paste IK Position/Rotation", "Paste changes made in Play Mode");
if(GUILayout.Button(buttonContent))
{
EditorGUI.BeginChangeCheck();
GUI.changed = true;
if(EditorGUI.EndChangeCheck()) {
Undo.RegisterUndo(target, "Pasted "+k.ToString("00")+" IK Pos/Rot");
}
iKScript.stateIKs[i].IKs[k].iKAttachment.localPosition = IKHelperUtils.copiedPos;
iKScript.stateIKs[i].IKs[k].iKAttachment.localEulerAngles = IKHelperUtils.copiedRot;
Debug.Log("Pasted IK Position/Rotation on IK Attachment "+k.ToString("00")+" in State "+i.ToString("00")+".");
}
GUI.enabled = true;
}
GUILayout.EndHorizontal();
if(iKScript.stateIKs[i].isSequence)
{
GUILayout.BeginHorizontal();
GUILayout.Space(60);
IKHelperUtils.DrawUILine(Color.black, 1, 10);
GUILayout.EndHorizontal();
}else{
break;
}
}
//Add IK Attachment (IK Sequence only)
if(iKScript.stateIKs[i].isSequence)
{
GUILayout.BeginHorizontal();
GUILayout.Space(60);
iIKAttachments = new List<IKAttachment>(iKScript.stateIKs[i].IKs);
buttonContent = new GUIContent("[+] Add IK Attachment", "Add a new IK attachment");
if(GUILayout.Button(buttonContent))
{
EditorGUI.BeginChangeCheck();
GUI.changed = true;
if(EditorGUI.EndChangeCheck())
{
Undo.RegisterUndo(target, "Added IK Attachment");
}
iKScript.stateIKs[i].IKs.Add(new IKAttachment());
}
GUILayout.EndHorizontal();
}
}else{
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
if(GUILayout.Button("► "+stateName))
{
iKScript.stateIKs[i].open = !iKScript.stateIKs[i].open;
}
GUI.color = previousColor;
GUILayout.EndHorizontal();
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
}
GUILayout.BeginHorizontal();
GUILayout.Space(30);
IKHelperUtils.DrawUILine(Color.black, 1, 5);
GUILayout.EndHorizontal();
}
//[+] Add State IK Button
GUILayout.BeginHorizontal();
GUILayout.Space(30);
iStateIKs = new List<StateIK>(iKScript.stateIKs);
buttonContent = new GUIContent("[+] Add State IK", "Add a new IK to take effect while in a state");
if(GUILayout.Button(buttonContent))
{
EditorGUI.BeginChangeCheck();
GUI.changed = true;
if(EditorGUI.EndChangeCheck())
{
Undo.RegisterUndo(target, "Added State IK");
}
iKScript.stateIKs.Add(new StateIK());
}
GUILayout.EndHorizontal();
if(GUI.changed)
{
if(!EditorApplication.isPlaying)
{
EditorUtility.SetDirty(target);
EditorApplication.MarkSceneDirty();
}
}
}
}
}
#endif