// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
#if UNITY_EDITOR
using System.Collections.Generic;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using Object = UnityEngine.Object;
namespace Animancer.Editor
{
/// [Editor-Only] A custom Inspector for s.
/// https://kybernetik.com.au/animancer/api/Animancer.Editor/NamedAnimancerComponentEditor
///
[CustomEditor(typeof(NamedAnimancerComponent), true), CanEditMultipleObjects]
public class NamedAnimancerComponentEditor : AnimancerComponentEditor
{
/************************************************************************************************************************/
///
protected override bool DoOverridePropertyGUI(string path, SerializedProperty property, GUIContent label)
{
switch (path)
{
case "_PlayAutomatically":
if (ShouldShowAnimationFields())
DoDefaultAnimationField(property);
return true;
case "_Animations":
if (ShouldShowAnimationFields())
DoAnimationsField(property);
return true;
default:
return base.DoOverridePropertyGUI(path, property, label);
}
}
/************************************************************************************************************************/
///
/// The and
/// fields are only used on startup, so we don't need to show
/// them in Play Mode after the object is already enabled.
///
private bool ShouldShowAnimationFields()
{
if (!EditorApplication.isPlayingOrWillChangePlaymode)
return true;
for (int i = 0; i < Targets.Length; i++)
if (!Targets[i].IsGraphInitialized)
return true;
return false;
}
/************************************************************************************************************************/
private void DoDefaultAnimationField(SerializedProperty playAutomatically)
{
var area = AnimancerGUI.LayoutSingleLineRect();
var playAutomaticallyWidth = EditorGUIUtility.labelWidth + AnimancerGUI.ToggleWidth;
var playAutomaticallyArea = AnimancerGUI.StealFromLeft(ref area, playAutomaticallyWidth);
using (var label = PooledGUIContent.Acquire(playAutomatically))
EditorGUI.PropertyField(playAutomaticallyArea, playAutomatically, label);
SerializedProperty firstElement;
AnimationClip clip;
var animations = serializedObject.FindProperty("_Animations");
if (animations.arraySize > 0)
{
firstElement = animations.GetArrayElementAtIndex(0);
clip = (AnimationClip)firstElement.objectReferenceValue;
EditorGUI.BeginProperty(area, null, firstElement);
}
else
{
firstElement = null;
clip = null;
EditorGUI.BeginProperty(area, null, animations);
}
EditorGUI.BeginChangeCheck();
var indentLevel = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
clip = AnimancerGUI.DoObjectFieldGUI(area, GUIContent.none, clip, true);
EditorGUI.indentLevel = indentLevel;
if (EditorGUI.EndChangeCheck())
{
if (clip != null)
{
if (firstElement == null)
{
animations.arraySize = 1;
firstElement = animations.GetArrayElementAtIndex(0);
}
firstElement.objectReferenceValue = clip;
}
else
{
if (firstElement == null || animations.arraySize == 1)
animations.arraySize = 0;
else
firstElement.objectReferenceValue = clip;
}
}
EditorGUI.EndProperty();
}
/************************************************************************************************************************/
private ReorderableList _Animations;
private static int _RemoveAnimationIndex;
private void DoAnimationsField(SerializedProperty property)
{
GUILayout.Space(AnimancerGUI.StandardSpacing - 1);
_Animations ??= new(property.serializedObject, property.Copy())
{
drawHeaderCallback = DrawAnimationsHeader,
drawElementCallback = DrawAnimationElement,
elementHeight = AnimancerGUI.LineHeight,
onRemoveCallback = RemoveSelectedElement,
};
_RemoveAnimationIndex = -1;
GUILayout.BeginVertical();
_Animations.DoLayoutList();
GUILayout.EndVertical();
if (_RemoveAnimationIndex >= 0)
property.DeleteArrayElementAtIndex(_RemoveAnimationIndex);
HandleDragAndDropToAddAnimations(GUILayoutUtility.GetLastRect(), property);
}
/************************************************************************************************************************/
private SerializedProperty _AnimationsArraySize;
private void DrawAnimationsHeader(Rect area)
{
var labelWidth = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth -= 6;
area.width += 5;
var property = _Animations.serializedProperty;
using (var label = PooledGUIContent.Acquire(property))
{
var propertyLabel = EditorGUI.BeginProperty(area, label, property);
if (_AnimationsArraySize == null)
{
_AnimationsArraySize = property.Copy();
_AnimationsArraySize.Next(true);
_AnimationsArraySize.Next(true);
}
EditorGUI.PropertyField(area, _AnimationsArraySize, propertyLabel);
EditorGUI.EndProperty();
}
EditorGUIUtility.labelWidth = labelWidth;
}
/************************************************************************************************************************/
private static readonly HashSet