diff --git a/Editor/AbstractPropertyDrawer.cs b/Editor/AbstractPropertyDrawer.cs index 1879be4..2dbde4e 100644 --- a/Editor/AbstractPropertyDrawer.cs +++ b/Editor/AbstractPropertyDrawer.cs @@ -14,6 +14,9 @@ namespace Module.Inspector.Editor if (accessType == EAccessType.Hidden) return; + bool prevEnabled = GUI.enabled; + GUI.enabled = accessType == EAccessType.Enabled; + label.tooltip = result.tooltip; for (var i = 0; i < result.predrawerModifiers.Count; i++) @@ -22,18 +25,39 @@ namespace Module.Inspector.Editor value.drawer.Modify(value.attribute, property, label); } - bool prevEnabled = GUI.enabled; - GUI.enabled = accessType == EAccessType.Enabled; + var isValid = true; + var validationError = string.Empty; + + for (var i = 0; i < result.validators.Count; i++) + { + EditorPropertyUtility.ResultValue value = result.validators[i]; + + if (value.drawer.Validate(value.attribute, property)) + continue; + + validationError += value.drawer.GetValidationError(property); + isValid = false; + } + + Color prevColor = GUI.color; + + if (!isValid) + { + if (string.IsNullOrEmpty(label.tooltip)) + label.tooltip = validationError; + else + label.tooltip += "\n" + validationError; + + GUI.color = Color.red; + } if (result.draw != null) { if (!result.draw.drawer.Draw(position, result.draw.attribute, property, label, result)) { - Color prevColor = GUI.color; GUI.color = Color.red; var errorContent = new GUIContent(result.draw.drawer.GetErrorMessage(property)); EditorGUI.LabelField(position, label, errorContent); - GUI.color = prevColor; } } else @@ -41,6 +65,7 @@ namespace Module.Inspector.Editor EditorGUI.PropertyField(position, property, label, true); } + GUI.color = prevColor; GUI.enabled = prevEnabled; for (var i = 0; i < result.valueModifiers.Count; i++) diff --git a/Editor/Utilities/EditorPropertyUtility.cs b/Editor/Utilities/EditorPropertyUtility.cs index b830539..7d17013 100644 --- a/Editor/Utilities/EditorPropertyUtility.cs +++ b/Editor/Utilities/EditorPropertyUtility.cs @@ -75,6 +75,7 @@ namespace Module.Inspector.Editor.Utilities var predrawerModifiers = new List>(2); var valueModifiers = new List>(2); var accessModifiers = new List>(2); + var validators = new List>(2); object[] attributes = fieldInfo.GetCustomAttributes(false); string tooltip = null; var isObsolete = false; @@ -115,6 +116,13 @@ namespace Module.Inspector.Editor.Utilities if (prop != null) accessModifiers.Add(new ResultValue(accessModifier, prop)); } + else if (att is ValidatePropertyAttribute validator) + { + var prop = InternalCreateInstanceOf(validator); + + if (prop != null) + validators.Add(new ResultValue(validator, prop)); + } else if (att is TooltipAttribute attTooltip) { tooltip = attTooltip.tooltip; @@ -144,7 +152,7 @@ namespace Module.Inspector.Editor.Utilities } } - return new Result(drawer, predrawerModifiers, valueModifiers, accessModifiers, tooltip, isObsolete); + return new Result(drawer, predrawerModifiers, valueModifiers, accessModifiers, validators, tooltip, isObsolete); } private static T InternalCreateInstanceOf(AbstractPropertyAttribute att) where T : AbstractPropertyDrawer @@ -172,6 +180,7 @@ namespace Module.Inspector.Editor.Utilities public readonly List> predrawerModifiers; public readonly List> valueModifiers; public readonly List> accessModifiers; + public readonly List> validators; public readonly string tooltip; public readonly bool isObsolete; @@ -179,6 +188,7 @@ namespace Module.Inspector.Editor.Utilities List> predrawerModifiers, List> valueModifiers, List> accessModifiers, + List> validators, string tooltip, bool isObsolete) { @@ -186,6 +196,7 @@ namespace Module.Inspector.Editor.Utilities this.predrawerModifiers = predrawerModifiers; this.valueModifiers = valueModifiers; this.accessModifiers = accessModifiers; + this.validators = validators; this.tooltip = tooltip; this.isObsolete = isObsolete; } @@ -222,6 +233,17 @@ namespace Module.Inspector.Editor.Utilities return null; } + + public T GetValidator() where T : ValidatePropertyAttribute + { + for (var i = 0; i < validators.Count; i++) + { + if (validators[i].attribute is T att) + return att; + } + + return null; + } } /// diff --git a/Editor/ValidatePropertyDrawer.cs b/Editor/ValidatePropertyDrawer.cs new file mode 100644 index 0000000..d1f2968 --- /dev/null +++ b/Editor/ValidatePropertyDrawer.cs @@ -0,0 +1,10 @@ +using UnityEditor; + +namespace Module.Inspector.Editor +{ + public abstract class ValidatePropertyDrawer : AbstractPropertyDrawer + { + public abstract bool Validate(ValidatePropertyAttribute attribute, SerializedProperty property); + public abstract string GetValidationError(SerializedProperty property); + } +} \ No newline at end of file diff --git a/Editor/ValidatePropertyDrawer.cs.meta b/Editor/ValidatePropertyDrawer.cs.meta new file mode 100644 index 0000000..f9ea19d --- /dev/null +++ b/Editor/ValidatePropertyDrawer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 28e84b42c2e449159f7f6da42e61d926 +timeCreated: 1638625447 \ No newline at end of file diff --git a/Editor/Validators.meta b/Editor/Validators.meta new file mode 100644 index 0000000..ba50f15 --- /dev/null +++ b/Editor/Validators.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9fb7568d40b24228ad7e6988dc114052 +timeCreated: 1638625429 \ No newline at end of file diff --git a/Editor/Validators/NotNullFieldAttributeDrawer.cs b/Editor/Validators/NotNullFieldAttributeDrawer.cs new file mode 100644 index 0000000..b950b7c --- /dev/null +++ b/Editor/Validators/NotNullFieldAttributeDrawer.cs @@ -0,0 +1,50 @@ +using UnityEditor; + +namespace Module.Inspector.Editor +{ + [CustomPropertyDrawer(typeof(NotNullFieldAttribute))] + internal sealed class NotNullFieldAttributeDrawer : ValidatePropertyDrawer + { + public override bool Validate(ValidatePropertyAttribute attribute, SerializedProperty property) + { + switch (property.propertyType) + { + case SerializedPropertyType.Integer: + case SerializedPropertyType.Boolean: + case SerializedPropertyType.Float: + case SerializedPropertyType.String: + case SerializedPropertyType.Color: + case SerializedPropertyType.LayerMask: + case SerializedPropertyType.Enum: + case SerializedPropertyType.Vector2: + case SerializedPropertyType.Vector3: + case SerializedPropertyType.Vector4: + case SerializedPropertyType.Rect: + case SerializedPropertyType.ArraySize: + case SerializedPropertyType.Character: + case SerializedPropertyType.Bounds: + case SerializedPropertyType.Quaternion: + case SerializedPropertyType.Vector2Int: + case SerializedPropertyType.Vector3Int: + case SerializedPropertyType.RectInt: + case SerializedPropertyType.BoundsInt: + return true; + case SerializedPropertyType.ObjectReference: + case SerializedPropertyType.Gradient: + case SerializedPropertyType.ExposedReference: + case SerializedPropertyType.ManagedReference: + case SerializedPropertyType.FixedBufferSize: + return property.objectReferenceValue != null; + case SerializedPropertyType.AnimationCurve: + return property.animationCurveValue != null; + } + + return true; + } + + public override string GetValidationError(SerializedProperty property) + { + return "NotNullField: Value is null"; + } + } +} \ No newline at end of file diff --git a/Editor/Validators/NotNullFieldAttributeDrawer.cs.meta b/Editor/Validators/NotNullFieldAttributeDrawer.cs.meta new file mode 100644 index 0000000..58ff1f4 --- /dev/null +++ b/Editor/Validators/NotNullFieldAttributeDrawer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5e97d0a1ad0c4cc48034e3e60ef3d18f +timeCreated: 1638625437 \ No newline at end of file diff --git a/README.md b/README.md index c9af063..aaa5ef7 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ These attributes have different categories and some can be combined to create th # Base -There are five different kinds of attributes: +There are six different kinds of attributes: * Access * Modify access to drawer or value change (E.g. Hide/Show, Disable/Enable input) @@ -16,6 +16,8 @@ There are five different kinds of attributes: * Custom drawing of the field/method * Value * Modify value before setting final result (E.g. clamp value) +* Validate + * Validate field (if invalid, draws as red) * Decorator * Adds additional information or styling to a field/method (E.g. Header displays a title/category to fields after attribute) @@ -121,6 +123,15 @@ List of all value attributes: * If value is less than other fields value, then set value to other fields value +## Validate + +list of all validate attributes + +* `NotNullField` + * Checks if field is null + + + ## Decorators List of all decorator attributes: diff --git a/Runtime/Enums/EPropertyType.cs b/Runtime/Enums/EPropertyType.cs index bc56450..9b9f122 100644 --- a/Runtime/Enums/EPropertyType.cs +++ b/Runtime/Enums/EPropertyType.cs @@ -5,6 +5,7 @@ PredrawerModifier, Drawer, ValueModifier, - AccessModifier + AccessModifier, + Validate } } \ No newline at end of file diff --git a/Runtime/ValidatePropertyAttribute.cs b/Runtime/ValidatePropertyAttribute.cs new file mode 100644 index 0000000..82a0f30 --- /dev/null +++ b/Runtime/ValidatePropertyAttribute.cs @@ -0,0 +1,7 @@ +namespace Module.Inspector +{ + public abstract class ValidatePropertyAttribute : AbstractPropertyAttribute + { + public override EPropertyType Type => EPropertyType.Validate; + } +} \ No newline at end of file diff --git a/Runtime/ValidatePropertyAttribute.cs.meta b/Runtime/ValidatePropertyAttribute.cs.meta new file mode 100644 index 0000000..becbbc0 --- /dev/null +++ b/Runtime/ValidatePropertyAttribute.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8b9e492ca9c74144ab913bc4d44a3cb6 +timeCreated: 1638625294 \ No newline at end of file diff --git a/Runtime/Validators.meta b/Runtime/Validators.meta new file mode 100644 index 0000000..c29eb9f --- /dev/null +++ b/Runtime/Validators.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ae50d6f9a5924095b1622fdce766030b +timeCreated: 1638625321 \ No newline at end of file diff --git a/Runtime/Validators/NotNullFieldAttribute.cs b/Runtime/Validators/NotNullFieldAttribute.cs new file mode 100644 index 0000000..d27fb33 --- /dev/null +++ b/Runtime/Validators/NotNullFieldAttribute.cs @@ -0,0 +1,14 @@ +using System; +using UnityEngine.Scripting; + +namespace Module.Inspector +{ + [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + public class NotNullFieldAttribute : ValidatePropertyAttribute + { + [Preserve] + public NotNullFieldAttribute() + { + } + } +} \ No newline at end of file diff --git a/Runtime/Validators/NotNullFieldAttribute.cs.meta b/Runtime/Validators/NotNullFieldAttribute.cs.meta new file mode 100644 index 0000000..943f743 --- /dev/null +++ b/Runtime/Validators/NotNullFieldAttribute.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 869816e3d1fa460dbcb80195c70e8af4 +timeCreated: 1638625328 \ No newline at end of file diff --git a/package.json b/package.json index 99caab3..68c925e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "com.module.inspector", - "version": "1.0.0", + "version": "1.1.0", "displayName": "Module.Inspector", "description": "Custom inspector with various useful property drawers", "unity": "2019.2",