canto/Assets/Scripts/Editor/PropertyDrawers/AnimatorParamPropertyDrawer.cs
2025-08-14 19:11:32 -04:00

135 lines
4.7 KiB
C#

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<string>, 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<int>.ussClassName);
AddToClassList(BaseField<int>.alignedFieldUssClassName);
}
private void OnAnimatorChanged(SerializedProperty property)
{
if (property.TryGetValue(out Animator animator))
{
choices = new List<string>(GetParameterNames(animator));
}
OnAnimatorChanged(animator);
}
protected virtual void OnAnimatorChanged(Animator animator) { }
protected abstract void OnValueChanged(ChangeEvent<string> 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<string> 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<string> evt)
{
Property.stringValue = evt.newValue;
Property.serializedObject.ApplyModifiedProperties();
}
}
}
}