canto/Assets/Scripts/Editor/Drawers/DrawIfPropertyDrawer.cs
2025-10-02 15:28:03 -04:00

136 lines
3.8 KiB
C#

using System;
using System.Collections;
using KitsuneCafe.Sys.Attributes;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace KitsuneCafe.Editor
{
public abstract class ConditionalElement : VisualElement
{
protected SerializedProperty property;
protected SerializedProperty comparedProperty;
public ConditionalElement(SerializedProperty property, SerializedProperty comparedProperty)
{
this.property = property;
this.comparedProperty = comparedProperty;
if (property.propertyType == SerializedPropertyType.Generic)
{
IEnumerator children = property.GetEnumerator();
while (children.MoveNext())
{
Add(new PropertyField(children.Current as SerializedProperty));
}
}
else
{
Add(new PropertyField(property));
}
this.TrackPropertyValue(comparedProperty, OnPropertyValueChanged);
schedule.Execute(() => OnPropertyValueChanged(comparedProperty));
}
protected void OnPropertyValueChanged(SerializedProperty property)
{
style.display = ShouldRender(property) ? DisplayStyle.Flex : DisplayStyle.None;
}
protected abstract bool ShouldRender(SerializedProperty property);
}
public class ConditionalBool : ConditionalElement
{
private readonly bool value;
public ConditionalBool(
SerializedProperty property,
SerializedProperty comparedProperty,
bool value
) : base(property, comparedProperty)
{
this.value = value;
}
protected override bool ShouldRender(SerializedProperty property)
{
return property.boolValue == value;
}
}
public class ConditionalInt : ConditionalElement
{
private readonly int value;
private readonly bool isFlagEnum;
public ConditionalInt(
SerializedProperty property,
SerializedProperty comparedProperty,
int value,
bool isFlagEnum = false
) : base(property, comparedProperty)
{
this.value = value;
this.isFlagEnum = isFlagEnum;
}
protected override bool ShouldRender(SerializedProperty property)
{
return isFlagEnum switch
{
true => (property.intValue & value) == value,
false => property.intValue == value
};
}
}
[CustomPropertyDrawer(typeof(DrawIfAttribute))]
public class DrawIfPropertyDrawer : PropertyDrawer
{
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
var drawIf = attribute as DrawIfAttribute;
var comparedField = TryToFindSerializableProperty(drawIf.ComparedPropertyName, property);
return comparedField.type switch
{
"bool" => new ConditionalBool(property, comparedField, (bool)drawIf.ComparedValue),
"Enum" or "int" => new ConditionalInt(
property,
comparedField,
(int)drawIf.ComparedValue,
drawIf.IsEnumWithFlags
),
_ => throw new NotImplementedException(),
};
}
/// <summary>
/// Return SerializedProperty by it's name if it exists, it works for nested objects and arrays
/// </summary>
/// <param name="propertyName"></param>
/// <param name="property"></param>
/// <returns></returns>
private SerializedProperty TryToFindSerializableProperty(string propertyName, SerializedProperty property)
{
var serializedProperty = property.serializedObject.FindProperty(propertyName);
if (serializedProperty == null)
{
string propertyPath = property.propertyPath;
int idx = propertyPath.LastIndexOf('.');
if (idx != -1)
{
propertyPath = propertyPath[..idx];
return property.serializedObject.FindProperty(propertyPath).FindPropertyRelative(propertyName);
}
}
return serializedProperty;
}
}
}