206 lines
8.9 KiB
C#
206 lines
8.9 KiB
C#
using System;
|
|
using KitsuneCafe.System.Attributes;
|
|
using UnityEditor;
|
|
using UnityEditor.UIElements;
|
|
using UnityEngine.UIElements;
|
|
using Debug = UnityEngine.Debug;
|
|
|
|
[CustomPropertyDrawer(typeof(ConditionalDisplayAttribute), true)]
|
|
public class ConditionalDisplayPropertyDrawer : PropertyDrawer
|
|
{
|
|
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
|
{
|
|
var attribute = this.attribute as ConditionalDisplayAttribute;
|
|
var properties = GetPropertiesFrom(property, attribute.Properties);
|
|
return new SimpleConditionPropertyField(properties, attribute, property);
|
|
}
|
|
|
|
private SerializedProperty[] GetPropertiesFrom(SerializedProperty property, string[] propertyNames)
|
|
{
|
|
var len = propertyNames.Length;
|
|
var properties = new SerializedProperty[len];
|
|
var path = property.propertyPath;
|
|
var index = path.LastIndexOf('.');
|
|
var obj = property.serializedObject;
|
|
|
|
if (index > -1)
|
|
{
|
|
var parentPath = path[..path.LastIndexOf('.')];
|
|
var parent = obj.FindProperty(parentPath);
|
|
for (int i = 0; i < len; i++)
|
|
{
|
|
properties[i] = parent.FindPropertyRelative(propertyNames[i]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < len; i++)
|
|
{
|
|
properties[i] = obj.FindProperty(propertyNames[i]);
|
|
}
|
|
}
|
|
|
|
return properties;
|
|
}
|
|
|
|
public abstract class ConditionalPropertyField : PropertyField
|
|
{
|
|
protected readonly SerializedProperty[] properties;
|
|
protected readonly ConditionalDisplayAttribute attribute;
|
|
|
|
public ConditionalPropertyField(SerializedProperty[] properties, ConditionalDisplayAttribute attribute, SerializedProperty property) : base(property)
|
|
{
|
|
this.properties = properties;
|
|
this.attribute = attribute;
|
|
TrackProperties(properties);
|
|
}
|
|
|
|
public ConditionalPropertyField(SerializedProperty[] properties, ConditionalDisplayAttribute attribute, SerializedProperty property, string label) : base(property, label)
|
|
{
|
|
this.properties = properties;
|
|
this.attribute = attribute;
|
|
TrackProperties(properties);
|
|
}
|
|
|
|
private void TrackProperties(SerializedProperty[] properties)
|
|
{
|
|
var len = properties.Length;
|
|
for (int i = 0; i < len; i++)
|
|
{
|
|
var property = properties[i];
|
|
OnTrackedValueChanged(property);
|
|
this.TrackPropertyValue(property, OnTrackedValueChanged);
|
|
}
|
|
}
|
|
|
|
protected abstract void OnTrackedValueChanged(SerializedProperty property);
|
|
}
|
|
|
|
public class SimpleConditionPropertyField : ConditionalPropertyField
|
|
{
|
|
public SimpleConditionPropertyField(SerializedProperty[] properties, ConditionalDisplayAttribute attribute, SerializedProperty property) : base(properties, attribute, property)
|
|
{
|
|
}
|
|
|
|
public SimpleConditionPropertyField(SerializedProperty[] properties, ConditionalDisplayAttribute attribute, SerializedProperty property, string label) : base(properties, attribute, property, label)
|
|
{
|
|
}
|
|
|
|
protected override void OnTrackedValueChanged(SerializedProperty property)
|
|
{
|
|
var value = (attribute.LogicalOperator, attribute.ComparisonOperator) switch
|
|
{
|
|
(LogicalOperator.Or, ComparisonOperator.Equal) => true,
|
|
(LogicalOperator.And, ComparisonOperator.NotEqual) => true,
|
|
_ => false
|
|
};
|
|
|
|
var display = attribute.LogicalOperator switch
|
|
{
|
|
LogicalOperator.And => All(properties, attribute.Value, attribute.ComparisonOperator),
|
|
LogicalOperator.Or => Any(properties, attribute.Value, attribute.ComparisonOperator),
|
|
};
|
|
|
|
DisplayElement(display);
|
|
}
|
|
|
|
protected bool Compare<T>(T self, T other, ComparisonOperator op) where T : IComparable<T>
|
|
{
|
|
var value = self.CompareTo(other);
|
|
|
|
return op switch
|
|
{
|
|
ComparisonOperator.Less => value < 0,
|
|
ComparisonOperator.Equal => value == 0,
|
|
ComparisonOperator.LessEqual => value <= 0,
|
|
ComparisonOperator.Greater => value > 0,
|
|
ComparisonOperator.NotEqual => value != 0,
|
|
ComparisonOperator.GreaterEqual => value >= 0,
|
|
_ => throw new NotImplementedException(),
|
|
};
|
|
}
|
|
|
|
protected bool Compare<T>(T self, object other, ComparisonOperator op) where T : IComparable<T>
|
|
{
|
|
return other is T otherValue && Compare(self, otherValue, op);
|
|
}
|
|
|
|
protected bool Compare(SerializedProperty self, object other, ComparisonOperator op)
|
|
{
|
|
return self.propertyType switch
|
|
{
|
|
SerializedPropertyType.Generic => false,
|
|
SerializedPropertyType.Float or SerializedPropertyType.Integer => self.numericType switch
|
|
{
|
|
SerializedPropertyNumericType.Unknown => false,
|
|
SerializedPropertyNumericType.UInt8 or SerializedPropertyNumericType.UInt16 or SerializedPropertyNumericType.UInt32 => Compare(self.uintValue, other, op),
|
|
SerializedPropertyNumericType.Int8 or SerializedPropertyNumericType.Int16 or SerializedPropertyNumericType.Int32 => Compare(self.intValue, other, op),
|
|
SerializedPropertyNumericType.Int64 => Compare(self.longValue, other, op),
|
|
SerializedPropertyNumericType.UInt64 => Compare(self.ulongValue, other, op),
|
|
SerializedPropertyNumericType.Float => Compare(self.floatValue, other, op),
|
|
SerializedPropertyNumericType.Double => Compare(self.doubleValue, other, op),
|
|
_ => false,
|
|
},
|
|
SerializedPropertyType.Boolean => Compare(self.boolValue, other, op),
|
|
SerializedPropertyType.String => Compare(self.stringValue, other, op),
|
|
// SerializedPropertyType.Color => Compare(self.colorValue, other, op),
|
|
SerializedPropertyType.ObjectReference => false,
|
|
SerializedPropertyType.LayerMask => Compare(self.intValue, other, op),
|
|
SerializedPropertyType.Enum => Compare(self.intValue, other, op),
|
|
// SerializedPropertyType.Vector2 => Compare(self.vector2Value, other, op),
|
|
// SerializedPropertyType.Vector3 => Compare(self.vector3Value, other, op),
|
|
// SerializedPropertyType.Vector4 => Compare(self.vector4Value, other, op),
|
|
// SerializedPropertyType.Rect => Compare(self.rectValue, other, op),
|
|
SerializedPropertyType.ArraySize => Compare(self.arraySize, other, op),
|
|
SerializedPropertyType.Character => Compare(self.stringValue, other, op),
|
|
// SerializedPropertyType.AnimationCurve => Compare(self.animationCurveValue, other, op),
|
|
// SerializedPropertyType.Bounds => Compare(self.boundsValue, other, op),
|
|
// SerializedPropertyType.Gradient => Compare(self.gradientValue, other, op),
|
|
// SerializedPropertyType.Quaternion => Compare(self.quaternionValue, other, op),
|
|
SerializedPropertyType.ExposedReference => false,
|
|
// SerializedPropertyType.FixedBufferSize => Compare(self.fixedBufferSize, other, op),
|
|
// SerializedPropertyType.Vector2Int => Compare(self.vector2IntValue, other, op),
|
|
// SerializedPropertyType.Vector3Int => Compare(self.vector3IntValue, other, op),
|
|
// SerializedPropertyType.RectInt => Compare(self.rectIntValue, other, op),
|
|
// SerializedPropertyType.BoundsInt => Compare(self.boundsIntValue, other, op),
|
|
SerializedPropertyType.ManagedReference => false,
|
|
SerializedPropertyType.Hash128 => Compare(self.hash128Value, other, op),
|
|
SerializedPropertyType.RenderingLayerMask => Compare(self.intValue, other, op),
|
|
_ => false,
|
|
};
|
|
}
|
|
|
|
protected bool All(SerializedProperty[] properties, object value, ComparisonOperator op)
|
|
{
|
|
foreach (var prop in properties)
|
|
{
|
|
if (!Compare(prop, value, op))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
protected bool Any(SerializedProperty[] properties, object value, ComparisonOperator op)
|
|
{
|
|
foreach (var prop in properties)
|
|
{
|
|
if (Compare(prop, value, op))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private void DisplayElement(bool displayed)
|
|
{
|
|
style.display = displayed ? DisplayStyle.Flex : DisplayStyle.None;
|
|
}
|
|
}
|
|
}
|
|
|
|
|