using System; using System.Collections.Generic; using KitsuneCafe.Extension; using KitsuneCafe.Sys.Attributes; using UnityEditor; using UnityEditor.UIElements; using UnityEngine; using UnityEngine.UIElements; namespace KitsuneCafe.Editor { [CustomPropertyDrawer(typeof(AnimatorParamAttribute))] public class AnimatorParamPropertyDrawer : PropertyDrawer { public override VisualElement CreatePropertyGUI(SerializedProperty property) { var attribute = base.attribute as AnimatorParamAttribute; return property.type switch { "int" => new AnimatorIntParameterElement(property, attribute.AnimatorProperty), "string" => new AnimatorStringParameterElement(property, attribute.AnimatorProperty), _ => throw new ArgumentException("AnimatorParam must be bound to an int or string.") }; } public abstract class AnimatorParameterElement : PopupField, IDisposable { public readonly SerializedProperty Property; public string Label => ObjectNames.NicifyVariableName(Property.name); public readonly SerializedProperty AnimatorProperty; public AnimatorParameterElement(SerializedProperty property, string animatorPropertyName) : base(ObjectNames.NicifyVariableName(property.name)) { Property = property; AnimatorProperty = property.serializedObject.FindProperty(animatorPropertyName); this.RegisterValueChangedCallback(OnValueChanged); OnAnimatorChanged(AnimatorProperty); this.TrackPropertyValue(AnimatorProperty, OnAnimatorChanged); AddToClassList(BaseField.ussClassName); AddToClassList(BaseField.alignedFieldUssClassName); } private void OnAnimatorChanged(SerializedProperty property) { if (property.TryGetValue(out Animator animator)) { choices = new List(GetParameterNames(animator)); } OnAnimatorChanged(animator); } protected virtual void OnAnimatorChanged(Animator animator) { } protected abstract void OnValueChanged(ChangeEvent evt); private static string[] GetParameterNames(Animator animator) { var parameters = animator.parameters; var len = parameters.Length; var names = new string[len]; for (int i = 0; i < len; i++) { names[i] = parameters[i].name; } return names; } public void Dispose() { this.UnregisterValueChangedCallback(OnValueChanged); } } public class AnimatorIntParameterElement : AnimatorParameterElement { public AnimatorIntParameterElement(SerializedProperty property, string animatorName) : base(property, animatorName) { } protected override void OnAnimatorChanged(Animator animator) { for (int i = 0; i < animator.parameterCount; i++) { if (animator.GetParameter(i).nameHash == Property.intValue) { index = i; return; } } index = 0; } protected override void OnValueChanged(ChangeEvent evt) { Property.intValue = Animator.StringToHash(evt.newValue); Property.serializedObject.ApplyModifiedProperties(); Property.serializedObject.Update(); } } public class AnimatorStringParameterElement : AnimatorParameterElement { public AnimatorStringParameterElement(SerializedProperty property, string animatorName) : base(property, animatorName) { } protected override void OnAnimatorChanged(Animator animator) { for (int i = 0; i < animator.parameterCount; i++) { if (animator.GetParameter(i).name == Property.stringValue) { index = i; return; } } index = 0; } protected override void OnValueChanged(ChangeEvent evt) { Property.stringValue = evt.newValue; Property.serializedObject.ApplyModifiedProperties(); } } } }