First commit for private source control. Older commits available on Github.
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user