public override bool CanDrawProperty(SerializedProperty property) { ShowIfAttribute showIfAttribute = PropertyUtility.GetAttribute <ShowIfAttribute>(property); UnityEngine.Object target = PropertyUtility.GetTargetObject(property); List <bool> conditionValues = new List <bool>(); foreach (var condition in showIfAttribute.Conditions) { FieldInfo conditionField = ReflectionUtility.GetField(target, condition); if (conditionField?.FieldType == typeof(bool)) { conditionValues.Add((bool)conditionField.GetValue(target)); } MethodInfo conditionMethod = ReflectionUtility.GetMethod(target, condition); if (conditionMethod?.ReturnType == typeof(bool) && conditionMethod.GetParameters().Length == 0) { conditionValues.Add((bool)conditionMethod.Invoke(target, null)); } PropertyInfo conditionProperty = ReflectionUtility.GetProperty(target, condition); if (conditionProperty?.PropertyType == typeof(bool)) { conditionValues.Add((bool)conditionProperty.GetValue(target)); } } if (conditionValues.Count > 0) { bool draw; if (showIfAttribute.ConditionOperator == ConditionOperator.And) { draw = true; foreach (var value in conditionValues) { draw = draw && value; } } else { draw = false; foreach (var value in conditionValues) { draw = draw || value; } } if (showIfAttribute.Reversed) { draw = !draw; } return(draw); } else { string warning = showIfAttribute.GetType().Name + " needs a valid boolean condition field or method name to work"; EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, context: target); return(true); } }
public static T[] GetAttributes <T>(SerializedProperty property) where T : Attribute { FieldInfo fieldInfo = ReflectionUtility.GetField(GetTargetObject(property), property.name); return((T[])fieldInfo.GetCustomAttributes(typeof(T), true)); }
public override void DrawProperty(SerializedProperty property) { EditorDrawUtility.DrawHeader(property); DropdownAttribute dropdownAttribute = PropertyUtility.GetAttribute <DropdownAttribute>(property); UnityEngine.Object target = PropertyUtility.GetTargetObject(property); FieldInfo fieldInfo = ReflectionUtility.GetField(target, property.name); FieldInfo valuesFieldInfo = ReflectionUtility.GetField(target, dropdownAttribute.ValuesFieldName); if (valuesFieldInfo == null) { this.DrawWarningBox(string.Format("{0} cannot find a values field with name \"{1}\"", dropdownAttribute.GetType().Name, dropdownAttribute.ValuesFieldName)); EditorGUILayout.PropertyField(property, true); } else if (valuesFieldInfo.GetValue(target) is IList && fieldInfo.FieldType == this.GetElementType(valuesFieldInfo)) { // Selected value object selectedValue = fieldInfo.GetValue(target); // Values and display options IList valuesList = (IList)valuesFieldInfo.GetValue(target); 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.ToString(); } // Selected value index int selectedValueIndex = Array.IndexOf(values, selectedValue); if (selectedValueIndex < 0) { selectedValueIndex = 0; } // Draw the dropdown this.DrawDropdown(target, fieldInfo, property.displayName, selectedValueIndex, values, displayOptions); } else if (valuesFieldInfo.GetValue(target) is IDropdownList) { // Current value object selectedValue = fieldInfo.GetValue(target); // Current value index, values and display options IDropdownList dropdown = (IDropdownList)valuesFieldInfo.GetValue(target); IEnumerator <KeyValuePair <string, object> > dropdownEnumerator = dropdown.GetEnumerator(); int index = -1; int selectedValueIndex = -1; List <object> values = new List <object>(); List <string> displayOptions = new List <string>(); while (dropdownEnumerator.MoveNext()) { index++; KeyValuePair <string, object> current = dropdownEnumerator.Current; if (current.Value.Equals(selectedValue)) { selectedValueIndex = index; } values.Add(current.Value); displayOptions.Add(current.Key); } if (selectedValueIndex < 0) { selectedValueIndex = 0; } // Draw the dropdown this.DrawDropdown(target, fieldInfo, property.displayName, selectedValueIndex, values.ToArray(), displayOptions.ToArray()); } else { this.DrawWarningBox(typeof(DropdownAttribute).Name + " works only when the type of the field is equal to the element type of the array"); EditorGUILayout.PropertyField(property, true); } }
private void OnEnable() { script = serializedObject.FindProperty("m_Script"); // Cache serialized fields fields = ReflectionUtility.GetAllFields(target, f => serializedObject.FindProperty(f.Name) != null); // If there are no NaughtyAttributes use default inspector if (fields.All(f => f.GetCustomAttributes(typeof(NaughtyAttribute), true).Length == 0)) { useDefaultInspector = true; } else { useDefaultInspector = false; // Cache grouped fields groupedFields = new HashSet <FieldInfo>( fields.Where(f => f.GetCustomAttributes(typeof(GroupAttribute), true).Length > 0)); // Cache grouped fields by group name groupedFieldsByGroupName = new Dictionary <string, List <FieldInfo> >(); foreach (var groupedField in groupedFields) { var groupName = (groupedField.GetCustomAttributes(typeof(GroupAttribute), true)[0] as GroupAttribute).Name; if (groupedFieldsByGroupName.ContainsKey(groupName)) { groupedFieldsByGroupName[groupName].Add(groupedField); } else { groupedFieldsByGroupName[groupName] = new List <FieldInfo> { groupedField } }; } // Cache serialized properties by field name serializedPropertiesByFieldName = new Dictionary <string, SerializedProperty>(); foreach (var field in fields) { serializedPropertiesByFieldName[field.Name] = serializedObject.FindProperty(field.Name); } } // Cache non-serialized fields nonSerializedFields = ReflectionUtility.GetAllFields( target, f => f.GetCustomAttributes(typeof(DrawerAttribute), true).Length > 0 && serializedObject.FindProperty(f.Name) == null); // Cache the native properties nativeProperties = ReflectionUtility.GetAllProperties( target, p => p.GetCustomAttributes(typeof(DrawerAttribute), true).Length > 0); // Cache methods with DrawerAttribute methods = ReflectionUtility.GetAllMethods( target, m => m.GetCustomAttributes(typeof(DrawerAttribute), true).Length > 0); }
protected virtual void OnEnable() { try { this.script = this.serializedObject.FindProperty("m_Script"); } //catch (Exception) { return; } catch (Exception e) { Debug.LogException(e); return; } // Cache serialized fields this.fields = ReflectionUtility.GetAllFields(this.target, f => this.serializedObject.FindProperty(f.Name) != null); // If there are no NaughtyAttributes use default inspector if (this.fields.All(f => f.GetCustomAttributes(typeof(NaughtyAttribute), true).Length == 0)) { this.useDefaultInspector = true; } else { this.useDefaultInspector = false; // Cache grouped fields this.groupedFields = new HashSet <FieldInfo>(this.fields.Where(f => f.GetCustomAttributes(typeof(GroupAttribute), true).Length > 0)); // Cache grouped fields by group name this.groupedFieldsByGroupName = new Dictionary <string, List <FieldInfo> >(); foreach (var groupedField in this.groupedFields) { string groupName = (groupedField.GetCustomAttributes(typeof(GroupAttribute), true)[0] as GroupAttribute).Name; if (this.groupedFieldsByGroupName.ContainsKey(groupName)) { this.groupedFieldsByGroupName[groupName].Add(groupedField); } else { this.groupedFieldsByGroupName[groupName] = new List <FieldInfo>() { groupedField } }; } // groupedState = new Dictionary <string, bool>(); UpdateGroupState(); // Cache serialized properties by field name this.serializedPropertiesByFieldName = new Dictionary <string, SerializedProperty>(); foreach (var field in this.fields) { this.serializedPropertiesByFieldName[field.Name] = this.serializedObject.FindProperty(field.Name); } } // Cache non-serialized fields this.nonSerializedFields = ReflectionUtility.GetAllFields( this.target, f => f.GetCustomAttributes(typeof(DrawerAttribute), true).Length > 0 && this.serializedObject.FindProperty(f.Name) == null); // Cache the native properties this.nativeProperties = ReflectionUtility.GetAllProperties( this.target, p => p.GetCustomAttributes(typeof(DrawerAttribute), true).Length > 0); // Cache methods with DrawerAttribute this.methods = ReflectionUtility.GetAllMethods( this.target, m => m.GetCustomAttributes(typeof(DrawerAttribute), true).Length > 0); }
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 static AnimatorController GetAnimatorController(SerializedProperty property, string animatorName) { object target = PropertyUtility.GetTargetObjectWithProperty(property); FieldInfo animatorFieldInfo = ReflectionUtility.GetField(target, animatorName); if (animatorFieldInfo != null) { if (animatorFieldInfo.FieldType == typeof(Animator)) { Animator animator = animatorFieldInfo.GetValue(target) as Animator; if (animator != null) { AnimatorController animatorController = animator.runtimeAnimatorController as AnimatorController; return(animatorController); } } else if (animatorFieldInfo.FieldType == typeof(AnimatorController)) { return(animatorFieldInfo.GetValue(target) as AnimatorController); } } PropertyInfo animatorPropertyInfo = ReflectionUtility.GetProperty(target, animatorName); if (animatorPropertyInfo != null) { if (animatorPropertyInfo.PropertyType == typeof(Animator)) { Animator animator = animatorPropertyInfo.GetValue(target) as Animator; if (animator != null) { AnimatorController animatorController = animator.runtimeAnimatorController as AnimatorController; return(animatorController); } } else if (animatorPropertyInfo.PropertyType == typeof(AnimatorController)) { return(animatorPropertyInfo.GetValue(target) as AnimatorController); } } MethodInfo animatorGetterMethodInfo = ReflectionUtility.GetMethod(target, animatorName); if (animatorGetterMethodInfo != null && animatorGetterMethodInfo.GetParameters().Length == 0) { if (animatorGetterMethodInfo.ReturnType == typeof(Animator)) { Animator animator = animatorGetterMethodInfo.Invoke(target, null) as Animator; if (animator != null) { AnimatorController animatorController = animator.runtimeAnimatorController as AnimatorController; return(animatorController); } } else if (animatorGetterMethodInfo.ReturnType == typeof(AnimatorController)) { return(animatorGetterMethodInfo.Invoke(target, null) as AnimatorController); } } return(null); }
public override void DrawProperty(SerializedProperty property) { var enableIfAttribute = PropertyUtility.GetAttribute <EnableIfAttribute>(property); var target = PropertyUtility.GetTargetObject(property); var conditionValues = new List <bool>(); foreach (var condition in enableIfAttribute.Conditions) { var conditionField = ReflectionUtility.GetField(target, condition); if (conditionField != null && conditionField.FieldType == typeof(bool)) { conditionValues.Add((bool)conditionField.GetValue(target)); } var conditionMethod = ReflectionUtility.GetMethod(target, condition); if (conditionMethod != null && conditionMethod.ReturnType == typeof(bool) && conditionMethod.GetParameters().Length == 0) { conditionValues.Add((bool)conditionMethod.Invoke(target, null)); } } if (conditionValues.Count > 0) { bool enabled; if (enableIfAttribute.ConditionOperator == ConditionOperator.And) { enabled = true; foreach (var value in conditionValues) { enabled = enabled && value; } } else { enabled = false; foreach (var value in conditionValues) { enabled = enabled || value; } } if (enableIfAttribute.Reversed) { enabled = !enabled; } GUI.enabled = enabled; EditorDrawUtility.DrawPropertyField(property); GUI.enabled = true; } else { var warning = enableIfAttribute.GetType().Name + " needs a valid boolean condition field or method name to work"; EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, target); } }
private void OnEnable() { try { this.script = this.serializedObject.FindProperty("m_Script"); } catch { // ignore. Unity Bug causes NPE deep inside the unity classes. this.useDefaultInspector = true; return; } // Cache serialized fields this.fields = ReflectionUtility.GetAllFieldsEfficiently(this.target, filterFieldsDelegate, this.fields); // Cache serialized properties by field name this.serializedPropertiesByFieldName.Clear(); foreach (var field in this.fields) { this.serializedPropertiesByFieldName[field.Name] = this.serializedObject.FindProperty(field.Name); } // If there are no NaughtyAttributes use default inspector if (this.fields.All(f => f.GetCustomAttribute <NaughtyAttribute>(true) == null)) { this.useDefaultInspector = true; } else { this.useDefaultInspector = false; // Cache grouped fields this.groupedFields.Clear(); foreach (var fi in fields) { if (fi.GetCustomAttribute <GroupAttribute>(true) != null) { this.groupedFields.Add(fi); } } // Cache grouped fields by group name groupedFieldsByGroupName.Clear(); foreach (var groupedField in this.groupedFields) { string groupName = (groupedField.GetCustomAttribute <GroupAttribute>(true)).Name; if (this.groupedFieldsByGroupName.TryGetValue(groupName, out var list)) { list.Add(groupedField); } else { this.groupedFieldsByGroupName[groupName] = new List <FieldInfo>() { groupedField }; } } } this.nonSerializedFields = ReflectionUtility.GetAllFieldsEfficiently(this.target, NonSerializedFieldsFilter, nonSerializedFields); // Cache the native properties this.nativeProperties = ReflectionUtility.GetAllPropertiesEfficiently( this.target, p => p.GetCustomAttribute <DrawerAttribute>(true) != null, nativeProperties); // Cache methods with DrawerAttribute this.methods = ReflectionUtility.GetAllMethodsEfficiently( this.target, m => m.GetCustomAttribute <DrawerAttribute>(true) != null, methods); }
public override void ValidateProperty(SerializedProperty property) { ValidateInputAttribute validateInputAttribute = PropertyUtility.GetAttribute <ValidateInputAttribute>(property); object target = PropertyUtility.GetTargetObjectWithProperty(property); MethodInfo validationCallback = ReflectionUtility.GetMethod(target, validateInputAttribute.CallbackName); if (validationCallback != null && validationCallback.ReturnType == typeof(bool)) { ParameterInfo[] callbackParameters = validationCallback.GetParameters(); if (callbackParameters.Length == 0) { if (!(bool)validationCallback.Invoke(target, null)) { if (string.IsNullOrEmpty(validateInputAttribute.Message)) { NaughtyEditorGUI.HelpBox_Layout( property.name + " is not valid", MessageType.Error, context: property.serializedObject.targetObject); } else { NaughtyEditorGUI.HelpBox_Layout( validateInputAttribute.Message, MessageType.Error, context: property.serializedObject.targetObject); } } } else if (callbackParameters.Length == 1) { FieldInfo fieldInfo = ReflectionUtility.GetField(target, property.name); Type fieldType = fieldInfo.FieldType; Type parameterType = callbackParameters[0].ParameterType; if (fieldType == parameterType) { if (!(bool)validationCallback.Invoke(target, new object[] { fieldInfo.GetValue(target) })) { if (string.IsNullOrEmpty(validateInputAttribute.Message)) { NaughtyEditorGUI.HelpBox_Layout( property.name + " is not valid", MessageType.Error, context: property.serializedObject.targetObject); } else { NaughtyEditorGUI.HelpBox_Layout( validateInputAttribute.Message, MessageType.Error, context: property.serializedObject.targetObject); } } } else { string warning = "The field type is not the same as the callback's parameter type"; NaughtyEditorGUI.HelpBox_Layout(warning, MessageType.Warning, context: property.serializedObject.targetObject); } } else { string warning = validateInputAttribute.GetType().Name + " needs a callback with boolean return type and an optional single parameter of the same type as the field"; NaughtyEditorGUI.HelpBox_Layout(warning, MessageType.Warning, context: property.serializedObject.targetObject); } } }
public override void DrawProperty(SerializedProperty property) { EditorDrawUtility.DrawHeader(property); if (property.propertyType != SerializedPropertyType.Float && property.propertyType != SerializedPropertyType.Integer) { EditorGUILayout.HelpBox("Field " + property.name + " is not a number", MessageType.Warning); return; } var value = property.propertyType == SerializedPropertyType.Integer ? property.intValue : property.floatValue; var valueFormatted = property.propertyType == SerializedPropertyType.Integer ? value.ToString() : String.Format("{0:0.##}", value); ProgressBarAttribute progressBarAttribute = PropertyUtility.GetAttribute <ProgressBarAttribute>(property); var position = EditorGUILayout.GetControlRect(); var maxValue = progressBarAttribute.MaxValue; float lineHight = EditorGUIUtility.singleLineHeight; float padding = EditorGUIUtility.standardVerticalSpacing; var barPosition = new Rect(position.position.x, position.position.y, position.size.x, lineHight); UnityEngine.Object target = PropertyUtility.GetTargetObject(property); // maxValueVar - if found so override maxValue var maxValueVar = progressBarAttribute.maxValueVar; if (maxValueVar.Trim().Length > 0) { // try to get field first FieldInfo maxValueFieldInfo = ReflectionUtility.GetField(target, maxValueVar); if (maxValueFieldInfo != null) { if (maxValueFieldInfo.FieldType == typeof(int)) { maxValue = (int)maxValueFieldInfo.GetValue(target); } if (maxValueFieldInfo.FieldType == typeof(float)) { maxValue = (float)maxValueFieldInfo.GetValue(target); } } else { // if not get the property PropertyInfo maxValuePropertyInfo = ReflectionUtility.GetProperty(target, maxValueVar); if (maxValuePropertyInfo != null) { if (maxValuePropertyInfo.PropertyType == typeof(int)) { maxValue = (int)maxValuePropertyInfo.GetValue(target); } if (maxValuePropertyInfo.PropertyType == typeof(float)) { maxValue = (float)maxValuePropertyInfo.GetValue(target); } } } } var fillPercentage = value / maxValue; var barLabel = (!string.IsNullOrEmpty(progressBarAttribute.Name) ? "[" + progressBarAttribute.Name + "] " : "") + valueFormatted + "/" + maxValue; var color = GetColor(progressBarAttribute.Color); var color2 = Color.white; DrawBar(barPosition, Mathf.Clamp01(fillPercentage), barLabel, color, color2); }
public override void DrawMethod(UnityEngine.Object target, MethodInfo methodInfo) { ButtonIfAttribute buttonIfAttribute = (ButtonIfAttribute)methodInfo.GetCustomAttributes(typeof(ButtonIfAttribute), true)[0]; List <bool> conditionValues = new List <bool>(); foreach (var condition in buttonIfAttribute.Conditions) { //Debug.Log("condition: " + condition); FieldInfo conditionField = ReflectionUtility.GetField(target, condition); if (conditionField != null && conditionField.FieldType == typeof(bool)) { conditionValues.Add((bool)conditionField.GetValue(target)); } MethodInfo conditionMethod = ReflectionUtility.GetMethod(target, condition); if (conditionMethod != null && conditionMethod.ReturnType == typeof(bool) && conditionMethod.GetParameters().Length == 0) { //Debug.Log("method found: " + condition); conditionValues.Add((bool)conditionMethod.Invoke(target, null)); } } bool enabled = false; if (conditionValues.Count > 0) { if (buttonIfAttribute.ConditionOperator == ConditionOperator.And) { enabled = true; foreach (var value in conditionValues) { enabled = enabled && value; } } else { enabled = false; foreach (var value in conditionValues) { enabled = enabled || value; } } if (buttonIfAttribute.Reversed) { enabled = !enabled; } } else { string warning = buttonIfAttribute.GetType().Name + " needs a valid boolean condition field or method name to work"; EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, context: target); return; } if (methodInfo.GetParameters().Length == 0) { string buttonText = string.IsNullOrEmpty(buttonIfAttribute.Text) ? methodInfo.Name : buttonIfAttribute.Text; GUI.enabled = enabled; if (GUILayout.Button(buttonText)) { methodInfo.Invoke(target, null); } GUI.enabled = true; if (!enabled) { string infoText = "Preconditions for " + buttonText + ":"; for (int ix = 0; ix < conditionValues.Count; ix++) { infoText += "\n "; if (ix > 0) { infoText += buttonIfAttribute.ConditionOperator + " "; } infoText += buttonIfAttribute.Conditions[ix]; infoText += " (" + conditionValues[ix] + ")"; } EditorGUILayout.HelpBox(infoText, MessageType.Info); } } else { string warning = typeof(ButtonIfAttribute).Name + " works only on methods with no parameters"; EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, context: target); } }
protected virtual void OnEnable() { this.script = this.serializedObject.FindProperty("m_Script"); // Cache serialized fields and order this.fields = ReflectionUtility.GetAllFields(this.target, f => this.serializedObject.FindProperty(f.Name) != null).OrderByDescending(field => { int order = 0; var drawOrderAttr = field.GetCustomAttributes(typeof(DrawOrderAttribute), true).FirstOrDefault() as DrawOrderAttribute; if (drawOrderAttr != null) { order = drawOrderAttr.Order; } return(order); }); // If there are no NaughtyAttributes use default inspector if (this.fields.All(f => f.GetCustomAttributes(typeof(NaughtyAttribute), true).Length == 0)) { this.useDefaultInspector = true; } else { this.useDefaultInspector = false; // Cache grouped fields this.groupedFields = new HashSet <FieldInfo>(this.fields.Where(f => f.GetCustomAttributes(typeof(GroupAttribute), true).Length > 0)); // Cache grouped fields by group name this.groupedFieldsByGroupName = new Dictionary <string, List <FieldInfo> >(); foreach (var groupedField in this.groupedFields) { string groupName = (groupedField.GetCustomAttributes(typeof(GroupAttribute), true)[0] as GroupAttribute).Name; if (this.groupedFieldsByGroupName.ContainsKey(groupName)) { this.groupedFieldsByGroupName[groupName].Add(groupedField); } else { this.groupedFieldsByGroupName[groupName] = new List <FieldInfo>() { groupedField }; } } // Cache serialized properties by field name this.serializedPropertiesByFieldName = new Dictionary <string, SerializedProperty>(); foreach (var field in this.fields) { this.serializedPropertiesByFieldName[field.Name] = this.serializedObject.FindProperty(field.Name); } } // Cache non-serialized fields this.nonSerializedFields = ReflectionUtility.GetAllFields( this.target, f => f.GetCustomAttributes(typeof(DrawerAttribute), true).Length > 0 && this.serializedObject.FindProperty(f.Name) == null); // Cache the native properties this.nativeProperties = ReflectionUtility.GetAllProperties( this.target, p => p.GetCustomAttributes(typeof(DrawerAttribute), true).Length > 0); // Cache methods with DrawerAttribute this.methods = ReflectionUtility.GetAllMethods( this.target, m => m.GetCustomAttributes(typeof(DrawerAttribute), true).Length > 0); }
protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label) { EditorGUI.BeginProperty(rect, label, property); DropdownConstantsAttribute dropdownAttribute = (DropdownConstantsAttribute)attribute; object target = PropertyUtility.GetTargetObjectWithProperty(property); Type selectFromType = dropdownAttribute.SelectFromType; FieldInfo dropdownField = ReflectionUtility.GetField(target, property.name); if (AreValuesValid(selectFromType, dropdownField)) { var searchFlags = BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy; var allPublicStaticFields = dropdownAttribute.SelectFromType.GetFields(searchFlags); var allPublicStaticProperties = dropdownAttribute.SelectFromType.GetProperties(searchFlags); // IsLiteral determines if its value is written at compile time and not changeable // IsInitOnly determines if the field can be set in the body of the constructor // for C# a field which is readonly keyword would have both true but a const field would have only IsLiteral equal to true foreach (FieldInfo field in allPublicStaticFields) { if ((field.IsInitOnly || field.IsLiteral) && field.FieldType == selectFromType) { _constants.Add(field); } } foreach (var prop in allPublicStaticProperties) { if (prop.PropertyType == selectFromType) { _constants.Add(prop); } } if (IsNullOrEmpty(_constants)) { return; } string[] names = new string[_constants.Count]; object[] values = new object[_constants.Count]; for (var i = 0; i < _constants.Count; i++) { names[i] = _constants[i].Name; values[i] = GetValue(i); } // Selected value object selectedValue = dropdownField.GetValue(target); int selectedValueIndex = -1; bool valueFound = false; if (selectedValue != null) { for (var i = 0; i < values.Length; i++) { if (selectedValue.Equals(values[i])) { valueFound = true; selectedValueIndex = i; } } } if (!valueFound) { names = InsertAt(names, 0); values = InsertAt(values, 0); var actualValue = selectedValue; var value = actualValue != null ? actualValue : "NULL"; names[0] = "NOT FOUND: " + value; values[0] = actualValue; } NaughtyEditorGUI.Dropdown( rect, property.serializedObject, target, dropdownField, label.text, selectedValueIndex, values, names); } else { string message = $"Invalid values provided to '{dropdownAttribute.GetType().Name}'. The types of the target field and the type provided to the attribute don't match"; DrawDefaultPropertyAndHelpBox(rect, property, message, MessageType.Warning); } EditorGUI.EndProperty(); }