using System; using System.Collections; using System.Collections.Generic; using UnityEngine; #if UNITY_EDITOR using System.Reflection; using UnityEditor; #endif namespace Jovian.InspectorTools { [AttributeUsage(AttributeTargets.Field)] public abstract class ArrayAttribute : Attribute { #if UNITY_EDITOR public virtual void OnPreGUI(ref Rect position, SerializedProperty property, ref GUIContent label) { } public virtual void OnPostGUI(ref Rect position, SerializedProperty property, ref GUIContent label) { } #endif } #if UNITY_EDITOR public static class ArrayAttributePropertyHandler { public static bool DrawArrayProperty(SerializedProperty property) { return DrawArrayProperty(property, new GUIContent(ObjectNames.NicifyVariableName(property.name), property.tooltip), true ); } public static bool DrawArrayProperty(SerializedProperty property, GUIContent label, bool includeChildren, params GUILayoutOption[] options) { Rect rect = EditorGUILayout.GetControlRect(LabelHasContent(label), EditorGUI.GetPropertyHeight(property, label, includeChildren), options); bool hasArrayAttributes = TryGetAttributes(property, true, out List arrayAttributes); bool isGuiEnabled = GUI.enabled; Color contentColor = GUI.contentColor; Color backgroundColor = GUI.backgroundColor; Color guiColor = GUI.color; Rect preRect = new Rect(rect); Rect postRect = new Rect(rect); if (hasArrayAttributes) { foreach (ArrayAttribute arrayAttribute in arrayAttributes) { arrayAttribute.OnPreGUI(ref preRect, property, ref label); } } bool hasChildPropertiesNotShown = EditorGUI.PropertyField(preRect, property, label, includeChildren); if (hasArrayAttributes) { foreach (ArrayAttribute arrayAttribute in arrayAttributes) { arrayAttribute.OnPostGUI(ref postRect, property, ref label); } } GUI.enabled = isGuiEnabled; GUI.contentColor = contentColor; GUI.backgroundColor = backgroundColor; GUI.color = guiColor; return hasChildPropertiesNotShown; } private static bool LabelHasContent(GUIContent label) { return label == null || label.text != string.Empty || (UnityEngine.Object) label.image != (UnityEngine.Object) null; } public static bool TryGetAttributes(SerializedProperty serializedProperty, bool inherit, out List attributes) where TAttribute : Attribute { if(serializedProperty == null) { throw new ArgumentNullException(nameof(serializedProperty)); } Type targetObjectType = serializedProperty.serializedObject.targetObject.GetType(); if(targetObjectType == null) { throw new ArgumentException($"Could not find the {nameof(targetObjectType)} of {nameof(serializedProperty)}"); } attributes = new List(); foreach(string pathSegment in serializedProperty.propertyPath.Split('.')) { FieldInfo fieldInfo = targetObjectType.GetRuntimeField(pathSegment); if(fieldInfo != null) { IEnumerable fieldAttributes = fieldInfo.GetCustomAttributes(inherit); foreach (TAttribute fieldAttribute in fieldAttributes) { attributes.Add(fieldAttribute); } } PropertyInfo propertyInfo = targetObjectType.GetRuntimeProperty(pathSegment); if(propertyInfo != null) { IEnumerable fieldAttributes = propertyInfo.GetCustomAttributes(inherit); foreach (TAttribute fieldAttribute in fieldAttributes) { attributes.Add(fieldAttribute); } } } return attributes.Count > 0; } } #endif }