sk-client/Assets/Scripts/AnimatorEvent/Editor/AnimatorEventEditor.cs

1194 lines
31 KiB
C#
Raw Permalink Normal View History

2024-07-03 18:38:10 +08:00
using UnityEngine;
using UnityEditor;
using UnityEditorInternal;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using UnityEditor.Animations;
using State = UnityEditor.Animations.AnimatorState;
using AnimatorTransitionBase = UnityEditor.Animations.AnimatorTransitionBase;
using AnimatorController = UnityEditor.Animations.AnimatorController;
using StateMachine = UnityEditor.Animations.AnimatorStateMachine;
using AnimatorControllerLayer = UnityEditor.Animations.AnimatorControllerLayer;
using GameLogic;
namespace Game {
public class AnimatorEventEditor : EditorWindow {
#region singleton
private static AnimatorEventEditor ms_instance = null;
public static AnimatorEventEditor instance {
get {
return ms_instance;
}
}
#endregion
#region private members
private AnimatorEventHandler m_handler = null;
private string[] m_animatorLayers = null;
private Dictionary<string, State[]> m_animatorStates = null;
private Dictionary<State, string> m_stateFullNames = null;
private Dictionary<StateMachine, string> m_stateMachineFullNames = null;
private Dictionary<int, AnimatorTransitionBase[]> m_animatorTransitions = null;
private int m_selectedLayerIndex = -1;
private int m_selectedStateIndex = -1;
private MsgEvent m_selectedEvent = null;
private bool m_isDataChanged = false;
private bool m_isSimulating = false;
private float m_playbackTime = 0f;
// 为了接入wwise的akwwisecomponetpicker而需要的参数
private SerializedObject m_AkSerializeObject = null;
private SerializedProperty[] m_AkValueProperty = null;
private string[] shakeTypeStrings = null;
#endregion
#region public properties
public AnimatorEventHandler handler {
set {
if (m_handler == value)
return;
_CheckDataSaved();
isSimulating = false;
m_handler = value;
_OnHandlerChanged();
}
get {
return m_handler;
}
}
#endregion
#region private properties
AnimatorController animatorController {
get {
if (handler == null)
return null;
if (handler.animator == null)
return null;
return (AnimatorController)handler.animator.runtimeAnimatorController;
}
}
int selectedLayerIndex {
set {
if (m_selectedLayerIndex == value)
return;
m_selectedLayerIndex = value;
_OnSelectedLayerChanged();
}
get {
return m_selectedLayerIndex;
}
}
string selectedLayerName {
get {
if (m_animatorLayers == null)
return null;
if (selectedLayerIndex < 0)
return null;
if (selectedLayerIndex >= m_animatorLayers.Length)
return null;
return m_animatorLayers[selectedLayerIndex];
}
}
State[] animatorStatesInSelectedLayer {
get {
if (m_animatorStates == null)
return null;
if (selectedLayerName == null)
return null;
State[] states;
if (!m_animatorStates.TryGetValue(selectedLayerName, out states))
return null;
return states;
}
}
string[] animatorStatesNameInSelectedLayer {
get {
if (animatorStatesInSelectedLayer == null)
return null;
string[] statesName = new string[animatorStatesInSelectedLayer.Length];
for (int i = 0; i < animatorStatesInSelectedLayer.Length; ++i)
statesName[i] = animatorStatesInSelectedLayer[i].name;
return statesName;
}
}
int selectedStateIndex {
set {
if (m_selectedStateIndex == value)
return;
m_selectedStateIndex = value;
_OnSelectedStateChanged();
}
get {
return m_selectedStateIndex;
}
}
State selectedState {
get {
if (animatorStatesInSelectedLayer == null)
return null;
if (selectedStateIndex < 0)
return null;
if (selectedStateIndex >= animatorStatesInSelectedLayer.Length)
return null;
return animatorStatesInSelectedLayer[selectedStateIndex];
}
}
float selectedStateLength {
get {
if (selectedState == null)
return 0;
Motion motion = selectedState.motion;
if (motion == null)
return 0;
return motion.averageDuration;
}
}
int selectedStateFrames {
get {
return Mathf.RoundToInt(selectedStateLength * 30);
}
}
List<MsgEvent> animatorEventsInSelectedState {
get {
if (handler == null)
return null;
if (handler.animatorEventData == null)
return null;
if (selectedState == null)
return null;
handler.animatorEventData.MakeSureEventList(GetUniqueNameHash(selectedState));
return handler.animatorEventData.GetEventList(GetUniqueNameHash(selectedState), selectedLayerIndex);
}
}
int GetUniqueNameHash(State state)
{
int hash = 0;
if (m_stateFullNames.ContainsKey(state))
{
hash = Animator.StringToHash(m_stateFullNames[state]);
}
else
{
hash = state.nameHash;
}
return hash;
}
bool RequestAddEvent(int stateHash, MsgEvent addEvent)
{
if (addEvent == null)
return false;
if (handler == null)
return false;
if (handler.animatorEventData == null)
return false;
return handler.animatorEventData.AddEvent(stateHash, addEvent);
}
bool RequestRemoveEvent(int stateHash, MsgEvent deleteEvent)
{
if (deleteEvent == null)
return false;
if (handler == null)
return false;
if (handler.animatorEventData == null)
return false;
return handler.animatorEventData.RemoveEvent(stateHash, deleteEvent);
}
MsgEvent selectedEvent {
set {
if (m_selectedEvent == value)
return;
m_selectedEvent = value;
_OnSelectedEventChanged();
}
get {
return m_selectedEvent;
}
}
bool isSimulating
{
set {
if (m_isSimulating == value)
return;
m_isSimulating = value;
if (m_isSimulating) {
_OnEnterSimulatingState();
}
else {
_OnLeaveSimulatingState();
}
}
get {
return m_isSimulating;
}
}
// In range [0, 1]
float playbackTime {
set {
if (value == 1f)
m_playbackTime = 1f;
else
m_playbackTime = Mathf.Repeat(value, 1f);
Repaint();
}
get {
return m_playbackTime;
}
}
#endregion
public static void ShowWindow() {
GetWindow<AnimatorEventEditor>();
}
void OnEnable() {
ms_instance = this;
isSimulating = false;
titleContent.text = "编辑动画器事件"; // title
minSize = new Vector2(950, 320);
m_AkSerializeObject = new SerializedObject(this);
m_AkValueProperty = new SerializedProperty[1];
m_AkValueProperty[0] = m_AkSerializeObject.FindProperty("valueGuid.Array");
shakeTypeStrings = new string[4];
shakeTypeStrings[0] = "全方向随机";
shakeTypeStrings[1] = "上下震动";
shakeTypeStrings[2] = "左右震动";
shakeTypeStrings[3] = "前后震动";
}
void OnDisable() {
isSimulating = false;
handler = null;
ms_instance = null;
}
#region OnGUI
void OnGUI() {
if (animatorController == null)
{
if (handler != null && handler.animator != null && handler.animator.runtimeAnimatorController==null)
{
ShowNotification(new GUIContent("该Animator没有控制器请先选择控制器."));
}
else
{
ShowNotification(new GUIContent("请先选择一个有Animator和AnimatorEventHandler组件的物件."));
}
return;
}
RemoveNotification();
GUILayout.BeginVertical();
GUILayout.Space(10);
GUILayout.BeginHorizontal();
_DrawLayersPanel();
GUILayout.Space(10);
_DrawStatesPanel();
GUILayout.Space(10);
_DrawStateInformation();
GUILayout.EndHorizontal();
GUILayout.Space(10);
GUILayout.EndVertical();
if (!Application.isPlaying)
m_isSimulating = false;
if (isSimulating) {
_SimulateStateStatus();
}
else {
_SyncStateStatus();
}
}
private Vector2 m_LayerScrollPos;
void _DrawLayersPanel() {
GUILayout.BeginVertical(GUILayout.Width(150));
if (animatorController != null && m_animatorLayers != null) {
GUILayout.Label(string.Format("动画器[{0}]有{1}个动画层。", animatorController.name, m_animatorLayers.Length));
GUILayout.BeginVertical("Box");
m_LayerScrollPos = GUILayout.BeginScrollView(m_LayerScrollPos);
selectedLayerIndex = GUILayout.SelectionGrid(selectedLayerIndex, m_animatorLayers, 1);
GUILayout.EndScrollView();
GUILayout.EndVertical();
}
else {
GUILayout.Label("此动画器无动画层!");
}
GUILayout.EndVertical();
}
private Vector2 m_StateScrollPos;
void _DrawStatesPanel() {
GUILayout.BeginVertical(GUILayout.Width(200));
if (selectedLayerName != null && animatorStatesNameInSelectedLayer != null) {
GUILayout.Label(string.Format("动画层[{0}]有{1}个动画状态。", selectedLayerName, animatorStatesNameInSelectedLayer.Length));
GUILayout.BeginVertical("Box");
m_StateScrollPos = GUILayout.BeginScrollView(m_StateScrollPos);
selectedStateIndex = GUILayout.SelectionGrid(selectedStateIndex, animatorStatesNameInSelectedLayer, 1);
GUILayout.EndScrollView();
GUILayout.EndVertical();
}
else {
GUILayout.Label("此动画层无动画状态。");
}
GUILayout.EndVertical();
}
void _DrawStateInformation() {
GUILayout.BeginVertical();
_DrawStateLabel();
GUILayout.Space(10);
GUILayout.BeginHorizontal();
GUILayout.Space(10);
_DrawStateTimeline();
GUILayout.Space(10);
GUILayout.EndHorizontal();
GUILayout.Space(10);
_DrawToolsPanel();
GUILayout.Space(10);
_DrawEventPanel();
GUILayout.EndVertical();
}
void _DrawStateLabel() {
if (selectedState == null) {
GUILayout.Label("请选择动画状态。");
return;
}
int totalEventCount = 0;
int effectEventCount = 0;
int wwiseEventCount = 0;
int cameraShakeEventCount = 0;
int msgEventCount = 0;
var listEvents = animatorEventsInSelectedState;
if (listEvents != null)
{
totalEventCount = listEvents.Count;
for (int i = 0; i < totalEventCount; ++i) {
switch (listEvents[i].type)
{
case AnimatorEventType.Msg:
++msgEventCount;
break;
default:
break;
}
}
}
GUILayout.Label(
string.Format(
"动画状态[{0}]{1}帧/{2}秒)共有{3}个动画事件,其中,{4}个Msg事件。请不要再黄线之后添加事件。",
selectedState.name,
selectedStateFrames,
selectedStateLength.ToString("0.00"),
totalEventCount,
msgEventCount));
}
void _DrawStateTimeline() {
Rect rect = GUILayoutUtility.GetRect(500, 10000, 50, 50);
int timelineId = GUIUtility.GetControlID("TimelineControl".GetHashCode(), FocusType.Passive, rect);
Rect thumbRect = new Rect(rect.x + rect.width * playbackTime - 5, rect.y + 2, 10, 10);
Event e = Event.current;
switch (e.type) {
case EventType.Repaint:
Rect lineRect = new Rect(rect.x, rect.y + 10, rect.width, 1.5f);
_DrawTimeLine(lineRect);
GUI.skin.horizontalSliderThumb.Draw(thumbRect, new GUIContent(), timelineId);
break;
case EventType.MouseDown:
if (thumbRect.Contains(e.mousePosition)) {
GUIUtility.hotControl = timelineId;
e.Use();
}
else {
if (GUIUtility.hotControl == timelineId) {
GUIUtility.hotControl = 0;
}
}
break;
case EventType.MouseUp:
if (GUIUtility.hotControl == timelineId) {
GUIUtility.hotControl = 0;
e.Use();
}
break;
case EventType.MouseDrag:
if (GUIUtility.hotControl == timelineId) {
Vector2 guiPos = e.mousePosition;
float clampedX = Mathf.Clamp(guiPos.x, rect.x, rect.x + rect.width);
playbackTime = (clampedX - rect.x) / rect.width;
e.Use();
}
break;
default:
break;
}
var listEvent = animatorEventsInSelectedState;
if (listEvent != null)
{
for (int i = 0; i < listEvent.Count; ++i)
{
_DrawEventKey(rect, listEvent[i]);
}
}
if (selectedState != null)
{
_DrawMinimumExitTime(rect, GetMinimumExitTimeForState(GetUniqueNameHash(selectedState)));
}
}
private Material m_lineMaterial = null;
void _DrawTimeLine(Rect rect) {
if (Event.current.type != EventType.Repaint) {
return;
}
if (selectedStateFrames <= 0)
return;
if (m_lineMaterial == null) {
m_lineMaterial = new Material(Shader.Find("Diffuse"));
}
if (m_lineMaterial != null)
m_lineMaterial.SetPass(0);
GL.Begin(GL.LINES);
GL.Color(new Color(1f, 1f, 1f, 0.75f));
_DrawHorizontalLine(rect.x, rect.y, rect.width);
_DrawHorizontalLine(rect.x, rect.y + 25, rect.width);
float frameWidth = rect.width / selectedStateFrames;
for (int i = 0; i <= selectedStateFrames; ++i) {
if (i % 10 == 0) {
_DrawVerticalLine(rect.x + i * frameWidth, rect.y, 15);
}
else if (i % 5 == 0) {
_DrawVerticalLine(rect.x + i * frameWidth, rect.y, 10);
}
else {
_DrawVerticalLine(rect.x + i * frameWidth, rect.y, 5);
}
}
GL.Color(new Color(1f, 1f, 1f, 0.75f));
_DrawVerticalLine(rect.x + rect.width * playbackTime, rect.y, 20);
GL.End();
}
void _DrawHorizontalLine(float x, float y, float width) {
GL.Vertex3(x, y, 0);
GL.Vertex3(x + width, y, 0);
}
void _DrawVerticalLine(float x, float y, float height) {
GL.Vertex3(x, y, 0);
GL.Vertex3(x, y + height, 0);
}
void _AddEventKey(object obj) {
MsgEvent newKey = null;
AnimatorEventType eventType = (AnimatorEventType)obj;
switch (eventType) {
case AnimatorEventType.Msg:
newKey = new MsgEvent();
newKey.name = "新建Msg事件";
break;
default:
break;
}
if (newKey != null && animatorEventsInSelectedState != null) {
newKey.layer = selectedLayerIndex;
newKey.normalizedTime = playbackTime;
RequestAddEvent(GetUniqueNameHash(selectedState), newKey);
m_isDataChanged = true;
selectedEvent = newKey;
}
}
void _DeleteEventKey() {
if (selectedEvent == null)
return;
if (selectedState == null)
return;
if (animatorEventsInSelectedState == null)
return;
int selectedIndex = animatorEventsInSelectedState.IndexOf(selectedEvent);
if (selectedIndex < 0)
return;
int stateHash = GetUniqueNameHash(selectedState);
RequestRemoveEvent(stateHash, selectedEvent);
selectedEvent = null;
List<MsgEvent> listEvent = animatorEventsInSelectedState;
m_isDataChanged = true;
if (listEvent.Count > 0)
{
if (selectedIndex >= listEvent.Count)
selectedIndex = listEvent.Count - 1;
selectedEvent = listEvent[selectedIndex];
}
}
void _DrawMinimumExitTime(Rect rect, float minimumExitTime)
{
float keyTime = minimumExitTime;
Rect keyRect = new Rect(rect.x + rect.width * keyTime - 3, rect.y, 6, 60);
int eventKeyCtrl = 999;
Event e = Event.current;
switch (e.type)
{
case EventType.Repaint:
Color savedColor = GUI.color;
GUI.color = Color.yellow;
GUI.skin.button.Draw(keyRect, new GUIContent(), eventKeyCtrl);
GUI.color = savedColor;
if (m_hotEventKey == eventKeyCtrl || (m_hotEventKey == 0 && keyRect.Contains(e.mousePosition)))
{
string labelString = string.Format(
"{0}@{1}", "exittime", minimumExitTime.ToString("0.0000"));
Vector2 size = EditorStyles.largeLabel.CalcSize(new GUIContent(labelString));
Rect infoRect = new Rect(rect.x + rect.width * keyTime - size.x, rect.y, size.x, size.y);
savedColor = GUI.color;
GUI.color = Color.yellow;
EditorStyles.largeLabel.Draw(infoRect, new GUIContent(labelString), eventKeyCtrl);
GUI.color = savedColor;
}
break;
}
}
private int m_hotEventKey = 0;
void _DrawEventKey(Rect rect, MsgEvent animatorEvent) {
if (animatorEvent.layer == -1)
{
animatorEvent.layer = selectedLayerIndex;
}
float keyTime = animatorEvent.normalizedTime;
Rect keyRect = new Rect(rect.x + rect.width * keyTime - 3, rect.y + 25, 6, 18);
int eventKeyCtrl = animatorEvent.GetHashCode();
Event e = Event.current;
switch (e.type) {
case EventType.Repaint:
Color savedColor = GUI.color;
GUI.color = Color.gray;
if (selectedEvent == animatorEvent)
GUI.color = Color.red;
GUI.skin.button.Draw(keyRect, new GUIContent(), eventKeyCtrl);
GUI.color = savedColor;
if (m_hotEventKey == eventKeyCtrl || (m_hotEventKey == 0 && keyRect.Contains(e.mousePosition))) {
string labelString = string.Format(
"{0}@{1}", animatorEvent.name, animatorEvent.normalizedTime.ToString("0.0000"));
Vector2 size = EditorStyles.largeLabel.CalcSize(new GUIContent(labelString));
Rect infoRect = new Rect(rect.x + rect.width * keyTime - size.x / 2, rect.y + 50, size.x, size.y);
EditorStyles.largeLabel.Draw(infoRect, new GUIContent(labelString), eventKeyCtrl);
}
break;
case EventType.MouseDown:
if (keyRect.Contains(e.mousePosition)) {
// 如果当前聚焦归一化时间编辑框,该编辑框的数据不会刷新。所以在选中事件时,清空当前聚焦。
EditorGUI.FocusTextInControl("");
m_hotEventKey = eventKeyCtrl;
selectedEvent = animatorEvent;
playbackTime = selectedEvent.normalizedTime;
e.Use();
}
break;
case EventType.MouseDrag:
if (m_hotEventKey == eventKeyCtrl) {
if (e.button == 0) {
Vector2 guiPos = e.mousePosition;
float clampedX = Mathf.Clamp(guiPos.x, rect.x, rect.x + rect.width);
animatorEvent.normalizedTime = (clampedX - rect.x) / rect.width;
m_isDataChanged = true;
selectedEvent = animatorEvent;
playbackTime = selectedEvent.normalizedTime;
}
e.Use();
}
break;
case EventType.MouseUp:
if (m_hotEventKey == eventKeyCtrl) {
m_hotEventKey = 0;
e.Use();
}
break;
}
}
void _DrawToolsPanel() {
GUILayout.BeginHorizontal();
EditorGUI.BeginDisabledGroup(Application.isPlaying == false);
string buttonText = isSimulating ? "关闭运行时编辑" : "开启运行时编辑";
if (GUILayout.Button(buttonText, GUILayout.Width(120))) {
isSimulating = !isSimulating;
if (!isSimulating && handler != null && handler.animator != null)
{
handler.animator.Update(0);
}
}
EditorGUI.EndDisabledGroup();
GUILayout.FlexibleSpace();
if (GUILayout.Button("添加事件", GUILayout.Width(80))) {
GenericMenu menu = new GenericMenu();
menu.AddItem(new GUIContent("Msg事件"), false, _AddEventKey, AnimatorEventType.Msg);
menu.ShowAsContext();
}
EditorGUI.BeginDisabledGroup(selectedEvent == null);
if (GUILayout.Button("删除事件", GUILayout.Width(80))) {
if (selectedEvent != null)
_DeleteEventKey();
}
EditorGUI.EndDisabledGroup();
EditorGUI.BeginDisabledGroup(false);
if (GUILayout.Button("清除冗余", GUILayout.Width(80)))
{
List<int> stateHashs = new List<int>();
foreach (var e in m_animatorStates)
{
for (int i = 0; i < e.Value.Length; ++i)
{
stateHashs.Add(GetUniqueNameHash(e.Value[i]));
}
}
}
EditorGUI.EndDisabledGroup();
GUILayout.Space(20);
EditorGUI.BeginDisabledGroup(m_isDataChanged == false);
if (GUILayout.Button("保存prefab", GUILayout.Width(80))) {
m_isDataChanged = false;
TestPrefabApply(handler.gameObject);
EditorUtility.SetDirty(handler.gameObject);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
if (GUILayout.Button("还原prefab", GUILayout.Width(80))) {
m_isDataChanged = false;
if (handler != null)
{
PrefabUtility.RevertPrefabInstance(handler.gameObject);
}
}
EditorGUI.EndDisabledGroup();
GUILayout.EndHorizontal();
if (selectedState == null)
return;
GUILayout.BeginHorizontal();
int slotIndex = 0;
List<MsgEvent> listBase = new List<MsgEvent>(animatorEventsInSelectedState);
List<MsgEvent> changedBase = new List<MsgEvent>();
List<string> listNormal = new List<string>();
int paramNum = 0;
while (listBase != null && listBase.Count > 0)
{
int index = 0;
for (int i = 1; i < listBase.Count; ++i)
{
if (listBase[i].normalizedTime < listBase[index].normalizedTime)
index = i;
}
if (listBase[index] == selectedEvent)
slotIndex = listNormal.Count;
changedBase.Add(listBase[index]);
listNormal.Add(string.Format("{0}: {1} - {2} - {3}", (paramNum++), listBase[index].type, listBase[index].name, listBase[index].normalizedTime));
listBase.RemoveAt(index);
}
int selectIndex = EditorGUILayout.Popup("事件列表", slotIndex, listNormal.ToArray());
if ((selectIndex >= 0 && selectIndex < changedBase.Count) && (selectIndex != slotIndex || selectedEvent == null))
{
selectedEvent = changedBase[selectIndex];
}
GUILayout.EndHorizontal();
}
private Vector2 m_EventScrollPos;
void _DrawEventPanel() {
EditorGUI.BeginChangeCheck();
GUILayout.BeginVertical("Box");
m_EventScrollPos = GUILayout.BeginScrollView(m_EventScrollPos);
if (selectedEvent != null) {
switch (selectedEvent.type) {
case AnimatorEventType.Msg:
_DrawMsgEventPanel();
break;
}
}
else {
GUILayout.Label("请选择要编辑的事件。");
}
GUILayout.EndScrollView();
GUILayout.EndVertical();
if (EditorGUI.EndChangeCheck()) {
m_isDataChanged = true;
}
}
static readonly string RESOURCES_DIR = "Resources/Prefabs/";
static readonly string PREFAB_SUFFIX = ".prefab";
string _GetEffectPrefabPath(GameObject effectPrefab) {
if (effectPrefab == null)
return string.Empty;
string filePath = AssetDatabase.GetAssetPath(effectPrefab);
bool isUseResourcePath = true;
if (isUseResourcePath)
{
int index = filePath.IndexOf(RESOURCES_DIR);
if (index < 0)
return filePath;
index += RESOURCES_DIR.Length;
if (index > filePath.Length)
return filePath;
filePath = filePath.Substring(index);
}
return filePath;
}
List<string> getAllGameNames()
{
var games = Directory.GetDirectories(AppConst.GameResRealPath);
var gameNames = new List<string>();
for (int i = 0; i < games.Length; i++)
{
games[i] = Path.GetFileNameWithoutExtension(games[i]);
gameNames.Add(games[i]);
}
return gameNames;
}
void _DrawMsgEventPanel() {
if (handler == null) return;
MsgEvent msgEvent = (MsgEvent)selectedEvent;
if (msgEvent == null) return;
GUILayout.BeginVertical();
GUILayout.Label(string.Format("编辑Msg事件[{0}@{1}]", msgEvent.name, msgEvent.normalizedTime));
GUILayout.Space(10);
msgEvent.name = EditorGUILayout.TextField("事件名称", msgEvent.name);
msgEvent.normalizedTime = EditorGUILayout.FloatField("归一化时间", msgEvent.normalizedTime);
msgEvent.normalizedTime = Mathf.Clamp(msgEvent.normalizedTime, 0, 1f);
msgEvent.msgFunction = EditorGUILayout.TextField("响应函数名称", msgEvent.msgFunction);
msgEvent.msgParams = EditorGUILayout.TextField("参数", msgEvent.msgParams);
GUILayout.EndVertical();
}
#endregion
public static void TestPrefabApply(GameObject selectGo)
{
if (selectGo == null)
{
Debug.LogError("请选中需要Apply的Prefab实例");
return;
}
PrefabType pType = EditorUtility.GetPrefabType(selectGo);
if (pType != PrefabType.PrefabInstance)
{
Debug.LogError("选中的实例不是Prefab实例");
return;
}
//这里必须获取到prefab实例的根节点否则ReplacePrefab保存不了
GameObject prefabGo = GetPrefabInstanceParent(selectGo);
UnityEngine.Object prefabAsset = null;
if (prefabGo != null)
{
prefabAsset = PrefabUtility.GetPrefabParent(prefabGo);
if (prefabAsset != null)
{
PrefabUtility.ReplacePrefab(prefabGo, prefabAsset, ReplacePrefabOptions.ConnectToPrefab);
}
}
AssetDatabase.SaveAssets();
}
//遍历获取prefab节点所在的根prefab节点
static GameObject GetPrefabInstanceParent(GameObject go)
{
if (go == null)
{
return null;
}
PrefabType pType = EditorUtility.GetPrefabType(go);
if (pType != PrefabType.PrefabInstance)
{
return null;
}
if (go.transform.parent == null)
{
return go;
}
pType = EditorUtility.GetPrefabType(go.transform.parent.gameObject);
if (pType != PrefabType.PrefabInstance)
{
return go;
}
return GetPrefabInstanceParent(go.transform.parent.gameObject);
}
void _CheckDataSaved() {
if (m_isDataChanged == false)
return;
if (handler == null)
return;
if (animatorController == null)
return;
string message = string.Format("动画器[{0}]的事件数据发生了变化,是否保存?", animatorController.name);
bool isSave = EditorUtility.DisplayDialog("是否保存动画器事件?", message, "保存", " 不保存");
if (isSave)
{
TestPrefabApply(handler.gameObject);
EditorUtility.SetDirty(handler.gameObject);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
m_isDataChanged = false;
}
void _OnHandlerChanged() {
m_animatorLayers = null;
m_animatorStates = null;
m_selectedLayerIndex = -1;
m_selectedStateIndex = -1;
selectedEvent = null;
if (handler == null)
return;
if (handler.animator == null)
return;
AnimatorController animatorController = (AnimatorController)handler.animator.runtimeAnimatorController;
if (animatorController == null)
return;
m_animatorLayers = new string[animatorController.layers.Length];
m_animatorStates = new Dictionary<string, State[]>();
m_stateFullNames = new Dictionary<State, string>();
m_stateMachineFullNames = new Dictionary<AnimatorStateMachine, string>();
m_animatorTransitions = new Dictionary<int, AnimatorTransitionBase[]>();
for (int i = 0; i < animatorController.layers.Length; ++i) {
AnimatorControllerLayer layer = animatorController.layers[i];
m_animatorLayers[i] = layer.name;
List<State> stateList = _GetStatesRecursive(layer.stateMachine);
m_animatorStates.Add(layer.name, stateList.ToArray());
Dictionary<int, AnimatorTransitionBase[]> transDic = _GetTransitionsRecursive(layer.stateMachine);
foreach (var e in transDic)
{
m_animatorTransitions[e.Key] = e.Value;
}
}
selectedLayerIndex = 0;
}
float GetMinimumExitTimeForState(int stateHash)
{
float exitTime = 1;
if (m_animatorTransitions == null)
return exitTime;
AnimatorTransitionBase[] trans = null;
if (!m_animatorTransitions.TryGetValue(stateHash, out trans) || trans == null)
return exitTime;
for (int j = 0; j < trans.Length; ++j)
{
AnimatorStateTransition stateTrans = trans[j] as AnimatorStateTransition;
if (stateTrans == null)
continue;
if (stateTrans.hasExitTime && stateTrans.exitTime < exitTime)
{
exitTime = stateTrans.exitTime;
}
}
return exitTime;
}
Dictionary<int, AnimatorTransitionBase[]> _GetTransitionsRecursive(StateMachine stateMachine)
{
Dictionary<int, AnimatorTransitionBase[]> dic = new Dictionary<int, AnimatorTransitionBase[]>();
for (int i = 0; i < stateMachine.states.Length; ++i)
{
State s = stateMachine.states[i].state;
dic[GetUniqueNameHash(s)] = s.transitions;
}
for (int i = 0; i < stateMachine.stateMachines.Length; ++i)
{
foreach (var e in _GetTransitionsRecursive(stateMachine.stateMachines[i].stateMachine))
{
dic[e.Key] = e.Value;
}
}
return dic;
}
List<State> _GetStatesRecursive(StateMachine stateMachine) {
if (!m_stateMachineFullNames.ContainsKey(stateMachine))
{
m_stateMachineFullNames.Add(stateMachine, stateMachine.name);
}
List<State> list = new List<State>();
list.AddRange(_GetAnimatorStates(stateMachine));
for (int i = 0; i < list.Count; ++i)
{
if (!m_stateFullNames.ContainsKey(list[i]))
{
m_stateFullNames.Add(list[i], m_stateMachineFullNames[stateMachine] + "." + list[i].name);
}
}
for (int i = 0; i < stateMachine.stateMachines.Length; ++i)
{
StateMachine childMachine = stateMachine.stateMachines[i].stateMachine;
if (!m_stateMachineFullNames.ContainsKey(childMachine))
{
m_stateMachineFullNames.Add(childMachine, m_stateMachineFullNames[stateMachine] + "." + childMachine.name);
}
list.AddRange(_GetStatesRecursive(stateMachine.stateMachines[i].stateMachine));
}
return list;
}
State[] _GetAnimatorStates(StateMachine stateMachine) {
State[] array = new State[stateMachine.states.Length];
for (int i = 0; i < stateMachine.states.Length; ++i) {
array[i] = stateMachine.states[i].state;
}
return array;
}
void _OnSelectedLayerChanged() {
selectedEvent = null;
selectedStateIndex = 0;
Repaint();
}
void _OnSelectedStateChanged() {
selectedEvent = null;
playbackTime = 0f;
Repaint();
}
void _OnSelectedEventChanged() {
if (!Application.isPlaying)
return;
if (!isSimulating)
return;
if (m_selectedEvent == null)
return;
_SimulateStateStatus();
}
void _OnEnterSimulatingState() {
if (!Application.isPlaying)
return;
if (handler != null)
handler.enabled = false;
if (handler.animator != null)
handler.animator.speed = 0f;
_OnSelectedEventChanged();
}
void _OnLeaveSimulatingState() {
if (!Application.isPlaying)
return;
if (handler != null) {
handler.enabled = true;
}
if (handler.animator != null)
handler.animator.speed = 1f;
}
void _SimulateStateStatus() {
if (!Application.isPlaying)
return;
if (handler == null)
return;
if (handler.animator != null) {
AnimatorControllerLayer ctllayer = animatorController.layers[selectedLayerIndex];
int playLayer = ctllayer.syncedLayerIndex < 0 ? selectedLayerIndex : ctllayer.syncedLayerIndex;
int nameHash = selectedState == null ? -1 : selectedState.nameHash;
handler.animator.Play(nameHash, playLayer, playbackTime);
}
}
void _SyncStateStatus() {
if (!Application.isPlaying)
return;
if (handler == null)
return;
if (animatorStatesInSelectedLayer == null)
return;
AnimatorStateInfo currentStateInfo = handler.GetCurrentStateInfo(selectedLayerIndex);
float _stateNormalizedTime = currentStateInfo.normalizedTime;
for (int i = 0; i < animatorStatesInSelectedLayer.Length; ++i) {
if (GetUniqueNameHash(animatorStatesInSelectedLayer[i]) != currentStateInfo.fullPathHash)
continue;
selectedStateIndex = i;
playbackTime = _stateNormalizedTime;
}
}
}
}