Skip to content

Instantly share code, notes, and snippets.

@Arakade
Last active January 24, 2018 12:28
Show Gist options
  • Save Arakade/02d101719bc8afae680d65d6330c9c5b to your computer and use it in GitHub Desktop.
Save Arakade/02d101719bc8afae680d65d6330c9c5b to your computer and use it in GitHub Desktop.
Unity3D NonNull attribute + colouring PropertyDrawer
using UnityEngine;
namespace UGS.unityutil.attributes {
/// <summary>
/// Checks non-null (and non-empty if applied to a string, non-zero if a scalar or Vector, etc) in a custom inspector.
/// Colours red if any problems.
/// </summary>
public sealed class NonNullAttribute : PropertyAttribute {
}
}
using UnityEditor;
using UnityEngine;
// Place in Editor sub-directory
namespace UGS.unityutil.attributes {
[CustomPropertyDrawer(typeof (NonNullAttribute))] // n.b. will need 2nd param 'true' if wish to use for subclasses of NonNullAttribute
public sealed class NonNullAttributePropertyDrawer : PropertyDrawer {
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
var oc = GUI.backgroundColor;
var result = isProblem(property);
if (result.HasValue) {
if (result.Value) {
GUI.backgroundColor = ColourBad;
if (string.IsNullOrEmpty(label.tooltip)) {
label.tooltip = (property.propertyType == SerializedPropertyType.String) ? "Must not be empty." : "Must not be null.";
}
}
} else { // no result = unhandled
GUI.backgroundColor = ColourUnhandled;
if (string.IsNullOrEmpty(label.tooltip)) {
label.tooltip = AttributeName + " cannot be applied to this type";
} else {
label.tooltip += "\n" + AttributeName + " cannot be applied to this type";
}
}
EditorGUI.PropertyField(position, property, label, true);
GUI.backgroundColor = oc;
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
return EditorGUI.GetPropertyHeight(property);
}
private bool? isProblem(SerializedProperty property) {
switch (property.propertyType) {
case SerializedPropertyType.String:
return string.IsNullOrEmpty(property.stringValue);
case SerializedPropertyType.Vector2:
return 0f >= property.vector2Value.sqrMagnitude;
case SerializedPropertyType.Vector2Int:
return 0f >= property.vector2IntValue.sqrMagnitude;
case SerializedPropertyType.Vector3:
return 0f >= property.vector3Value.sqrMagnitude;
case SerializedPropertyType.Vector3Int:
return 0f >= property.vector3IntValue.sqrMagnitude;
case SerializedPropertyType.Vector4:
return 0f >= property.vector4Value.sqrMagnitude;
case SerializedPropertyType.Float:
return 0f == property.floatValue;
case SerializedPropertyType.Integer:
return 0 == property.intValue;
case SerializedPropertyType.Color:
return NullColour == property.colorValue;
case SerializedPropertyType.LayerMask:
return 0 == property.intValue;
case SerializedPropertyType.ObjectReference:
return null == property.objectReferenceValue;
}
return null; // indicate not handled
}
private static readonly string AttributeName = "WARNING: " + typeof (NonNullAttribute).Name;
private static readonly Color ColourBad = new Color(1f, 0.5f, 0.5f);
private static readonly Color ColourUnhandled = new Color(1f, 0f, 0.8f);
private static readonly Color NullColour = new Color(0f, 0f, 0f, 0f);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment