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(), }; } /// /// Return SerializedProperty by it's name if it exists, it works for nested objects and arrays /// /// /// /// 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; } } }