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);
            }
        }
Esempio n. 4
0
        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);
        }
Esempio n. 5
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);
        }
Esempio n. 6
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);
        }
Esempio n. 8
0
        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);
            }
        }
Esempio n. 9
0
        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);
                }
            }
        }
Esempio n. 11
0
        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);
        }
Esempio n. 12
0
        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);
            }
        }
Esempio n. 13
0
        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);
        }
Esempio n. 14
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();
        }