Created
August 26, 2016 13:28
-
-
Save akof1314/65ca8ffcf64ccdc802730ddade71a8ff to your computer and use it in GitHub Desktop.
Unity Animator 窗口的控制
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Reflection; | |
using UnityEditor; | |
using UnityEditor.Animations; | |
using UnityEditor.Graphs; | |
using UnityEngine; | |
public class AnimatorControllerToolReflect | |
{ | |
private Assembly m_Assembly; | |
private Type m_TypeAnimatorWindow; | |
private Type m_TypeGraph; | |
private Type m_TypeGraphGUI; | |
private EditorWindow m_AnimatorWindow; | |
private Graph m_StateMachineGraph; | |
private GraphGUI m_StateMachineGraphGUI; | |
private PropertyInfo m_ActiveStateMachineInfo; | |
private MethodInfo m_AddBreadCrumbInfo; | |
private MethodInfo m_BuildBreadCrumbsFromSMHierarchyInfo; | |
private FieldInfo m_ScrollPositionInfo; | |
private FieldInfo m_GraphExtentsInfo; | |
private FieldInfo m_GraphClientAreaInfo; | |
private Assembly assembly | |
{ | |
get | |
{ | |
if (m_Assembly == null) | |
{ | |
m_Assembly = Assembly.GetAssembly(typeof(Graph)); | |
} | |
return m_Assembly; | |
} | |
} | |
private Type animatorWindowType | |
{ | |
get | |
{ | |
if (m_TypeAnimatorWindow == null) | |
{ | |
m_TypeAnimatorWindow = assembly.GetType("UnityEditor.Graphs.AnimatorControllerTool"); | |
} | |
return m_TypeAnimatorWindow; | |
} | |
} | |
private Type graphType | |
{ | |
get | |
{ | |
if (m_TypeGraph == null) | |
{ | |
m_TypeGraph = assembly.GetType("UnityEditor.Graphs.AnimationStateMachine.Graph"); | |
} | |
return m_TypeGraph; | |
} | |
} | |
private Type graphGUIType | |
{ | |
get | |
{ | |
if (m_TypeGraphGUI == null) | |
{ | |
m_TypeGraphGUI = assembly.GetType("UnityEditor.Graphs.AnimationStateMachine.GraphGUI"); | |
} | |
return m_TypeGraphGUI; | |
} | |
} | |
public EditorWindow animatorWindow | |
{ | |
get | |
{ | |
if (m_AnimatorWindow == null) | |
{ | |
FieldInfo toolInfo = animatorWindowType.GetField("tool", BindingFlags.Public | BindingFlags.Static); | |
m_AnimatorWindow = toolInfo.GetValue(null) as EditorWindow; | |
} | |
return m_AnimatorWindow; | |
} | |
} | |
public Graph stateMachineGraph | |
{ | |
get | |
{ | |
if (m_StateMachineGraph == null) | |
{ | |
FieldInfo stateMachineGraphInfo = animatorWindowType.GetField("stateMachineGraph", BindingFlags.Public | BindingFlags.Instance); | |
m_StateMachineGraph = stateMachineGraphInfo.GetValue(animatorWindow) as Graph; | |
} | |
return m_StateMachineGraph; | |
} | |
} | |
public GraphGUI stateMachineGraphGUI | |
{ | |
get | |
{ | |
if (m_StateMachineGraphGUI == null) | |
{ | |
FieldInfo stateMachineGraphGUIInfo = animatorWindowType.GetField("stateMachineGraphGUI", BindingFlags.Public | BindingFlags.Instance); | |
m_StateMachineGraphGUI = stateMachineGraphGUIInfo.GetValue(animatorWindow) as GraphGUI; | |
} | |
return m_StateMachineGraphGUI; | |
} | |
} | |
private PropertyInfo activeStateMachineInfoInfo | |
{ | |
get | |
{ | |
if (m_ActiveStateMachineInfo == null) | |
{ | |
m_ActiveStateMachineInfo = graphType.GetProperty("activeStateMachine", BindingFlags.Instance | BindingFlags.Public); | |
} | |
return m_ActiveStateMachineInfo; | |
} | |
} | |
public AnimatorStateMachine activeStateMachine | |
{ | |
get | |
{ | |
return activeStateMachineInfoInfo.GetValue(stateMachineGraph, null) as AnimatorStateMachine; | |
} | |
} | |
private MethodInfo addBreadCrumbInfo | |
{ | |
get | |
{ | |
if (m_AddBreadCrumbInfo == null) | |
{ | |
m_AddBreadCrumbInfo = animatorWindowType.GetMethod("AddBreadCrumb", BindingFlags.Instance | BindingFlags.Public); | |
} | |
return m_AddBreadCrumbInfo; | |
} | |
} | |
public void AddBreadCrumb(UnityEngine.Object target) | |
{ | |
addBreadCrumbInfo.Invoke(animatorWindow, new object[] {target}); | |
} | |
private MethodInfo buildBreadCrumbsFromSMHierarchyInfo | |
{ | |
get | |
{ | |
if (m_BuildBreadCrumbsFromSMHierarchyInfo == null) | |
{ | |
m_BuildBreadCrumbsFromSMHierarchyInfo = animatorWindowType.GetMethod("BuildBreadCrumbsFromSMHierarchy", BindingFlags.Instance | BindingFlags.Public); | |
} | |
return m_BuildBreadCrumbsFromSMHierarchyInfo; | |
} | |
} | |
public void BuildBreadCrumbsFromSMHierarchy(IEnumerable<AnimatorStateMachine> hierarchy) | |
{ | |
buildBreadCrumbsFromSMHierarchyInfo.Invoke(animatorWindow, new object[] { hierarchy }); | |
} | |
private FieldInfo scrollPositionInfo | |
{ | |
get | |
{ | |
if (m_ScrollPositionInfo == null) | |
{ | |
m_ScrollPositionInfo = graphGUIType.GetField("m_ScrollPosition", BindingFlags.Instance | BindingFlags.NonPublic); | |
} | |
return m_ScrollPositionInfo; | |
} | |
} | |
public Vector2 scrollPosition | |
{ | |
get | |
{ | |
return (Vector2)scrollPositionInfo.GetValue(stateMachineGraphGUI); | |
} | |
set | |
{ | |
scrollPositionInfo.SetValue(stateMachineGraphGUI, value); | |
} | |
} | |
private FieldInfo graphExtentsInfo | |
{ | |
get | |
{ | |
if (m_GraphExtentsInfo == null) | |
{ | |
m_GraphExtentsInfo = graphType.GetField("graphExtents", BindingFlags.Instance | BindingFlags.NonPublic); | |
} | |
return m_GraphExtentsInfo; | |
} | |
} | |
public Rect graphExtents | |
{ | |
get | |
{ | |
return (Rect)graphExtentsInfo.GetValue(stateMachineGraph); | |
} | |
} | |
private FieldInfo graphClientAreaInfo | |
{ | |
get | |
{ | |
if (m_GraphClientAreaInfo == null) | |
{ | |
m_GraphClientAreaInfo = graphGUIType.GetField("m_GraphClientArea", BindingFlags.Instance | BindingFlags.NonPublic); | |
} | |
return m_GraphClientAreaInfo; | |
} | |
} | |
public Rect graphClientArea | |
{ | |
get | |
{ | |
return (Rect)graphClientAreaInfo.GetValue(stateMachineGraphGUI); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEditor.Animations; | |
using UnityEditor.Graphs; | |
public static class AnimatorControllerToolUtil | |
{ | |
private static AnimatorControllerToolReflect animatorControllerToolReflect; | |
private static void InitReflect() | |
{ | |
if (animatorControllerToolReflect == null) | |
{ | |
animatorControllerToolReflect = new AnimatorControllerToolReflect(); | |
} | |
} | |
public static void SyncGraphToUnitySelection() | |
{ | |
InitReflect(); | |
GraphGUI graphGUI = animatorControllerToolReflect.stateMachineGraphGUI; | |
// 重要,没有这个设置,将会被底层返回 | |
GUIUtility.hotControl = 0; | |
graphGUI.SyncGraphToUnitySelection(); | |
} | |
public static void SetActiveStateMachine(AnimatorController animatorController, AnimatorStateMachine animatorStateMachine) | |
{ | |
InitReflect(); | |
AnimatorStateMachine activeStateMachine = animatorControllerToolReflect.activeStateMachine; | |
if (animatorStateMachine != activeStateMachine && animatorStateMachine != null) | |
{ | |
List<AnimatorStateMachine> hierarchy = new List<AnimatorStateMachine>(); | |
AnimatorControllerUtil.MecanimUtilities_StateMachineRelativePath( | |
AnimatorControllerUtil.AnimatorController_BaseLayerStateMachine(animatorController), | |
animatorStateMachine, ref hierarchy); | |
animatorControllerToolReflect.BuildBreadCrumbsFromSMHierarchy(hierarchy); | |
} | |
} | |
public static void ScrollToState(AnimatorStateMachine animatorStateMachine, AnimatorState state) | |
{ | |
InitReflect(); | |
Vector3 pos = AnimatorControllerUtil.AnimatorStateMachine_GetStatePosition(animatorStateMachine, state); | |
Rect graphExtents = animatorControllerToolReflect.graphExtents; | |
Rect graphClientArea = animatorControllerToolReflect.graphClientArea; | |
Vector2 pos2 = new Vector2(pos.x - graphExtents.x - graphClientArea.width / 2 + 100f, | |
pos.y - graphExtents.y - graphClientArea.height / 2 + 25f); | |
animatorControllerToolReflect.scrollPosition = pos2; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using UnityEngine; | |
using UnityEditor.Animations; | |
public static class AnimatorControllerUtil | |
{ | |
#region AnimatorController | |
/// <summary> | |
/// 获取动画控制器 Base Layer 层的状态机 | |
/// </summary> | |
/// <param name="animatorController"></param> | |
/// <returns></returns> | |
public static AnimatorStateMachine AnimatorController_BaseLayerStateMachine(AnimatorController animatorController) | |
{ | |
if (animatorController.layers.Length > 0) | |
{ | |
return animatorController.layers[0].stateMachine; | |
} | |
return null; | |
} | |
#endregion | |
#region AnimatorStateMachine | |
/// <summary> | |
/// 动画状态机是否包含指定的动画状态(不递归) | |
/// </summary> | |
/// <param name="stateMachines"></param> | |
/// <param name="state"></param> | |
/// <returns></returns> | |
public static bool AnimatorStateMachine_HasState(AnimatorStateMachine stateMachine, AnimatorState state, bool recursive = false) | |
{ | |
for (int i = 0; i < stateMachine.states.Length; i++) | |
{ | |
if (stateMachine.states[i].state == state) | |
{ | |
return true; | |
} | |
} | |
if (recursive) | |
{ | |
return AnimatorStateMachine_StatesRecursive(stateMachine).Any(s => s.state == state); | |
} | |
return false; | |
} | |
/// <summary> | |
/// 获取所有子状态机(递归) | |
/// </summary> | |
/// <param name="stateMachines"></param> | |
/// <returns></returns> | |
public static List<ChildAnimatorStateMachine> AnimatorStateMachine_StateMachinesRecursive(AnimatorStateMachine stateMachine) | |
{ | |
List<ChildAnimatorStateMachine> list = new List<ChildAnimatorStateMachine>(); | |
list.AddRange(stateMachine.stateMachines); | |
for (int i = 0; i < stateMachine.stateMachines.Length; i++) | |
{ | |
list.AddRange(AnimatorStateMachine_StateMachinesRecursive(stateMachine.stateMachines[i].stateMachine)); | |
} | |
return list; | |
} | |
/// <summary> | |
/// 获取所有的动画状态(递归) | |
/// </summary> | |
/// <param name="stateMachines"></param> | |
/// <returns></returns> | |
public static List<ChildAnimatorState> AnimatorStateMachine_StatesRecursive(AnimatorStateMachine stateMachine) | |
{ | |
List<ChildAnimatorState> list = new List<ChildAnimatorState>(); | |
list.AddRange(stateMachine.states); | |
for (int i = 0; i < stateMachine.stateMachines.Length; i++) | |
{ | |
list.AddRange(AnimatorStateMachine_StatesRecursive(stateMachine.stateMachines[i].stateMachine)); | |
} | |
return list; | |
} | |
public static Vector3 AnimatorStateMachine_GetStatePosition(AnimatorStateMachine stateMachine, AnimatorState state) | |
{ | |
ChildAnimatorState[] states = stateMachine.states; | |
for (int i = 0; i < states.Length; i++) | |
{ | |
if (state == states[i].state) | |
{ | |
return states[i].position; | |
} | |
} | |
return Vector3.zero; | |
} | |
#endregion | |
#region AnimatorState | |
/// <summary> | |
/// 查找动画状态的所在状态机 | |
/// </summary> | |
/// <param name="state"></param> | |
/// <param name="root"></param> | |
/// <returns></returns> | |
public static AnimatorStateMachine AnimatorState_FindParent(AnimatorState state, AnimatorStateMachine root) | |
{ | |
if (AnimatorStateMachine_HasState(root, state)) | |
{ | |
return root; | |
} | |
return AnimatorStateMachine_StateMachinesRecursive(root).Find(machine => | |
AnimatorStateMachine_HasState(machine.stateMachine, state) | |
).stateMachine; | |
} | |
#endregion | |
#region MecanimUtilities | |
public static bool MecanimUtilities_StateMachineRelativePath(AnimatorStateMachine parent, AnimatorStateMachine toFind, ref List<AnimatorStateMachine> hierarchy) | |
{ | |
hierarchy.Add(parent); | |
if (parent == toFind) | |
{ | |
return true; | |
} | |
for (int i = 0; i < parent.stateMachines.Length; i++) | |
{ | |
if (MecanimUtilities_StateMachineRelativePath(parent.stateMachines[i].stateMachine, toFind, ref hierarchy)) | |
{ | |
return true; | |
} | |
} | |
hierarchy.Remove(parent); | |
return false; | |
} | |
#endregion | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment