using System; using System.Reflection; using UnityEngine; using UnityEditor; using UnityEngine.Rendering.Universal; namespace UnityEditor.Rendering.Universal { /// /// Class Provider2D_ProperyDrawer is the default property drawer for all shadow providers and will render the providers serialized properties /// /// [CustomPropertyDrawer(typeof(Provider2D), true)] public class Provider2D_ProperyDrawer : PropertyDrawer { delegate void ProcessChild(SerializedProperty child); bool IsChildVisible(Type parentType, SerializedProperty child) { // Check to see if the child is public and not hidden in the inspector FieldInfo fieldInfoPublic = parentType.GetField(child.name, BindingFlags.Public | BindingFlags.Instance); bool publicAndVisible = fieldInfoPublic != null && ((fieldInfoPublic.GetCustomAttribute() == null) || (fieldInfoPublic.GetCustomAttribute() == null)); bool privateButVisible = false; if (fieldInfoPublic == null) { // Check to see if the child is a private m FieldInfo fieldInfoNonPublic = parentType.GetField(child.name, BindingFlags.NonPublic | BindingFlags.Instance); privateButVisible = fieldInfoNonPublic != null && (fieldInfoNonPublic.GetCustomAttribute() != null); } return publicAndVisible || privateButVisible; } void ProcessProviderChildren(SerializedProperty parentProperty, ProcessChild onProcessChild) { if (parentProperty == null) return; // 1. Get the type and the starting depth Type parentType = parentProperty.boxedValue?.GetType(); SerializedProperty iterator = parentProperty.Copy(); int rootDepth = iterator.depth; // 2. The loop condition: // - NextVisible(true) moves to the next property (descending into children) // - iterator.depth > rootDepth ensures we haven't climbed back out to a sibling while (iterator.NextVisible(true) && iterator.depth > rootDepth) { if (IsChildVisible(parentType, iterator)) { onProcessChild(iterator); } } } /// /// Gets the name to be listed in the ShadowCaster2D Casting Option drop down. /// /// Rectangle on the screen to use for the property GUI. /// The SerializedProperty to make the custom GUI for. /// The label of this property. public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label) { ProcessProviderChildren(property, (SerializedProperty child) => { rect.height = EditorGUIUtility.singleLineHeight; EditorGUI.PropertyField(rect, child, true); float height = EditorGUI.GetPropertyHeight(child, includeChildren: true); rect.y += EditorGUIUtility.standardVerticalSpacing + height; }); } /// /// Gets the name to be listed in the ShadowCaster2D Casting Option drop down. /// /// The SerializedProperty to make the custom GUI for. /// The label of this property. /// The float height in pixels. public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { float height = 0; ProcessProviderChildren(property, (SerializedProperty child) => { float propHeight = EditorGUI.GetPropertyHeight(child, includeChildren: true); height += EditorGUIUtility.standardVerticalSpacing + propHeight; }); return height; } } }