136 lines
3.8 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|