public override void OnGUI(Rect position) { Rect rect = EditorGUI.IndentedRect(position); rect.y += EditorGUIUtility.singleLineHeight / 3.0f; HorizontalLineAttribute lineAttr = (HorizontalLineAttribute)attribute; NaughtyEditorGUI.HorizontalLine(rect, lineAttr.Height, lineAttr.Color.GetColor()); }
public override void OnGUI(Rect rect) { InfoBoxAttribute infoBoxAttribute = (InfoBoxAttribute)attribute; float indentLength = NaughtyEditorGUI.GetIndentLength(rect); Rect infoBoxRect = new Rect( rect.x + indentLength, rect.y, rect.width - indentLength, GetHelpBoxHeight() - 2.0f); DrawInfoBox(infoBoxRect, infoBoxAttribute.Text, infoBoxAttribute.Type); }
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; } EColor newColor = EColor.Gray; foreach (var property in visibleProperties) { newColor = PropertyUtility.GetAttribute <BoxGroupAttribute>(property).myColor; if (newColor != EColor.Gray) { break; } } bool show = BeginBoxGroup_Layout(group.Key, newColor); if (show) { foreach (var property in visibleProperties) { NaughtyEditorGUI.PropertyField_Layout(property, true); } } NaughtyEditorGUI.EndBoxGroup_Layout(); } serializedObject.ApplyModifiedProperties(); }
protected void DrawButtons() { if (_methods.Any()) { EditorGUILayout.Space(); EditorGUILayout.LabelField("Buttons", GetHeaderGUIStyle()); NaughtyEditorGUI.HorizontalLine( EditorGUILayout.GetControlRect(false), HorizontalLineAttribute.DefaultHeight, HorizontalLineAttribute.DefaultColor.GetColor()); foreach (var method in _methods) { NaughtyEditorGUI.Button(serializedObject.targetObject, method); } } }
protected void DrawNativeProperties() { if (_nativeProperties.Any()) { EditorGUILayout.Space(); EditorGUILayout.LabelField("Native Properties", GetHeaderGUIStyle()); NaughtyEditorGUI.HorizontalLine( EditorGUILayout.GetControlRect(false), HorizontalLineAttribute.DefaultHeight, HorizontalLineAttribute.DefaultColor.GetColor()); foreach (var property in _nativeProperties) { NaughtyEditorGUI.NativeProperty_Layout(serializedObject.targetObject, property); } } }
protected void DrawNonSerializedFields() { if (_nonSerializedFields.Any()) { EditorGUILayout.Space(); EditorGUILayout.LabelField("Non-Serialized Fields", GetHeaderGUIStyle()); NaughtyEditorGUI.HorizontalLine( EditorGUILayout.GetControlRect(false), HorizontalLineAttribute.DefaultHeight, HorizontalLineAttribute.DefaultColor.GetColor()); foreach (var field in _nonSerializedFields) { NaughtyEditorGUI.NonSerializedField_Layout(serializedObject.targetObject, field); } } }
protected override void OnGUI_Internal(SerializedProperty property, GUIContent label) { if (property.isArray) { string key = GetPropertyKeyName(property); if (!_reorderableListsByPropertyName.ContainsKey(key)) { ReorderableList reorderableList = new ReorderableList(property.serializedObject, property, true, true, true, true) { drawHeaderCallback = (Rect rect) => { EditorGUI.LabelField(rect, string.Format("{0}: {1}", label.text, property.arraySize), EditorStyles.boldLabel); }, drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) => { SerializedProperty element = property.GetArrayElementAtIndex(index); rect.y += 1.0f; rect.x += 10.0f; rect.width -= 10.0f; EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, 0.0f), element, true); }, elementHeightCallback = (int index) => { return(EditorGUI.GetPropertyHeight(property.GetArrayElementAtIndex(index)) + 4.0f); } }; _reorderableListsByPropertyName[key] = reorderableList; } _reorderableListsByPropertyName[key].DoLayoutList(); } else { string message = typeof(ReorderableListAttribute).Name + " can be used only on arrays or lists"; NaughtyEditorGUI.HelpBox_Layout(message, MessageType.Warning, context: property.serializedObject.targetObject); EditorGUILayout.PropertyField(property, true); } }
public void DrawDefaultPropertyAndHelpBox(Rect rect, SerializedProperty property, string message, MessageType messageType) { float indentLength = NaughtyEditorGUI.GetIndentLength(rect); Rect helpBoxRect = new Rect( rect.x + indentLength, rect.y, rect.width - indentLength, GetHelpBoxHeight() - 2.0f); NaughtyEditorGUI.HelpBox(helpBoxRect, message, MessageType.Warning, context: property.serializedObject.targetObject); Rect propertyRect = new Rect( rect.x, rect.y + GetHelpBoxHeight(), rect.width, GetPropertyHeight(property)); EditorGUI.PropertyField(propertyRect, property, true); }
protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label) { if (!IsNumber(property)) { string message = string.Format("Field {0} is not a number", property.name); DrawDefaultPropertyAndHelpBox(rect, property, message, MessageType.Warning); return; } ProgressBarAttribute progressBarAttribute = PropertyUtility.GetAttribute <ProgressBarAttribute>(property); var value = property.propertyType == SerializedPropertyType.Integer ? property.intValue : property.floatValue; var valueFormatted = property.propertyType == SerializedPropertyType.Integer ? value.ToString() : string.Format("{0:0.00}", value); var maxValue = GetMaxValue(property, progressBarAttribute); if (maxValue != null && maxValue is float) { var fillPercentage = value / (float)maxValue; var barLabel = (!string.IsNullOrEmpty(progressBarAttribute.Name) ? "[" + progressBarAttribute.Name + "] " : "") + valueFormatted + "/" + maxValue; var barColor = progressBarAttribute.Color.GetColor(); var labelColor = Color.white; var indentLength = NaughtyEditorGUI.GetIndentLength(rect); Rect barRect = new Rect() { x = rect.x + indentLength, y = rect.y, width = rect.width - indentLength, height = EditorGUIUtility.singleLineHeight }; DrawBar(barRect, Mathf.Clamp01(fillPercentage), barLabel, barColor, labelColor); } else { string message = string.Format( "The provided dynamic max value for the progress bar is not correct. Please check if the '{0}' is correct, or the return type is float", nameof(progressBarAttribute.MaxValueName)); DrawDefaultPropertyAndHelpBox(rect, property, message, MessageType.Warning); } }
private void DrawInfoBox(Rect rect, string infoText, EInfoBoxType infoBoxType) { MessageType messageType = MessageType.None; switch (infoBoxType) { case EInfoBoxType.Normal: messageType = MessageType.Info; break; case EInfoBoxType.Warning: messageType = MessageType.Warning; break; case EInfoBoxType.Error: messageType = MessageType.Error; break; } NaughtyEditorGUI.HelpBox(rect, infoText, messageType); }
protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label) { EditorGUI.BeginProperty(rect, label, property); if (property.propertyType == SerializedPropertyType.ObjectReference) { Rect propertyRect = new Rect() { x = rect.x, y = rect.y, width = rect.width, height = EditorGUIUtility.singleLineHeight }; EditorGUI.PropertyField(propertyRect, property, label); Texture2D previewTexture = GetAssetPreview(property); if (previewTexture != null) { Rect previewRect = new Rect() { x = rect.x + NaughtyEditorGUI.GetIndentLength(rect), y = rect.y + EditorGUIUtility.singleLineHeight, width = rect.width, height = GetAssetPreviewSize(property).y }; GUI.Label(previewRect, previewTexture); } } else { string message = property.name + " doesn't have an asset preview"; DrawDefaultPropertyAndHelpBox(rect, property, message, MessageType.Warning); } EditorGUI.EndProperty(); }
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; } NaughtyEditorGUI.HelpBox_Layout(errorMessage, MessageType.Error, context: property.serializedObject.targetObject); } } else { string warning = requiredAttribute.GetType().Name + " works only on reference types"; NaughtyEditorGUI.HelpBox_Layout(warning, MessageType.Warning, context: property.serializedObject.targetObject); } }
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(); }
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); } } }
protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label) { EditorGUI.BeginProperty(rect, label, property); MinMaxSliderAttribute minMaxSliderAttribute = (MinMaxSliderAttribute)attribute; if (property.propertyType == SerializedPropertyType.Vector2) { EditorGUI.BeginProperty(rect, label, property); float indentLength = NaughtyEditorGUI.GetIndentLength(rect); float labelWidth = EditorGUIUtility.labelWidth; float floatFieldWidth = EditorGUIUtility.fieldWidth; float sliderWidth = rect.width - labelWidth - 2f * floatFieldWidth; float sliderPadding = 5f; Rect labelRect = new Rect( rect.x, rect.y, labelWidth, rect.height); Rect sliderRect = new Rect( rect.x + labelWidth + floatFieldWidth + sliderPadding - indentLength, rect.y, sliderWidth - 2f * sliderPadding + indentLength, rect.height); Rect minFloatFieldRect = new Rect( rect.x + labelWidth - indentLength, rect.y, floatFieldWidth + indentLength, rect.height); Rect maxFloatFieldRect = new Rect( rect.x + labelWidth + floatFieldWidth + sliderWidth - indentLength, rect.y, floatFieldWidth + indentLength, rect.height); // Draw the label EditorGUI.LabelField(labelRect, label.text); // 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; } EditorGUI.EndProperty(); } else { string message = minMaxSliderAttribute.GetType().Name + " can be used only on Vector2 fields"; DrawDefaultPropertyAndHelpBox(rect, property, message, MessageType.Warning); } EditorGUI.EndProperty(); }