protected void DrawSerializedProperties()
        {
            serializedObject.Update();

            // Draw non-grouped serialized properties
            foreach (var property in GetNonGroupedProperties(_serializedProperties))
            {
                if (property.name.Equals("m_Script", System.StringComparison.Ordinal))
                {
                    GUI.enabled = false;
                    EditorGUILayout.PropertyField(property);
                    GUI.enabled = true;
                }
                else
                {
                    NaughtyEditorGUI.PropertyField_Layout(property, true);
                }
            }

            // Draw grouped serialized properties
            foreach (var group in GetGroupedProperties(_serializedProperties))
            {
                IEnumerable <SerializedProperty> visibleProperties = group.Where(p => PropertyUtility.IsVisible(p));
                if (!visibleProperties.Any())
                {
                    continue;
                }

                NaughtyEditorGUI.BeginBoxGroup_Layout(group.Key);
                foreach (var property in visibleProperties)
                {
                    NaughtyEditorGUI.PropertyField_Layout(property, true);
                }

                NaughtyEditorGUI.EndBoxGroup_Layout();
            }

            // Draw foldout serialized properties
            foreach (var group in GetFoldoutProperties(_serializedProperties))
            {
                IEnumerable <SerializedProperty> visibleProperties = group.Where(p => PropertyUtility.IsVisible(p));
                if (!visibleProperties.Any())
                {
                    continue;
                }

                if (!_foldouts.ContainsKey(group.Key))
                {
                    _foldouts[group.Key] = new SavedBool($"{target.GetType()}.{group.Key}", false);
                }

                _foldouts[group.Key].value = NaughtyEditorGUI.BeginFoldout_Layout(_foldouts[group.Key].value, group.Key);
                if (_foldouts[group.Key].value)
                {
                    foreach (var property in visibleProperties)
                    {
                        NaughtyEditorGUI.PropertyField_Layout(property, true);
                    }
                }

                NaughtyEditorGUI.EndFoldout_Layout();
            }

            serializedObject.ApplyModifiedProperties();
        }
        public override void DrawProperty(SerializedProperty property)
        {
            EditorDrawUtility.DrawHeader(property);

            if (property.propertyType == SerializedPropertyType.String)
            {
                EditorGUILayout.LabelField(property.displayName);

                EditorGUI.BeginChangeCheck();

                string textAreaValue = EditorGUILayout.TextArea(property.stringValue, GUILayout.MinHeight(EditorGUIUtility.singleLineHeight * 3f));

                if (EditorGUI.EndChangeCheck())
                {
                    property.stringValue = textAreaValue;
                }
            }
            else
            {
                string warning = PropertyUtility.GetAttribute <ResizableTextAreaAttribute>(property).GetType().Name + " can only be used on string fields";
                EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: PropertyUtility.GetTargetObject(property));

                EditorDrawUtility.DrawPropertyField(property);
            }
        }
예제 #3
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);
            }
        }
예제 #4
0
        public override void DrawProperty(SerializedProperty property)
        {
            EditorDrawUtility.DrawHeader(property);
            var attr   = PropertyUtility.GetAttribute <PrefabOnlyAttribute>(property);
            var type   = this.FieldInfo.FieldType;
            var target = property.serializedObject.targetObject;

            if (target is Component)
            {
                var parent = (target as Component).transform;
                if (typeof(GameObject).IsAssignableFrom(type))
                {
                    var obj = (GameObject)EditorGUILayout.ObjectField(property.displayName, property.objectReferenceValue, this.FieldInfo.FieldType, true);
                    if (obj == null || obj.transform.IsChildOf(parent))
                    {
                        property.objectReferenceValue = obj;
                    }
                    else
                    {
                        Debug.LogWarning($"{obj.name} is not child of {parent.name} thus can not be used", obj);
                    }
                    return;
                }
                else if (typeof(Component).IsAssignableFrom(type))
                {
                    var obj = (Component)EditorGUILayout.ObjectField(property.displayName, property.objectReferenceValue, this.FieldInfo.FieldType, true);
                    if (obj == null || obj.transform.IsChildOf(parent))
                    {
                        property.objectReferenceValue = obj;
                    }
                    else
                    {
                        Debug.LogWarning($"{obj.name} is not child of {parent.name} thus can not be used", obj);
                    }
                    return;
                }
            }
            EditorDrawUtility.DrawHelpBox($"Field={this.FieldInfo.Name} Type={this.FieldInfo.FieldType.Name} {nameof(TranformChildOnlyAttribute)} can only be used on GameObject or Component fields of UnityEngine.Component", MessageType.Warning, context: PropertyUtility.GetTargetObject(property));
            EditorDrawUtility.DrawPropertyField(property);
        }
예제 #5
0
 private static IEnumerable <IGrouping <string, SerializedProperty> > GetGroupedProperties(IEnumerable <SerializedProperty> properties)
 {
     return(properties
            .Where(p => PropertyUtility.GetAttribute <BoxGroupAttribute>(p) != null)
            .GroupBy(p => PropertyUtility.GetAttribute <BoxGroupAttribute>(p).Name));
 }
        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 != null &&
                    conditionField.FieldType == typeof(bool))
                {
                    conditionValues.Add((bool)conditionField.GetValue(target));
                }

                PropertyInfo pi = ReflectionUtility.GetProperty(target, condition);
                if (pi != null &&
                    pi.PropertyType == typeof(bool))
                {
                    conditionValues.Add((bool)pi.GetValue(target));
                }

                MethodInfo 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 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);
            }
        }
예제 #7
0
        protected void DrawSerializedProperties()
        {
            serializedObject.Update();

            // Draw non-grouped serialized properties
            foreach (var property in GetNonGroupedProperties(_serializedProperties))
            {
                if (property.name.Equals("m_Script", System.StringComparison.Ordinal))
                {
                    using (new EditorGUI.DisabledScope(disabled: true))
                    {
                        EditorGUILayout.PropertyField(property);
                    }
                }
                else
                {
                    NaughtyEditorGUI.PropertyField_Layout(property, includeChildren: true);
                }
            }

            // Draw grouped serialized properties
            foreach (var group in GetGroupedProperties(_serializedProperties))
            {
                IEnumerable <SerializedProperty> visibleProperties = group.Where(p => PropertyUtility.IsVisible(p));
                if (!visibleProperties.Any())
                {
                    continue;
                }

                NaughtyEditorGUI.BeginBoxGroup_Layout(group.Key);
                foreach (var property in visibleProperties)
                {
                    NaughtyEditorGUI.PropertyField_Layout(property, includeChildren: true);
                }

                NaughtyEditorGUI.EndBoxGroup_Layout();
            }

            // Draw foldout serialized properties
            foreach (var group in GetFoldoutProperties(_serializedProperties))
            {
                IEnumerable <SerializedProperty> visibleProperties = group.Where(p => PropertyUtility.IsVisible(p));
                if (!visibleProperties.Any())
                {
                    continue;
                }

                if (!_foldouts.ContainsKey(group.Key))
                {
                    _foldouts[group.Key] = new SavedBool($"{target.GetInstanceID()}.{group.Key}", false);
                }

                _foldouts[group.Key].Value = EditorGUILayout.Foldout(_foldouts[group.Key].Value, group.Key, true);
                if (_foldouts[group.Key].Value)
                {
                    EditorGUI.indentLevel++;
                    foreach (var property in visibleProperties)
                    {
                        NaughtyEditorGUI.PropertyField_Layout(property, true);
                    }
                    EditorGUI.indentLevel--;
                }
            }

            serializedObject.ApplyModifiedProperties();
        }
        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);
                }
            }
        }
예제 #9
0
        public override void DrawProperty(SerializedProperty property)
        {
            EditorDrawUtility.DrawHeader(property);

            if (property.isArray)
            {
                if (!this.reorderableListsByPropertyName.ContainsKey(property.name))
                {
                    ReorderableList reorderableList = new ReorderableList(property.serializedObject, property, true, true, true, true)
                    {
                        drawHeaderCallback = (Rect rect) =>
                        {
                            EditorGUI.LabelField(rect, string.Format("{0}: {1}", property.displayName, property.arraySize), EditorStyles.label);
                        },

                        drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) =>
                        {
                            var element = property.GetArrayElementAtIndex(index);
                            rect.y += 2f;

                            EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), element);
                        }
                    };

                    this.reorderableListsByPropertyName[property.name] = reorderableList;
                }

                this.reorderableListsByPropertyName[property.name].DoLayoutList();
            }
            else
            {
                string warning = typeof(ReorderableListAttribute).Name + " can be used only on arrays or lists";
                EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: PropertyUtility.GetTargetObject(property));

                EditorDrawUtility.DrawPropertyField(property);
            }
        }
예제 #10
0
 private static IEnumerable <IGrouping <string, SerializedProperty> > GetFoldoutProperties(IEnumerable <SerializedProperty> properties) => properties
 .Where(p => PropertyUtility.GetAttribute <FoldoutAttribute>(p) != null)
 .GroupBy(p => PropertyUtility.GetAttribute <FoldoutAttribute>(p).Name);
예제 #11
0
        protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label)
        {
            EditorGUI.BeginProperty(rect, label, property);
            Texture2D            previewTexture = GetAssetPreview(property);
            HeaderImageAttribute headerImageAttribute
                = PropertyUtility.GetAttribute <HeaderImageAttribute>(property);

            if (previewTexture != null)
            {
                float indentLength = NaughtyEditorGUI.GetIndentLength(rect);
                var   previewSize  = GetAssetPreviewSize(property);

                float width = rect.width - indentLength;
                previewSize = RescaleSize(previewSize, width);
                float alignmentLength = 0f;
                if (previewSize.x < width)
                {
                    switch (headerImageAttribute.Alignment)
                    {
                    case EAlignment.Center:
                        alignmentLength = (width - previewSize.x) / 2f;
                        break;

                    case EAlignment.Right:
                        alignmentLength = (width - previewSize.x);
                        break;

                    case EAlignment.Left:
                    default:
                        alignmentLength = 0f;
                        break;
                    }
                }
                Rect propertyRect = new Rect()
                {
                    x      = rect.x,
                    y      = rect.y + previewSize.y,
                    width  = width,
                    height = EditorGUIUtility.singleLineHeight
                };

                EditorGUI.PropertyField(propertyRect, property, label);

                Rect previewRect = new Rect()
                {
                    x = rect.x + indentLength + alignmentLength,
                    y = rect.y,
                    // width = rect.width,
                    width  = previewSize.x,
                    height = previewSize.y
                };

                GUI.Label(previewRect, previewTexture);
            }
            else
            {
                string message = property.name + " has no header image for path: " + headerImageAttribute.Path;
                DrawDefaultPropertyAndHelpBox(rect, property, message, MessageType.Warning);
            }

            EditorGUI.EndProperty();
        }
예제 #12
0
        public override void DrawProperty(SerializedProperty property)
        {
            ShowAssetPreviewAttribute showAssetPreviewAttribute = PropertyUtility.GetAttribute <ShowAssetPreviewAttribute>(property);

            if (showAssetPreviewAttribute.DrawPropertyField)
            {
                EditorDrawUtility.DrawPropertyField(property);
            }

            if (property.propertyType == SerializedPropertyType.ObjectReference)
            {
                if (property.objectReferenceValue != null)
                {
                    Texture2D previewTexture = AssetPreview.GetAssetPreview(property.objectReferenceValue);
                    if (previewTexture != null)
                    {
                        int width  = Mathf.Clamp(showAssetPreviewAttribute.Width, 0, previewTexture.width);
                        int height = Mathf.Clamp(showAssetPreviewAttribute.Height, 0, previewTexture.height);

                        GUILayout.Label(previewTexture, GUILayout.MaxWidth(width), GUILayout.MaxHeight(height));
                    }
                    else
                    {
                        string warning = property.name + " doesn't have an asset preview";
                        EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, context: PropertyUtility.GetTargetObject(property));
                    }
                }
            }
            else
            {
                string warning = property.name + " doesn't have an asset preview";
                EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, context: PropertyUtility.GetTargetObject(property));
            }
        }
        public override void ValidateProperty(SerializedProperty property)
        {
            RequiredAttribute requiredAttribute = PropertyUtility.GetAttribute <RequiredAttribute>(property);

            if (property.propertyType == SerializedPropertyType.ObjectReference)
            {
                if (property.objectReferenceValue == null)
                {
                    string errorMessage = property.name + " is required";
                    if (!string.IsNullOrEmpty(requiredAttribute.Message))
                    {
                        errorMessage = requiredAttribute.Message;
                    }

                    EditorDrawUtility.DrawHelpBox(errorMessage, MessageType.Error, logToConsole: true, context: PropertyUtility.GetTargetObject(property));
                }
            }
            else
            {
                string warning = requiredAttribute.GetType().Name + " works only on reference types";
                EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: PropertyUtility.GetTargetObject(property));
            }
        }
예제 #14
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);
        }
예제 #15
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();
        }
예제 #16
0
        public override void DrawProperty(SerializedProperty property)
        {
            EditorDrawUtility.DrawHeader(property);

            if (property.isArray)
            {
                if (!this.reorderableListsByPropertyName.ContainsKey(property.name))
                {
                    ReorderableList reorderableList = new ReorderableList(property.serializedObject, property, true, true, true, true)
                    {
                        drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) =>
                        {
                            var element = property.GetArrayElementAtIndex(index);
                            rect.y += 2f;
                            EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), element);
                        }
                    };

                    reorderableList.drawHeaderCallback = (Rect rect) => {
                        property.isExpanded = EditorGUI.Foldout(rect, property.isExpanded, string.Format("{0} [{1}]", property.displayName, property.arraySize));
                        Rect rect2 = rect;
                        if (reorderableList.count == 0)
                        {
                            rect2.height = (rect2.height * 3f);
                        }
                        Event     current = Event.current;
                        EventType type    = current.type;
                        if (type != EventType.DragExited)
                        {
                            if (type == EventType.DragUpdated || type == EventType.DragPerform)
                            {
                                if (rect2.Contains(current.mousePosition))
                                {
                                    DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
                                    if (current.type == EventType.DragPerform)
                                    {
                                        DragAndDrop.AcceptDrag();
                                        Object[] objectReferences = DragAndDrop.objectReferences;
                                        for (int i = 0; i < objectReferences.Length; i++)
                                        {
                                            Object obj = objectReferences[i];
                                            AddElement(property, obj);
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            DragAndDrop.PrepareStartDrag();
                        }
//                            EditorGUI.LabelField(rect, string.Format("{0}: {1}", property.displayName, property.arraySize), EditorStyles.label);
                    };

                    this.reorderableListsByPropertyName[property.name] = reorderableList;
                }
                if (property.isExpanded)
                {
                    this.reorderableListsByPropertyName[property.name].DoLayoutList();
                }
                else
                {
                    property.isExpanded = (EditorGUILayout.Foldout(property.isExpanded, new GUIContent(string.Format("{0} [{1}]", property.displayName, property.arraySize), property.tooltip)));
                }
            }
            else
            {
                string warning = typeof(ReorderableListAttribute).Name + " can be used only on arrays or lists";
                EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: PropertyUtility.GetTargetObject(property));

                EditorDrawUtility.DrawPropertyField(property);
            }
        }
예제 #17
0
        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 (fieldInfo.FieldType == valuesFieldInfo.FieldType.GetElementType())
            {
                // 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);
            }
        }
예제 #18
0
 private static IEnumerable <SerializedProperty> GetNonGroupedProperties(IEnumerable <SerializedProperty> properties)
 {
     return(properties.Where(p => PropertyUtility.GetAttribute <BoxGroupAttribute>(p) == null));
 }
        public override void DrawProperty(SerializedProperty property)
        {
            EditorDrawUtility.DrawHeader(property);

            MinMaxSliderAttribute minMaxSliderAttribute = PropertyUtility.GetAttribute <MinMaxSliderAttribute>(property);

            if (property.propertyType == SerializedPropertyType.Vector2)
            {
                Rect  controlRect     = EditorGUILayout.GetControlRect();
                float labelWidth      = EditorGUIUtility.labelWidth;
                float floatFieldWidth = EditorGUIUtility.fieldWidth;
                float sliderWidth     = controlRect.width - labelWidth - 2f * floatFieldWidth;
                float sliderPadding   = 5f;

                Rect labelRect = new Rect(
                    controlRect.x,
                    controlRect.y,
                    labelWidth,
                    controlRect.height);

                Rect sliderRect = new Rect(
                    controlRect.x + labelWidth + floatFieldWidth + sliderPadding,
                    controlRect.y,
                    sliderWidth - 2f * sliderPadding,
                    controlRect.height);

                Rect minFloatFieldRect = new Rect(
                    controlRect.x + labelWidth,
                    controlRect.y,
                    floatFieldWidth,
                    controlRect.height);

                Rect maxFloatFieldRect = new Rect(
                    controlRect.x + labelWidth + floatFieldWidth + sliderWidth,
                    controlRect.y,
                    floatFieldWidth,
                    controlRect.height);

                // Draw the label
                EditorGUI.LabelField(labelRect, property.displayName);

                // Draw the slider
                EditorGUI.BeginChangeCheck();

                Vector2 sliderValue = property.vector2Value;
                EditorGUI.MinMaxSlider(sliderRect, ref sliderValue.x, ref sliderValue.y, minMaxSliderAttribute.MinValue, minMaxSliderAttribute.MaxValue);

                sliderValue.x = EditorGUI.FloatField(minFloatFieldRect, sliderValue.x);
                sliderValue.x = Mathf.Clamp(sliderValue.x, minMaxSliderAttribute.MinValue, Mathf.Min(minMaxSliderAttribute.MaxValue, sliderValue.y));

                sliderValue.y = EditorGUI.FloatField(maxFloatFieldRect, sliderValue.y);
                sliderValue.y = Mathf.Clamp(sliderValue.y, Mathf.Max(minMaxSliderAttribute.MinValue, sliderValue.x), minMaxSliderAttribute.MaxValue);

                if (EditorGUI.EndChangeCheck())
                {
                    property.vector2Value = sliderValue;
                }
            }
            else
            {
                string warning = minMaxSliderAttribute.GetType().Name + " can be used only on Vector2 fields";
                EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: PropertyUtility.GetTargetObject(property));

                EditorDrawUtility.DrawPropertyField(property);
            }
        }
예제 #20
0
        private void DrawChildProperties(Rect rect, SerializedProperty property)
        {
            ScriptableObject scriptableObject = property.objectReferenceValue as ScriptableObject;

            if (scriptableObject == null)
            {
                return;
            }

            Rect boxRect = new Rect()
            {
                x      = 0.0f,
                y      = rect.y + EditorGUIUtility.singleLineHeight,
                width  = rect.width * 2.0f,
                height = rect.height - EditorGUIUtility.singleLineHeight
            };

            GUI.Box(boxRect, GUIContent.none);

            using (new EditorGUI.IndentLevelScope())
            {
                EditorGUI.BeginChangeCheck();

                SerializedObject serializedObject = new SerializedObject(scriptableObject);
                using (var iterator = serializedObject.GetIterator())
                {
                    float yOffset = EditorGUIUtility.singleLineHeight;

                    if (iterator.NextVisible(true))
                    {
                        do
                        {
                            SerializedProperty childProperty = serializedObject.FindProperty(iterator.name);
                            if (childProperty.name.Equals("m_Script", System.StringComparison.Ordinal))
                            {
                                continue;
                            }

                            bool visible = PropertyUtility.IsVisible(childProperty);
                            if (!visible)
                            {
                                continue;
                            }

                            float childHeight = GetPropertyHeight(childProperty);
                            Rect  childRect   = new Rect()
                            {
                                x      = rect.x,
                                y      = rect.y + yOffset,
                                width  = rect.width,
                                height = childHeight
                            };

                            NaughtyEditorGUI.PropertyField(childRect, childProperty, true);

                            yOffset += childHeight;
                        }while (iterator.NextVisible(false));
                    }
                }

                if (EditorGUI.EndChangeCheck())
                {
                    serializedObject.ApplyModifiedProperties();
                }
            }
        }
예제 #21
0
        protected void DrawSerializedProperties()
        {
            serializedObject.Update();

            // Draw non-grouped serialized properties
            foreach (var property in GetNonGroupedProperties(_serializedProperties))
            {
                if (property.name.Equals("m_Script", System.StringComparison.Ordinal))
                {
                    GUI.enabled = false;
                    EditorGUILayout.PropertyField(property);
                    GUI.enabled = true;
                }
                else
                {
                    NaughtyEditorGUI.PropertyField_Layout(property, true);
                }
            }

            // Draw grouped serialized properties
            foreach (var group in GetGroupedProperties(_serializedProperties))
            {
                IEnumerable <SerializedProperty> visibleProperties = group.Where(p => PropertyUtility.IsVisible(p));
                if (!visibleProperties.Any())
                {
                    continue;
                }

                NaughtyEditorGUI.BeginBoxGroup_Layout(group.Key);
                foreach (var property in visibleProperties)
                {
                    NaughtyEditorGUI.PropertyField_Layout(property, true);
                }

                NaughtyEditorGUI.EndBoxGroup_Layout();
            }

            serializedObject.ApplyModifiedProperties();
        }
        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.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))
                            {
                                selectedValueIndex = index;
                            }

                            values.Add(current.Value);
                            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();
        }
        public override void ValidateProperty(SerializedProperty property)
        {
            MaxValueAttribute maxValueAttribute = PropertyUtility.GetAttribute <MaxValueAttribute>(property);

            if (property.propertyType == SerializedPropertyType.Integer)
            {
                if (property.intValue > maxValueAttribute.MaxValue)
                {
                    property.intValue = (int)maxValueAttribute.MaxValue;
                }
            }
            else if (property.propertyType == SerializedPropertyType.Float)
            {
                if (property.floatValue > maxValueAttribute.MaxValue)
                {
                    property.floatValue = maxValueAttribute.MaxValue;
                }
            }
            else
            {
                string warning = maxValueAttribute.GetType().Name + " can be used only on int or float fields";
                EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: PropertyUtility.GetTargetObject(property));
            }
        }
예제 #24
0
        public override void DrawProperty(SerializedProperty property)
        {
            EditorDrawUtility.DrawHeader(property);

            SliderAttribute sliderAttribute = PropertyUtility.GetAttribute <SliderAttribute>(property);

            if (property.propertyType == SerializedPropertyType.Integer)
            {
                EditorGUILayout.IntSlider(property, (int)sliderAttribute.MinValue, (int)sliderAttribute.MaxValue);
            }
            else if (property.propertyType == SerializedPropertyType.Float)
            {
                EditorGUILayout.Slider(property, sliderAttribute.MinValue, sliderAttribute.MaxValue);
            }
            else
            {
                string warning = sliderAttribute.GetType().Name + " can be used only on int or float fields";
                EditorDrawUtility.DrawHelpBox(warning, MessageType.Warning, logToConsole: true, context: PropertyUtility.GetTargetObject(property));

                EditorDrawUtility.DrawPropertyField(property);
            }
        }
예제 #25
0
        public override void DrawProperty(SerializedProperty property)
        {
            EditorDrawUtility.DrawHeader(property);
            var attr = PropertyUtility.GetAttribute <PrefabOnlyAttribute>(property);
            var type = this.FieldInfo.FieldType;

            if (typeof(GameObject).IsAssignableFrom(type) || typeof(Component).IsAssignableFrom(type))
            {
                property.objectReferenceValue = EditorGUILayout.ObjectField(property.displayName, property.objectReferenceValue, this.FieldInfo.FieldType, false);
            }
            else
            {
                EditorDrawUtility.DrawHelpBox($"Field={this.FieldInfo.Name} Type={this.FieldInfo.FieldType.Name} {nameof(PrefabOnlyAttribute)} can only be used on GameObject or Component fields", MessageType.Warning, context: PropertyUtility.GetTargetObject(property));
                EditorDrawUtility.DrawPropertyField(property);
            }
        }