/////////////////////////////////////////////////////////////////////////// // IK Helper Tool 1.1 - Sequence IK StateMachineBehaviour // // 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; //For custom inspector only #if UNITY_EDITOR using UnityEditor; #endif namespace KevinIglesias { public class IKHelperToolSequenceSMB : StateMachineBehaviour { private IKHelperTool iKHTScript; public int id; public int selectorIKType; public IKType goal; public bool smoothEntry; public bool clearOnExit; public bool isLoop; public List iKSequence = new List(); override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { if(iKHTScript == null) { iKHTScript = animator.GetComponent(); } if(iKHTScript != null) { iKHTScript.StartSequence(id, goal, iKSequence, smoothEntry, isLoop); } } override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { if(clearOnExit) { if(iKHTScript != null) { iKHTScript.ClearIK(false, id, 0, false, 0); } } } } #if UNITY_EDITOR //Custom Inspector [CustomEditor(typeof(IKHelperToolSequenceSMB))] public class IKHelperToolSequenceSMBCustomInspector : Editor { public override void OnInspectorGUI() { var SMBScript = target as IKHelperToolSequenceSMB; if(SMBScript.iKSequence == null) { SMBScript.iKSequence = new List(); } GUI.enabled = true; GUILayout.Space(5); GUILayout.BeginHorizontal(); EditorGUI.BeginChangeCheck(); EditorStyles.label.fontStyle = FontStyle.Bold; int iID = EditorGUILayout.IntField("State IK ID:", SMBScript.id); EditorStyles.label.fontStyle = FontStyle.Normal; if(EditorGUI.EndChangeCheck()) { Undo.RegisterUndo(target, "Changed ID"); SMBScript.id = iID; } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); EditorGUI.BeginChangeCheck(); iID = EditorGUILayout.Popup("IK Type:", SMBScript.selectorIKType, IKHelperUtils.IKGoalNames, EditorStyles.popup); if(EditorGUI.EndChangeCheck()) { Undo.RegisterUndo(target, "Changed IK Goal"); SMBScript.selectorIKType = iID; SMBScript.goal = (IKType)iID; } GUILayout.EndHorizontal(); IKHelperUtils.DrawUILine(Color.black, 1, 5); GUIContent buttonContent = null; for(int i = 0; i < SMBScript.iKSequence.Count; i++) { if(!SMBScript.iKSequence[i].useDefault) { GUILayout.BeginHorizontal(); EditorGUI.BeginChangeCheck(); EditorStyles.label.fontStyle = FontStyle.Bold; iID = EditorGUILayout.IntField("#"+i+"- Attachment ID: ", SMBScript.iKSequence[i].attachment); EditorStyles.label.fontStyle = FontStyle.Normal; if(EditorGUI.EndChangeCheck()) { Undo.RegisterUndo(target, "Changed ID"); SMBScript.iKSequence[i].attachment = iID; } GUILayout.EndHorizontal(); }else{ GUILayout.BeginHorizontal(); EditorGUILayout.LabelField("#"+i+"- Default Animation", EditorStyles.boldLabel); GUILayout.EndHorizontal(); } GUI.enabled = true; GUILayout.BeginHorizontal(); EditorGUI.BeginChangeCheck(); bool iDefault = EditorGUILayout.Toggle("Use default animation:", SMBScript.iKSequence[i].useDefault); if(EditorGUI.EndChangeCheck()) { Undo.RegisterUndo(target, "Change Use Default Animation"); SMBScript.iKSequence[i].useDefault = iDefault; } GUILayout.EndHorizontal(); if(i == 0) { GUILayout.BeginHorizontal(); EditorGUI.BeginChangeCheck(); bool iBool = EditorGUILayout.Toggle("Smooth Entry:", SMBScript.smoothEntry); if(EditorGUI.EndChangeCheck()) { Undo.RegisterUndo(target, "Change Smooth Entry"); SMBScript.smoothEntry = iBool; } GUILayout.EndHorizontal(); if(SMBScript.smoothEntry) { GUI.enabled = true; }else{ GUI.enabled = false; } GUILayout.BeginHorizontal(); EditorGUI.BeginChangeCheck(); float iFloat = EditorGUILayout.FloatField("Speed (seconds):", SMBScript.iKSequence[i].speed); if(EditorGUI.EndChangeCheck()) { Undo.RegisterUndo(target, "Change IK Speed"); SMBScript.iKSequence[i].speed = iFloat; } GUILayout.EndHorizontal(); GUI.enabled = true; }else{ if(SMBScript.iKSequence[i].speed < 0.01f) { SMBScript.iKSequence[i].speed = 0.01f; } GUILayout.BeginHorizontal(); EditorGUI.BeginChangeCheck(); float iFloat = EditorGUILayout.FloatField("Delay (seconds):", SMBScript.iKSequence[i].time); if(EditorGUI.EndChangeCheck()) { Undo.RegisterUndo(target, "Change IK Delay"); SMBScript.iKSequence[i].time = iFloat; } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); EditorGUI.BeginChangeCheck(); iFloat = EditorGUILayout.FloatField("Speed (seconds):", SMBScript.iKSequence[i].speed); if(EditorGUI.EndChangeCheck()) { Undo.RegisterUndo(target, "Change IK Speed"); SMBScript.iKSequence[i].speed = iFloat; } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); buttonContent = new GUIContent("[X] Delete this IK Entry", "Remove this IK Entry"); if(GUILayout.Button(buttonContent)) { EditorGUI.BeginChangeCheck(); GUI.changed = true; if(EditorGUI.EndChangeCheck()) { Undo.RegisterUndo(target, "Removed IK Entry"); } SMBScript.iKSequence.RemoveAt(i); break; } GUILayout.EndHorizontal(); } IKHelperUtils.DrawUILine(Color.black, 1, 5); } GUILayout.BeginHorizontal(); EditorGUI.BeginChangeCheck(); bool isLoop = EditorGUILayout.Toggle("Loop:", SMBScript.isLoop); if(EditorGUI.EndChangeCheck()) { Undo.RegisterUndo(target, "Change is Loop"); SMBScript.isLoop = isLoop; } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); EditorGUI.BeginChangeCheck(); bool clearExit = EditorGUILayout.Toggle("Clear IK on Exit:", SMBScript.clearOnExit); if(EditorGUI.EndChangeCheck()) { Undo.RegisterUndo(target, "Change Clear IK on Exit"); SMBScript.clearOnExit = clearExit; } GUILayout.EndHorizontal(); GUI.enabled = true; IKHelperUtils.DrawUILine(Color.black, 1, 5); GUILayout.BeginHorizontal(); List iIKSequence = new List(SMBScript.iKSequence); buttonContent = new GUIContent("[+] Add IK Entry (IK Attachment)", "Add a new IK entry to link with an IK Attachment"); if(GUILayout.Button(buttonContent)) { EditorGUI.BeginChangeCheck(); GUI.changed = true; if(EditorGUI.EndChangeCheck()) { Undo.RegisterUndo(target, "Added IK Entry"); } SMBScript.iKSequence.Add(new IKSequence()); } GUILayout.EndHorizontal(); GUILayout.Space(2); GUILayout.BeginHorizontal(); if(EditorApplication.isPlaying) { if(IKHelperUtils.sequenceClipboard) { buttonContent = new GUIContent("Variables copied!", "Copy changes made in Play Mode"); }else{ buttonContent = new GUIContent("Copy variables", "Copy changes made in Play Mode"); } if(GUILayout.Button(buttonContent)) { IKHelperUtils.savedSequenceSMB.id = SMBScript.id; IKHelperUtils.savedSequenceSMB.selectorIKType = SMBScript.selectorIKType; IKHelperUtils.savedSequenceSMB.goal = SMBScript.goal; IKHelperUtils.savedSequenceSMB.smoothEntry = SMBScript.smoothEntry; IKHelperUtils.savedSequenceSMB.clearOnExit = SMBScript.clearOnExit; IKHelperUtils.savedSequenceSMB.isLoop = SMBScript.isLoop; IKHelperUtils.savedSequenceSMB.iKSequence = new List(SMBScript.iKSequence); IKHelperUtils.sequenceClipboard = true; } }else{ GUI.enabled = IKHelperUtils.sequenceClipboard; buttonContent = new GUIContent("Paste variables", "Paste changes made in Play Mode"); if(GUILayout.Button(buttonContent)) { EditorGUI.BeginChangeCheck(); GUI.changed = true; if(EditorGUI.EndChangeCheck()) { Undo.RegisterUndo(target, "Pasted variables"); } SMBScript.id = IKHelperUtils.savedSequenceSMB.id; SMBScript.selectorIKType = IKHelperUtils.savedSequenceSMB.selectorIKType; SMBScript.goal = IKHelperUtils.savedSequenceSMB.goal; SMBScript.smoothEntry = IKHelperUtils.savedSequenceSMB.smoothEntry; SMBScript.clearOnExit = IKHelperUtils.savedSequenceSMB.clearOnExit; SMBScript.isLoop = IKHelperUtils.savedSequenceSMB.isLoop; SMBScript.iKSequence = new List(IKHelperUtils.savedSequenceSMB.iKSequence); Debug.Log("Pasted variables."); } GUI.enabled = true; } GUILayout.EndHorizontal(); if(GUI.changed) { if(!EditorApplication.isPlaying) { EditorUtility.SetDirty(target); EditorApplication.MarkSceneDirty(); } } } } #endif }