Files
test/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ValueButtonsDrawer.cs
T

162 lines
5.2 KiB
C#

using UnityEditor;
using UnityEngine.UIElements;
#if UNITY_6000_0_OR_NEWER
using System;
using System.Linq;
using UnityEngine;
using System.Reflection;
using System.Collections;
using UnityEditor.UIElements;
using System.Collections.Generic;
using EditorAttributes.Editor.Utility;
#endif
namespace EditorAttributes.Editor
{
[CustomPropertyDrawer(typeof(ValueButtonsAttribute))]
public class ValueButtonsDrawer : PropertyDrawerBase
{
#if !UNITY_6000_0_OR_NEWER
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
var root = new VisualElement();
root.Add(new HelpBox("The <b>ValueButtons Attribute</b> is only available in <b>Unity 6 and above</b>, use the <b>SelectionButtons Attribute</b> for the same functionality", HelpBoxMessageType.Warning));
return root;
}
#else
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
var valueButtonsAttribute = attribute as ValueButtonsAttribute;
var root = new VisualElement();
var errorBox = new HelpBox();
var collectionInfo = ReflectionUtility.GetValidMemberInfo(valueButtonsAttribute.CollectionName, property);
string[] propertyValues = ConvertCollectionValuesToStrings(valueButtonsAttribute.CollectionName, property, collectionInfo, errorBox).ToArray();
string[] displayValues = GetDisplayValues(collectionInfo, valueButtonsAttribute, property, propertyValues.ToList());
if (!IsCollectionValid(displayValues))
{
errorBox.text = "The provided collection is empty";
DisplayErrorBox(root, errorBox);
return root;
}
int buttonsValueIndex = Array.IndexOf(propertyValues, GetPropertyValueAsString(property));
var valueButtons = DrawButtons(buttonsValueIndex, displayValues, valueButtonsAttribute, (value) =>
{
if (valueButtonsAttribute.DisplayNames != null || IsDictionary(collectionInfo, property, out _))
{
if (value >= 0 && value < propertyValues.Length)
SetPropertyValueFromString(propertyValues[value], property);
}
else
{
if (value >= 0 && value < propertyValues.Length)
SetPropertyValueFromString(propertyValues[value], property);
}
});
valueButtons.TrackPropertyValue(property, (trackedProperty) =>
{
if (propertyValues.Contains(trackedProperty.boxedValue.ToString()))
{
int propertyValueIndex = Array.IndexOf(propertyValues, GetPropertyValueAsString(trackedProperty));
bool[] selectionValues = new bool[propertyValues.Length];
selectionValues[propertyValueIndex] = true;
valueButtons.SetValueWithoutNotify(ToggleButtonGroupState.CreateFromOptions(selectionValues));
}
else
{
Debug.LogWarning($"The value <b>{trackedProperty.boxedValue}</b> set to the <b>{trackedProperty.name}</b> variable is not a value available in the button selection", trackedProperty.serializedObject.targetObject);
}
});
AddPropertyContextMenu(valueButtons, property);
root.Add(valueButtons);
DisplayErrorBox(root, errorBox);
return root;
}
private ToggleButtonGroup DrawButtons(int buttonsValue, string[] valueLabels, ValueButtonsAttribute selectionButtonsAttribute, Action<int> onValueChanged)
{
var activeButtonList = new List<bool>();
var buttonGroup = new ToggleButtonGroup(selectionButtonsAttribute.ShowLabel ? preferredLabel : string.Empty);
foreach (string label in valueLabels)
{
var toggle = new Button
{
text = label,
style = { height = selectionButtonsAttribute.ButtonsHeight }
};
activeButtonList.Add(false);
buttonGroup.Add(toggle);
}
activeButtonList[buttonsValue == -1 ? 0 : buttonsValue] = true;
buttonGroup.SetValueWithoutNotify(ToggleButtonGroupState.CreateFromOptions(activeButtonList));
buttonGroup.RegisterValueChangedCallback((value) => onValueChanged.Invoke(value.newValue.GetActiveOptions(ConvertBoolsToSpan(activeButtonList))[0]));
return buttonGroup;
}
private static Span<int> ConvertBoolsToSpan(List<bool> boolList)
{
var intArray = new int[boolList.Count];
for (int i = 0; i < boolList.Count; i++)
intArray[i] = boolList[i] ? 1 : 0;
return new Span<int>(intArray);
}
private string[] GetDisplayValues(MemberInfo collectionInfo, ValueButtonsAttribute valueButtonsAttribute, SerializedProperty serializedProperty, List<string> propertyValues)
{
var displayStrings = new List<string>();
if (valueButtonsAttribute.DisplayNames == null)
{
if (IsDictionary(collectionInfo, serializedProperty, out IDictionary dictionary))
{
foreach (DictionaryEntry item in dictionary)
displayStrings.Add(item.Key == null ? "NULL" : item.Key.ToString());
}
else
{
displayStrings = propertyValues;
}
}
else
{
displayStrings = valueButtonsAttribute.DisplayNames.ToList();
}
return displayStrings.ToArray();
}
private bool IsDictionary(MemberInfo collectionInfo, SerializedProperty serializedProperty, out IDictionary dictionary)
{
var collectionValue = ReflectionUtility.GetMemberInfoValue(collectionInfo, serializedProperty);
dictionary = collectionValue as IDictionary;
return collectionValue is IDictionary;
}
#endif
}
}