204 lines
8.1 KiB
C#
204 lines
8.1 KiB
C#
|
|
using System.Collections.Generic;
|
|||
|
|
using UnityEditor;
|
|||
|
|
using UnityEngine;
|
|||
|
|
|
|||
|
|
namespace StaTech.AnimationValidator {
|
|||
|
|
public class AnimationValidatorView : EditorWindow {
|
|||
|
|
private Texture2D _successIcon;
|
|||
|
|
private Texture2D SuccessIcon {
|
|||
|
|
get{
|
|||
|
|
if(_successIcon == null){
|
|||
|
|
_successIcon = GetBuiltInIcon("testpassed.png");
|
|||
|
|
}
|
|||
|
|
return _successIcon;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private Texture2D _errorIcon;
|
|||
|
|
private Texture2D ErrorIcon {
|
|||
|
|
get{
|
|||
|
|
if(_errorIcon == null){
|
|||
|
|
_errorIcon = GetBuiltInIcon("testfailed.png");
|
|||
|
|
}
|
|||
|
|
return _errorIcon;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private const float DetailSpace = 30f;
|
|||
|
|
private const float RightPadding = 30f;
|
|||
|
|
|
|||
|
|
private static List <ClipValidationContainer> _clipValidations;
|
|||
|
|
private static GameObject _selectedObject;
|
|||
|
|
private static AnimationValidatorView _window;
|
|||
|
|
private static Vector2 _scrollPos;
|
|||
|
|
|
|||
|
|
[MenuItem("GameObject/アニメーションクリップ修正", false, -1)]
|
|||
|
|
public static void Open(){
|
|||
|
|
_clipValidations = AnimationValidator.ValidateAnimation();
|
|||
|
|
if(_clipValidations == null){
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
_window = GetWindow <AnimationValidatorView>();
|
|||
|
|
_window.titleContent = new GUIContent("anim修正");
|
|||
|
|
_selectedObject = Selection.activeGameObject;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void OnGUI(){
|
|||
|
|
if(_clipValidations == null || _clipValidations.Count == 0){
|
|||
|
|
GUILayout.Label("AnimationClipがありません");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_scrollPos = EditorGUILayout.BeginScrollView(_scrollPos, true, true);
|
|||
|
|
GUILayout.Label("=====================================");
|
|||
|
|
GUILayout.Label("Animationでmissingになっているものを表示します");
|
|||
|
|
GUILayout.Label("オブジェクトの名前が他と被っていなれば自動で修正します");
|
|||
|
|
GUILayout.Label("=====================================");
|
|||
|
|
|
|||
|
|
if(_clipValidations.Count > 1){
|
|||
|
|
foreach(var result in _clipValidations){
|
|||
|
|
if(!result.HasNoError){
|
|||
|
|
DrawButton("全部まとめて修正", () => {
|
|||
|
|
AnimationValidator.ExecuteAllRecovery(_selectedObject, _clipValidations, ShowProgress);
|
|||
|
|
_window.Repaint();
|
|||
|
|
EditorApplication.RepaintAnimationWindow();
|
|||
|
|
});
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
foreach(var result in _clipValidations){
|
|||
|
|
DrawResult(result);
|
|||
|
|
}
|
|||
|
|
DrawButton("閉じる", () => _window.Close());
|
|||
|
|
EditorGUILayout.EndScrollView();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void DrawResult(ClipValidationContainer result){
|
|||
|
|
if(result.HasNoError){
|
|||
|
|
using(new EditorGUILayout.VerticalScope("box", GUILayout.Width(position.width - RightPadding))){
|
|||
|
|
DrawOnSuccess(result);
|
|||
|
|
}
|
|||
|
|
}else{
|
|||
|
|
using(new EditorGUILayout.VerticalScope("box", GUILayout.Width(position.width - RightPadding))){
|
|||
|
|
DrawOnError(result);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void DrawOnSuccess(ClipValidationContainer result){
|
|||
|
|
DrawIconAndLabel(SuccessIcon, result.ClipName, "→正常です");
|
|||
|
|
DrawDetail(result.LostProperties);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void DrawOnError(ClipValidationContainer result){
|
|||
|
|
DrawIconAndLabel(ErrorIcon, result.ClipName);
|
|||
|
|
DrawDetail(result.LostProperties);
|
|||
|
|
DrawButton("自動修正", () => {
|
|||
|
|
AnimationValidator.ExecuteUnitRecovery(_selectedObject, result, ShowProgress);
|
|||
|
|
_window.Repaint();
|
|||
|
|
EditorApplication.RepaintAnimationWindow();
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void ShowProgress(string content, float progress){
|
|||
|
|
EditorUtility.DisplayProgressBar("実行中", content, progress);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void DrawDetail(List <LostProperty> Props){
|
|||
|
|
using(new GUILayout.VerticalScope()){
|
|||
|
|
foreach(var prop in Props){
|
|||
|
|
var icon = prop.State == FixState.Fixed ? SuccessIcon : ErrorIcon;
|
|||
|
|
DrawSpaceAndText(DetailSpace, prop.PropPath + " : " + prop.AttributeName, icon, prop.State);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void DrawIconAndLabel(Texture image, string content, string detail = ""){
|
|||
|
|
using(new GUILayout.HorizontalScope()){
|
|||
|
|
GUILayout.Label(image, GUILayout.Height(18f), GUILayout.Width(20f));
|
|||
|
|
GUILayout.Label(content);
|
|||
|
|
if(!string.IsNullOrEmpty(detail)){
|
|||
|
|
GUIStyle s = new GUIStyle(EditorStyles.label){
|
|||
|
|
normal = { textColor = Color.green }
|
|||
|
|
};
|
|||
|
|
GUILayout.Label(detail, s);
|
|||
|
|
GUILayout.FlexibleSpace();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void DrawSpaceAndText(float space, string content, Texture headIcon, FixState state = FixState.None){
|
|||
|
|
using(new GUILayout.HorizontalScope()){
|
|||
|
|
GUILayout.Space(space);
|
|||
|
|
if(headIcon){
|
|||
|
|
GUILayout.Label(headIcon, GUILayout.Height(18f), GUILayout.Width(20f));
|
|||
|
|
}
|
|||
|
|
GUILayout.Label(content);
|
|||
|
|
var detail = GetDetail(state);
|
|||
|
|
if(!string.IsNullOrEmpty(detail)){
|
|||
|
|
// 黄色文字で足す
|
|||
|
|
var color = GetColor(state);
|
|||
|
|
if(color != Color.white){
|
|||
|
|
GUIStyle s = new GUIStyle(EditorStyles.label){
|
|||
|
|
normal = { textColor = color }
|
|||
|
|
};
|
|||
|
|
GUILayout.Label(detail, s);
|
|||
|
|
GUILayout.FlexibleSpace();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static Color GetColor(FixState state){
|
|||
|
|
switch(state){
|
|||
|
|
case FixState.ErrorDuplicate:
|
|||
|
|
case FixState.ErrorNoSameName:
|
|||
|
|
return Color.yellow;
|
|||
|
|
case FixState.Fixed:
|
|||
|
|
return Color.green;
|
|||
|
|
default:
|
|||
|
|
return Color.white;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static string GetDetail(FixState state){
|
|||
|
|
switch(state){
|
|||
|
|
case FixState.ErrorDuplicate:
|
|||
|
|
return "→同じ名前のオブジェクトが子階層上に複数あります";
|
|||
|
|
case FixState.ErrorNoSameName:
|
|||
|
|
return "→同じ名前のオブジェクトが見つかりませんでした";
|
|||
|
|
case FixState.Lost:
|
|||
|
|
return " ";
|
|||
|
|
case FixState.Fixed:
|
|||
|
|
return "→Animationのパスを変更しました";
|
|||
|
|
default:
|
|||
|
|
return "";
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void DrawButton(string buttonName, System.Action callback = null){
|
|||
|
|
if(GUILayout.Button(buttonName, GUILayout.Width(200f))){
|
|||
|
|
if(callback != null){
|
|||
|
|
callback.Invoke();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void OnDestroy(){
|
|||
|
|
if(_clipValidations != null){
|
|||
|
|
_clipValidations.Clear();
|
|||
|
|
_clipValidations = null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static Texture2D GetBuiltInIcon(string name){
|
|||
|
|
System.Reflection.MethodInfo mi = typeof(EditorGUIUtility).GetMethod("IconContent", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public, null, new System.Type[] { typeof(string) }, null);
|
|||
|
|
if(mi == null){
|
|||
|
|
mi = typeof(EditorGUIUtility).GetMethod("IconContent", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic, null, new System.Type[] { typeof(string) }, null);
|
|||
|
|
}
|
|||
|
|
return (Texture2D)((GUIContent) mi.Invoke(null, new object[] { name })).image;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|