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); } }
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); } }
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); }
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); } }
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); } } }
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); } }
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);
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(); }
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)); } }
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); }
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(); }
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); } }
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); } }
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); } }
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(); } } }
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)); } }
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); } }
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); } }