334 lines
12 KiB
C#
334 lines
12 KiB
C#
using Thousandto.Launcher.ExternalLibs;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEngine.Animations;
|
|
using UnityEngine.Playables;
|
|
|
|
namespace Thousandto.DIY.UniScene
|
|
{
|
|
public class AnimPlayEditor : EditorWindow
|
|
{
|
|
[MenuItem("Window/PlayableAnimation &6")]
|
|
static void Open()
|
|
{
|
|
var win = (AnimPlayEditor)EditorWindow.GetWindow(typeof(AnimPlayEditor));
|
|
win.Show();
|
|
}
|
|
|
|
private const float FrameWidthMaxScale = 1f;
|
|
private const float FrameWidthMinScale = 0.3f;
|
|
private float _curFrameWidthScale = 1f;
|
|
private int _curSelectFrame = 0;
|
|
private Vector2 _scrollPos = Vector2.zero;
|
|
private const int PageFrameCount = 301;
|
|
private AnimationClip _curSelectClip = null;
|
|
private AnimListScript _curPlayAnim = null;
|
|
private bool _isPlaying = false;
|
|
private float _playTimer = 0f;
|
|
private string[] _animNameList = new string[] { "1111", "2222"};
|
|
private List<AnimationClip> _animList = null;
|
|
private int _curSelectIndex = 0;
|
|
private bool _draging = false;
|
|
private PlayableGraph _graph;
|
|
private AnimationPlayableOutput _output;
|
|
private AnimationClipPlayable _animPlayable;
|
|
|
|
#region//属性
|
|
private float CurFrameWidth
|
|
{
|
|
get
|
|
{
|
|
return _curFrameWidthScale * 20;
|
|
}
|
|
}
|
|
|
|
public static bool IsOpen { get; private set; }
|
|
#endregion
|
|
|
|
private void CreatePlayable()
|
|
{
|
|
if(_graph.IsValid())
|
|
{
|
|
_graph.Destroy();
|
|
}
|
|
var animator = _curPlayAnim.GetComponent<Animator>();
|
|
_graph = PlayableGraph.Create();
|
|
_output = AnimationPlayableOutput.Create(_graph, "output", animator);
|
|
_graph.SetTimeUpdateMode(DirectorUpdateMode.Manual);
|
|
}
|
|
|
|
private void SetPlayClip(AnimationClip clip)
|
|
{
|
|
if(_animPlayable.IsValid())
|
|
{
|
|
_animPlayable.Destroy();
|
|
}
|
|
_curSelectClip = clip;
|
|
_curSelectClip.legacy = false;
|
|
_animPlayable = AnimationClipPlayable.Create(_graph, clip);
|
|
_output.SetSourcePlayable(_animPlayable);
|
|
}
|
|
|
|
private void OnClipGUI()
|
|
{
|
|
var clipFrameCount = (int)(_curSelectClip.length / (1f / 30f));
|
|
_scrollPos = GUILayout.BeginScrollView(_scrollPos, true, false);
|
|
int drawFrameCount = Math.Max(PageFrameCount, clipFrameCount);
|
|
var spaceCount = (int)(CurFrameWidth * drawFrameCount);
|
|
GUILayout.Box("", GUILayout.Width(spaceCount + 30));
|
|
|
|
Vector2 size = new Vector2(2, 50);
|
|
Vector2 pos = Vector2.zero;
|
|
Rect boxRect = new Rect();
|
|
Rect textRect = new Rect();
|
|
textRect.size = new Vector2(30, 20);
|
|
GUIStyle textStyle = new GUIStyle();
|
|
|
|
textStyle.alignment = TextAnchor.MiddleCenter;
|
|
|
|
GUIStyle eventStyle = new GUIStyle();
|
|
eventStyle.alignment = TextAnchor.MiddleCenter;
|
|
eventStyle.fontSize = 10;
|
|
|
|
int diffIndex = Mathf.RoundToInt(24f / CurFrameWidth);
|
|
for (int i = 0; i < drawFrameCount; ++i)
|
|
{
|
|
pos.x = i * CurFrameWidth + 10;
|
|
textRect.position = new Vector2(pos.x - 15, 0);
|
|
|
|
if (i % 5 == 0)
|
|
{
|
|
GUI.Label(textRect, i.ToString(), textStyle);
|
|
boxRect.size = new Vector2(2, 240);
|
|
pos.y = 20;
|
|
boxRect.position = pos;
|
|
}
|
|
else
|
|
{
|
|
pos.y = 25;
|
|
boxRect.size = new Vector2(2, 230);
|
|
boxRect.position = pos;
|
|
}
|
|
|
|
if (i < clipFrameCount)
|
|
{
|
|
GUI.color = Color.white;
|
|
}
|
|
else
|
|
{
|
|
GUI.color = Color.black;
|
|
}
|
|
GUI.Box(boxRect, string.Empty);
|
|
|
|
pos.x -= (CurFrameWidth / 2 - 4);
|
|
boxRect.position = pos;
|
|
boxRect.size = new Vector2(CurFrameWidth, 200);
|
|
if (_draging && boxRect.Contains(Event.current.mousePosition))
|
|
{
|
|
_curSelectFrame = i;
|
|
_isPlaying = false;
|
|
}
|
|
}
|
|
GUI.color = Color.red;
|
|
boxRect.position = new Vector2(_curSelectFrame * CurFrameWidth + 10, 0);
|
|
boxRect.size = new Vector2(2, 280);
|
|
GUI.Box(boxRect, string.Empty);
|
|
GUI.color = Color.white;
|
|
GUILayout.EndScrollView();
|
|
}
|
|
|
|
private void OnGUI()
|
|
{
|
|
var selectGo = UnityEditor.Selection.activeGameObject;
|
|
if (selectGo != null)
|
|
{
|
|
var animScript = selectGo.GetComponent<AnimListScript>();
|
|
if (animScript != null)
|
|
{
|
|
if (_curPlayAnim != animScript)
|
|
{
|
|
//重新设置动作
|
|
_curPlayAnim = animScript;
|
|
CreatePlayable();
|
|
_isPlaying = false;
|
|
|
|
_animNameList = null;
|
|
//选择默认动作
|
|
var animList = _curPlayAnim.GetAnimListByEditor();
|
|
var selfAnimList = _curPlayAnim.GetSelfAnimList();
|
|
if (animList.Count > 0 || selfAnimList.Count > 0)
|
|
{
|
|
for(int i = animList.Count - 1; i >= 0; --i)
|
|
{
|
|
if (animList[i] == null)
|
|
{
|
|
animList.RemoveAt(i);
|
|
}
|
|
}
|
|
for (int i = selfAnimList.Count - 1; i >= 0; --i)
|
|
{
|
|
if (selfAnimList[i] == null)
|
|
{
|
|
selfAnimList.RemoveAt(i);
|
|
}
|
|
}
|
|
_curSelectFrame = 0;
|
|
_curSelectIndex = 0;
|
|
_animNameList = new string[animList.Count + selfAnimList.Count];
|
|
_animList = new List<AnimationClip>(animList.Count + selfAnimList.Count);
|
|
for (int i = 0; i < selfAnimList.Count; ++i)
|
|
{
|
|
_animNameList[i] = selfAnimList[i].name;
|
|
_animList.Add(selfAnimList[i]);
|
|
}
|
|
|
|
for (int i = 0; i < animList.Count; ++i)
|
|
{
|
|
_animNameList[i + selfAnimList.Count] = animList[i].name;
|
|
_animList.Add(animList[i]);
|
|
}
|
|
SetPlayClip(_animList[0]);
|
|
}
|
|
else
|
|
{
|
|
_curSelectClip = null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
switch (Event.current.type)
|
|
{
|
|
case EventType.ScrollWheel:
|
|
{
|
|
float oldScale = _curFrameWidthScale;
|
|
_curFrameWidthScale -= Event.current.delta.y * 0.05f;
|
|
if (_curFrameWidthScale > FrameWidthMaxScale)
|
|
{
|
|
_curFrameWidthScale = FrameWidthMaxScale;
|
|
}
|
|
if (_curFrameWidthScale < FrameWidthMinScale)
|
|
{
|
|
_curFrameWidthScale = FrameWidthMinScale;
|
|
}
|
|
}
|
|
break;
|
|
case EventType.MouseDown:
|
|
{
|
|
if (Event.current.button == 0)
|
|
{
|
|
//左键
|
|
_draging = true;
|
|
}
|
|
}
|
|
break;
|
|
case EventType.MouseUp:
|
|
{
|
|
if (Event.current.button == 0)
|
|
{
|
|
//左键
|
|
_draging = false;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (_curPlayAnim != null)
|
|
{
|
|
if (_animList != null && _animList.Count > 0)
|
|
{
|
|
if (_curSelectClip != null)
|
|
{
|
|
if (!_animList.Contains(_curSelectClip))
|
|
{
|
|
//不是自己的动作,重新设置动作
|
|
SetPlayClip(_animList[0]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//没有动作,重新设置动作
|
|
SetPlayClip(_animList[0]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
EditorGUILayout.LabelField("动作列表为空");
|
|
//动作列表为空
|
|
_curSelectClip = null;
|
|
}
|
|
|
|
if (_animNameList != null && _animNameList.Length > 0)
|
|
{
|
|
EditorGUILayout.BeginHorizontal();
|
|
var newSelect = EditorGUILayout.Popup(_curSelectIndex, _animNameList, GUILayout.Width(100));
|
|
if (_curSelectIndex != newSelect)
|
|
{
|
|
_curSelectIndex = newSelect;
|
|
SetPlayClip(_animList[_curSelectIndex]);
|
|
_isPlaying = false;
|
|
_curSelectFrame = 0;
|
|
_draging = false;
|
|
}
|
|
if(!_isPlaying)
|
|
{
|
|
if (GUILayout.Button("播放", GUILayout.Width(100)))
|
|
{
|
|
_isPlaying = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (GUILayout.Button("停止", GUILayout.Width(100)))
|
|
{
|
|
_isPlaying = false;
|
|
_playTimer = 0f;
|
|
}
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
if (_curSelectClip != null)
|
|
{
|
|
OnClipGUI();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
EditorGUILayout.LabelField("请选择正确的AnimListScript动作组件");
|
|
}
|
|
Repaint();
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (_curSelectClip != null)
|
|
{
|
|
if (_isPlaying)
|
|
{
|
|
_playTimer += Time.deltaTime;
|
|
if (_playTimer > _curSelectClip.length)
|
|
{
|
|
_playTimer -= _curSelectClip.length;
|
|
}
|
|
_animPlayable.SetTime(_playTimer);
|
|
_graph.Evaluate();
|
|
_curSelectFrame = (int)(_playTimer / (1f / 30f));
|
|
}
|
|
else
|
|
{
|
|
var time = _curSelectFrame * (1f / 30f);
|
|
if (time > _curSelectClip.length)
|
|
{
|
|
time = _curSelectClip.length;
|
|
}
|
|
_animPlayable.SetTime(time);
|
|
_graph.Evaluate();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|