com.alicizax.unity.animatio.../Editor/Window/GraphWindow.cs

345 lines
10 KiB
C#
Raw Normal View History

2025-02-07 16:05:13 +08:00
using System;
using System.Collections.Generic;
using System.Linq;
using AlicizaX.AnimationFlow.Runtime;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
namespace AlicizaX.AnimationFlow.Editor
{
public class GraphWindow : EditorWindow
{
private GraphInspector graphInspector;
private GraphView graphContentView;
private Runtime.AnimationFlow animationFlowComponent;
private float editorPreviousTime;
private bool _subScribeEditorEventState;
[MenuItem("Window/AnimationGraph")]
public static void Open()
{
GetWindow<GraphWindow>("AnimationFlow");
}
private void Update()
{
if (graphContentView == null || animationFlowComponent == null || Application.isPlaying)
{
return;
}
if (animationFlowComponent.InPlaying)
{
float delta = (Time.realtimeSinceStartup - editorPreviousTime) * Time.timeScale;
editorPreviousTime = Time.realtimeSinceStartup;
animationFlowComponent.Tick(delta);
}
List<ActionNode> nodes = new List<ActionNode>();
foreach (var VARIABLE in animationFlowComponent.AnimationNodes)
{
nodes.Add(VARIABLE);
}
UpdateNodeState(nodes);
}
private void UpdateNodeState(List<ActionNode> nodes)
{
foreach (var node in nodes)
{
switch (node.State)
{
case EState.Enter:
graphContentView?.OnNodeEnter(node);
break;
case EState.Running:
graphContentView?.OnNodeUpdate(node);
break;
case EState.Exit:
graphContentView?.OnNodeExit(node);
break;
;
}
if (node.Childs.Count > 0)
{
UpdateNodeState(node.Childs);
}
}
}
private void OnEnable()
{
animationFlowComponent = null;
BuildView();
CheckSelectionAnimationFlow();
Selection.selectionChanged -= OnSelectionChanged;
Selection.selectionChanged += OnSelectionChanged;
Undo.undoRedoPerformed -= UndoRedoPerformed;
Undo.undoRedoPerformed += UndoRedoPerformed;
EditorApplication.playModeStateChanged -= OnModeStateChanged;
EditorApplication.playModeStateChanged += OnModeStateChanged;
}
private void OnDisable()
{
Selection.selectionChanged -= OnSelectionChanged;
Undo.undoRedoPerformed -= UndoRedoPerformed;
EditorApplication.playModeStateChanged -= OnModeStateChanged;
if (animationFlowComponent != null)
{
animationFlowComponent.ResetNode();
}
}
/// <summary>
/// 生成View
/// </summary>
private void BuildView()
{
if (!EditorResourceTool.LocateEditorAssets())
{
return;
}
Texture2D btnPlayIcon = EditorGUIUtility.FindTexture("d_PlayButton");
Texture2D btnPauseIcon = EditorGUIUtility.FindTexture("d_PauseButton");
Texture2D btnStepIcon = EditorGUIUtility.FindTexture("d_StepButton");
Texture2D btnSaveIcon = EditorGUIUtility.FindTexture("SaveActive");
VisualTreeAsset visual_tree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(EditorResourceTool.editorAssets + "/UIGraphWindow.uxml");
visual_tree.CloneTree(rootVisualElement);
graphInspector = new GraphInspector();
rootVisualElement.Q<VisualElement>("Inspector").Add(graphInspector);
VisualElement graph_parent = rootVisualElement.Q<VisualElement>("Graph");
GUIStyle gui_style = new();
Texture2D texture = new(1, 1);
texture.SetPixel(0, 0, new Color(0.25f, 0.25f, 0.25f, 1f));
texture.Apply();
gui_style.normal.background = texture;
gui_style.padding = new RectOffset(5, 5, 4, 4);
int index_name = 0;
IMGUIContainer imgui_container = new(() =>
{
if (animationFlowComponent == null)
{
graphContentView?.ClearGraph();
return;
}
GUILayout.BeginHorizontal(gui_style);
List<string> keys = new();
foreach (ActionNode baseData in animationFlowComponent.AnimationNodes)
{
if (baseData is EntryNode root && !string.IsNullOrEmpty(root.Name))
{
keys.Add(root.Name);
}
}
GUI.color = !animationFlowComponent.InPlaying && keys.Count > 0 ? Color.white : Color.gray;
index_name = EditorGUILayout.Popup(index_name, keys.ToArray(), GUILayout.Width(100));
if (GUILayout.Button(btnPlayIcon))
{
if (keys.Count > 0)
{
if (animationFlowComponent.InPlaying)
{
animationFlowComponent.Stop();
return;
}
OnBtnClickPlay(keys[index_name]);
}
}
GUI.color = animationFlowComponent.InPlaying ? Color.white : Color.gray;
if (GUILayout.Button(btnPauseIcon))
{
OnBtnClickPause();
}
GUI.color = animationFlowComponent.InPlaying || animationFlowComponent.InPause ? Color.white : Color.gray;
if (GUILayout.Button(btnStepIcon))
{
OnBtnClickStep();
}
GUI.color = Color.white;
GUILayout.EndHorizontal();
});
graph_parent.Add(imgui_container);
imgui_container.style.position = Position.Absolute;
imgui_container.style.bottom = 0;
imgui_container.style.alignSelf = Align.Center;
imgui_container.style.height = 40;
graphContentView = new(this);
graph_parent.Insert(0, graphContentView);
}
private void OnFocus()
{
CheckSelectionAnimationFlow();
}
private void OnSelectionChanged()
{
CheckSelectionAnimationFlow();
}
private void UndoRedoPerformed()
{
RePaintGraph();
}
private void OnModeStateChanged(PlayModeStateChange _)
{
if (TryGetPlayerFromSelection())
{
RePaintGraph();
}
else
{
graphInspector.Clear();
graphContentView.ClearGraph();
}
}
/// <summary>
/// 检查当前选中的物体是否存在AnimationFlow组件
/// </summary>
private void CheckSelectionAnimationFlow()
{
if (TryGetPlayerFromSelection())
{
RePaintGraph();
}
}
private void RePaintGraph()
{
List<ActionNode> nodes = new List<ActionNode>();
foreach (var VARIABLE in animationFlowComponent.AnimationNodes)
{
nodes.Add(VARIABLE);
}
CheckEmptyNode(nodes);
graphInspector.Clear();
graphContentView.ClearGraph();
graphContentView.SetAnimationFlow(animationFlowComponent);
}
private void CheckEmptyNode(List<ActionNode> nodes)
{
for (int i = nodes.Count - 1; i >= 0; i--)
{
if (nodes[i] == null)
{
nodes.RemoveAt(i);
}
if (nodes[i].Childs.Count > 0)
{
CheckEmptyNode(nodes[i].Childs);
}
}
}
private bool TryGetPlayerFromSelection()
{
if (Selection.activeGameObject != null)
{
Runtime.AnimationFlow new_animation_flow = Selection.activeGameObject.GetComponent<Runtime.AnimationFlow>();
if (new_animation_flow != null && (animationFlowComponent == null || new_animation_flow != animationFlowComponent))
{
if (animationFlowComponent != null)
{
// DeleteAction();
}
animationFlowComponent = new_animation_flow;
return true;
}
}
return false;
}
#region
private void OnBtnClickPlay(string name)
{
if (graphContentView == null || animationFlowComponent == null)
{
return;
}
if (animationFlowComponent.AnimationNodes.Exists(v => !v.Valid()))
{
EditorUtility.DisplayDialog("Warning", "Please make sure the required parameters are set.", "ok");
return;
}
editorPreviousTime = Time.realtimeSinceStartup;
ResetView();
animationFlowComponent.Play(name);
}
private void OnBtnClickPause()
{
if (graphContentView == null || animationFlowComponent == null || !animationFlowComponent.InPlaying)
{
return;
}
animationFlowComponent.AnimationFlowPlayebleType = EAnimationFlowPlayebleType.Pause;
}
private void OnBtnClickStep()
{
if (graphContentView == null || animationFlowComponent == null || !animationFlowComponent.InPlaying || !animationFlowComponent.InPause)
{
return;
}
animationFlowComponent.Tick(0.016f);
}
#endregion
public void OnSelect(NodeView node_view)
{
graphInspector.DrawNode(node_view);
}
public void OnNodeRemove()
{
graphInspector.Clear();
}
private void ResetView()
{
graphContentView?.ResetView();
}
}
}