using UnityEngine; #if UNITY_EDITOR using System.Reflection; using UnityEditor; using InspectorToolkit.EditorTools; #endif namespace InspectorToolkit { /// /// Does not work on objects with children - will break their UI /// public class RequireMethodAttribute : PropertyAttribute, IPropertyCondition { private readonly string methodName; public RequireMethodAttribute(string methodName) { this.methodName = methodName; } #if UNITY_EDITOR public bool DoesPropertyMeetCondition(SerializedProperty property, out string description) { Object target = property.serializedObject.targetObject; MethodInfo methodInfo = target.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); description = string.Empty; if (methodInfo != null && methodInfo.ReturnParameter?.ParameterType == typeof(bool)) { ParameterInfo[] methodParameters = methodInfo.GetParameters(); object[] parameterValues = null; if (methodParameters.Length == 1 && methodParameters[0].ParameterType == property.GetValue().GetType()) { parameterValues = new[] { property.GetValue() }; } object returnValue = methodInfo.Invoke(target, parameterValues); if (returnValue is bool boolReturnValue) { if (!boolReturnValue) { description = $"{property.name} is failing {methodName}."; return false; } return true; } else { description = $"{property.name} {methodName} is invalid - does not return a boolean."; return false; } } description = $"{property.name} {methodName} is invalid - no method can be found on {target}."; return false; } #endif } } #if UNITY_EDITOR namespace InspectorToolkit.Internal { [CustomPropertyDrawer(typeof(RequireMethodAttribute))] public class RequireMethodAttributePropertyDrawer : PropertyDrawer { public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { RequireMethodAttribute requireMethodAttribute = (RequireMethodAttribute)attribute; if (property.hasChildren) { EditorGUI.LabelField(position, new GUIContent(property.displayName), new GUIContent("RequireMethod GUI does not work on properties with children")); return; } Color guiColor = GUI.color; if (!requireMethodAttribute.DoesPropertyMeetCondition(property, out string description)) { RequiredUtil.LayoutRequired(ref position, description, false); RequiredUtil.DrawRequired(ref position, description, false); } label = EditorGUI.BeginProperty(position, label, property); position = EditorGUI.PrefixLabel(position, label); EditorGUI.BeginChangeCheck(); EditorGUI.PropertyField(position, property, GUIContent.none); if (EditorGUI.EndChangeCheck()) { property.serializedObject.ApplyModifiedProperties(); } EditorGUI.EndProperty(); GUI.color = guiColor; } } } #endif