You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
5.2 KiB
177 lines
5.2 KiB
using UnityEngine; |
|
using UnityEditor; |
|
using System.Collections; |
|
using System.Reflection; |
|
using System; |
|
using System.Collections.Generic; |
|
|
|
namespace NaughtyAttributes.Editor |
|
{ |
|
[CustomPropertyDrawer(typeof(DropdownAttribute))] |
|
public class DropdownPropertyDrawer : PropertyDrawerBase |
|
{ |
|
protected override float GetPropertyHeight_Internal(SerializedProperty property, GUIContent label) |
|
{ |
|
DropdownAttribute dropdownAttribute = (DropdownAttribute)attribute; |
|
object values = GetValues(property, dropdownAttribute.ValuesName); |
|
FieldInfo fieldInfo = ReflectionUtility.GetField(PropertyUtility.GetTargetObjectWithProperty(property), property.name); |
|
|
|
float propertyHeight = AreValuesValid(values, fieldInfo) |
|
? GetPropertyHeight(property) |
|
: GetPropertyHeight(property) + GetHelpBoxHeight(); |
|
|
|
return propertyHeight; |
|
} |
|
|
|
protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label) |
|
{ |
|
EditorGUI.BeginProperty(rect, label, property); |
|
|
|
DropdownAttribute dropdownAttribute = (DropdownAttribute)attribute; |
|
object target = PropertyUtility.GetTargetObjectWithProperty(property); |
|
|
|
object valuesObject = GetValues(property, dropdownAttribute.ValuesName); |
|
FieldInfo dropdownField = ReflectionUtility.GetField(target, property.name); |
|
|
|
if (AreValuesValid(valuesObject, dropdownField)) |
|
{ |
|
if (valuesObject is IList && dropdownField.FieldType == GetElementType(valuesObject)) |
|
{ |
|
// Selected value |
|
object selectedValue = dropdownField.GetValue(target); |
|
|
|
// Values and display options |
|
IList valuesList = (IList)valuesObject; |
|
object[] values = new object[valuesList.Count]; |
|
string[] displayOptions = new string[valuesList.Count]; |
|
|
|
for (int i = 0; i < values.Length; i++) |
|
{ |
|
object value = valuesList[i]; |
|
values[i] = value; |
|
displayOptions[i] = value == null ? "<null>" : value.ToString(); |
|
} |
|
|
|
// Selected value index |
|
int selectedValueIndex = Array.IndexOf(values, selectedValue); |
|
if (selectedValueIndex < 0) |
|
{ |
|
selectedValueIndex = 0; |
|
} |
|
|
|
NaughtyEditorGUI.Dropdown( |
|
rect, property.serializedObject, target, dropdownField, label.text, selectedValueIndex, values, displayOptions); |
|
} |
|
else if (valuesObject is IDropdownList) |
|
{ |
|
// Current value |
|
object selectedValue = dropdownField.GetValue(target); |
|
|
|
// Current value index, values and display options |
|
int index = -1; |
|
int selectedValueIndex = -1; |
|
List<object> values = new List<object>(); |
|
List<string> displayOptions = new List<string>(); |
|
IDropdownList dropdown = (IDropdownList)valuesObject; |
|
|
|
using (IEnumerator<KeyValuePair<string, object>> dropdownEnumerator = dropdown.GetEnumerator()) |
|
{ |
|
while (dropdownEnumerator.MoveNext()) |
|
{ |
|
index++; |
|
|
|
KeyValuePair<string, object> current = dropdownEnumerator.Current; |
|
if (current.Value?.Equals(selectedValue) == true) |
|
{ |
|
selectedValueIndex = index; |
|
} |
|
|
|
values.Add(current.Value); |
|
|
|
if (current.Key == null) |
|
{ |
|
displayOptions.Add("<null>"); |
|
} |
|
else if (string.IsNullOrWhiteSpace(current.Key)) |
|
{ |
|
displayOptions.Add("<empty>"); |
|
} |
|
else |
|
{ |
|
displayOptions.Add(current.Key); |
|
} |
|
} |
|
} |
|
|
|
if (selectedValueIndex < 0) |
|
{ |
|
selectedValueIndex = 0; |
|
} |
|
|
|
NaughtyEditorGUI.Dropdown( |
|
rect, property.serializedObject, target, dropdownField, label.text, selectedValueIndex, values.ToArray(), displayOptions.ToArray()); |
|
} |
|
} |
|
else |
|
{ |
|
string message = string.Format("Invalid values with name '{0}' provided to '{1}'. Either the values name is incorrect or the types of the target field and the values field/property/method don't match", |
|
dropdownAttribute.ValuesName, dropdownAttribute.GetType().Name); |
|
|
|
DrawDefaultPropertyAndHelpBox(rect, property, message, MessageType.Warning); |
|
} |
|
|
|
EditorGUI.EndProperty(); |
|
} |
|
|
|
private object GetValues(SerializedProperty property, string valuesName) |
|
{ |
|
object target = PropertyUtility.GetTargetObjectWithProperty(property); |
|
|
|
FieldInfo valuesFieldInfo = ReflectionUtility.GetField(target, valuesName); |
|
if (valuesFieldInfo != null) |
|
{ |
|
return valuesFieldInfo.GetValue(target); |
|
} |
|
|
|
PropertyInfo valuesPropertyInfo = ReflectionUtility.GetProperty(target, valuesName); |
|
if (valuesPropertyInfo != null) |
|
{ |
|
return valuesPropertyInfo.GetValue(target); |
|
} |
|
|
|
MethodInfo methodValuesInfo = ReflectionUtility.GetMethod(target, valuesName); |
|
if (methodValuesInfo != null && |
|
methodValuesInfo.ReturnType != typeof(void) && |
|
methodValuesInfo.GetParameters().Length == 0) |
|
{ |
|
return methodValuesInfo.Invoke(target, null); |
|
} |
|
|
|
return null; |
|
} |
|
|
|
private bool AreValuesValid(object values, FieldInfo dropdownField) |
|
{ |
|
if (values == null || dropdownField == null) |
|
{ |
|
return false; |
|
} |
|
|
|
if ((values is IList && dropdownField.FieldType == GetElementType(values)) || |
|
(values is IDropdownList)) |
|
{ |
|
return true; |
|
} |
|
|
|
return false; |
|
} |
|
|
|
private Type GetElementType(object values) |
|
{ |
|
Type valuesType = values.GetType(); |
|
Type elementType = ReflectionUtility.GetListElementType(valuesType); |
|
|
|
return elementType; |
|
} |
|
} |
|
} |