Files
trail-into-darkness/Packages/com.jovian.inspector/Editor/Attributes/AnimatorParameterAttribute.cs
2026-03-29 18:59:24 +02:00

105 lines
4.4 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace InspectorToolkit {
public class AnimatorParameterAttribute : PropertyAttribute {
public readonly string animatorPropertyName;
public bool allParameterTypes;
public AnimatorControllerParameterType parameterType;
public AnimatorParameterAttribute(string animatorPropertyName) {
this.animatorPropertyName = animatorPropertyName;
allParameterTypes = true;
}
public AnimatorParameterAttribute(string animatorPropertyName, AnimatorControllerParameterType parameterType) {
this.animatorPropertyName = animatorPropertyName;
allParameterTypes = false;
this.parameterType = parameterType;
}
}
}
#if UNITY_EDITOR
namespace InspectorToolkit.Internal {
[CustomPropertyDrawer(typeof(AnimatorParameterAttribute))]
public class AnimatorParameterAttributeDrawer : PropertyDrawer {
private bool hasAnimator;
private Animator animator;
private string[] parameterNames;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
label = EditorGUI.BeginProperty(position, label, property);
position = EditorGUI.PrefixLabel(position, label);
if(parameterNames == null) {
var animatorParameterAttribute = (AnimatorParameterAttribute)attribute;
string animatorFieldName = animatorParameterAttribute.animatorPropertyName;
parameterNames = UpdateParameterNames(property, animatorFieldName, animatorParameterAttribute.allParameterTypes, animatorParameterAttribute.parameterType);
}
EditorGUI.BeginChangeCheck();
bool didChange = false;
if(parameterNames is { Length: > 0 }) {
int parameterIndex = Array.IndexOf(parameterNames, property.stringValue);
int newIndex = EditorGUI.Popup(position, parameterIndex, parameterNames);
if(parameterIndex != newIndex) {
property.stringValue = parameterNames[newIndex];
didChange = true;
}
}
else {
EditorGUI.PropertyField(position, property, GUIContent.none);
}
int indentLevel = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
if(EditorGUI.EndChangeCheck() || didChange) {
property.serializedObject.ApplyModifiedProperties();
}
EditorGUI.indentLevel = indentLevel;
EditorGUI.EndProperty();
}
private string[] UpdateParameterNames(SerializedProperty property, string animatorFieldName, bool allParameterTypesAllowed, AnimatorControllerParameterType parameterType) {
int pathIndexOfPropertyName = property.propertyPath.LastIndexOf(property.name, StringComparison.Ordinal);
bool isTopLevelObject = pathIndexOfPropertyName == 0;
SerializedProperty animatorProperty;
if(isTopLevelObject) {
animatorProperty = property.serializedObject.FindProperty(animatorFieldName);
}
else {
SerializedProperty parentProperty = property.serializedObject.FindProperty(property.propertyPath.Substring(0, pathIndexOfPropertyName - 1));
animatorProperty = parentProperty.FindPropertyRelative(animatorFieldName);
}
if(animatorProperty is { objectReferenceValue: Animator targetAnimator }) {
if(!targetAnimator.gameObject.activeSelf ||
!targetAnimator.gameObject.activeInHierarchy ||
targetAnimator.runtimeAnimatorController == null) {
return new string[] { }; // return an empty array so it uses the fallback of just text
}
AnimatorControllerParameter[] parameters = targetAnimator.parameters;
if(allParameterTypesAllowed) {
return parameters.Select(p => p.name).ToArray();
}
else {
return parameters.Where(p => p.type == parameterType).Select(p => p.name).ToArray();
}
}
return new[] { "<MISSING>" };
}
}
}
#endif