123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
- #if UNITY_EDITOR
- using System;
- using UnityEditor;
- using UnityEngine;
- namespace Animancer.Editor
- {
- /// <summary>[Editor-Only]
- /// A <see cref="PropertyDrawer"/> for <see cref="IPolymorphic"/> and <see cref="PolymorphicAttribute"/>.
- /// </summary>
- /// https://kybernetik.com.au/animancer/api/Animancer.Editor/PolymorphicDrawer
- [CustomPropertyDrawer(typeof(IPolymorphic), true)]
- [CustomPropertyDrawer(typeof(PolymorphicAttribute), true)]
- public sealed class PolymorphicDrawer : PropertyDrawer
- {
- /************************************************************************************************************************/
- private bool _DrawerThrewException;
- /************************************************************************************************************************/
- /// <inheritdoc/>
- public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
- {
- var height = 0f;
- if (property.propertyType == SerializedPropertyType.ManagedReference)
- {
- GetDetails(property, out var value, out var drawer, out var details);
- if (value == null)
- return AnimancerGUI.LineHeight;
- if (drawer != null)
- {
- if (details.SeparateHeader)
- {
- if (!property.isExpanded)
- return AnimancerGUI.LineHeight;
- height += AnimancerGUI.LineHeight + AnimancerGUI.StandardSpacing;
- }
- try
- {
- height += drawer.GetPropertyHeight(property, label);
- return height;
- }
- catch (Exception exception)
- {
- _DrawerThrewException = true;
- Debug.LogException(exception, property.serializedObject.targetObject);
- // Continue to the regular calculation.
- }
- }
- }
- height += EditorGUI.GetPropertyHeight(property, label, true);
- return height;
- }
- /************************************************************************************************************************/
- /// <inheritdoc/>
- public override void OnGUI(Rect area, SerializedProperty property, GUIContent label)
- {
- if (property.propertyType != SerializedPropertyType.ManagedReference)
- {
- EditorGUI.PropertyField(area, property, label, true);
- return;
- }
- GetDetails(property, out _, out var drawer, out var details);
- var drawTypeSelectionButton = drawer == null || drawer is not IPolymorphic;
- var button = drawTypeSelectionButton
- ? new TypeSelectionButton(area, property, true)
- : default;
- if (drawer != null)
- {
- if (details.SeparateHeader)
- {
- var foldoutArea = area;
- foldoutArea.width = EditorGUIUtility.labelWidth;
- foldoutArea.height = AnimancerGUI.LineHeight;
- label = EditorGUI.BeginProperty(foldoutArea, label, property);
- property.isExpanded = EditorGUI.Foldout(foldoutArea, property.isExpanded, label, true);
- EditorGUI.EndProperty();
- area.yMin += AnimancerGUI.LineHeight + AnimancerGUI.StandardSpacing;
- }
- // If drawing a separate header, don't draw the body if it's collapsed.
- if (!details.SeparateHeader || property.isExpanded)
- {
- try
- {
- #pragma warning disable UNT0027 // Do not call PropertyDrawer.OnGUI(). Should only apply to calling base.OnGUI.
- drawer.OnGUI(area, property, label);
- #pragma warning restore UNT0027 // Do not call PropertyDrawer.OnGUI().
- }
- catch (Exception exception)
- {
- _DrawerThrewException = true;
- Debug.LogException(exception, property.serializedObject.targetObject);
- // Continue to PropertyField.
- }
- }
- }
- else
- {
- EditorGUI.PropertyField(area, property, label, true);
- }
- if (drawTypeSelectionButton)
- button.DoGUI();
- }
- /************************************************************************************************************************/
- private void GetDetails(
- SerializedProperty property,
- out object value,
- out PropertyDrawer drawer,
- out PolymorphicDrawerDetails details)
- {
- value = property.managedReferenceValue;
- if (_DrawerThrewException || value == null)
- {
- drawer = null;
- details = PolymorphicDrawerDetails.Default;
- return;
- }
- if (PropertyDrawers.TryGetDrawer(value.GetType(), fieldInfo, attribute, out drawer) &&
- drawer is PolymorphicDrawer)
- drawer = null;
- details = PolymorphicDrawerDetails.Get(value);
- }
- /************************************************************************************************************************/
- }
- }
- #endif
|