| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 | // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //#if UNITY_EDITORusing System;using System.Collections.Generic;using UnityEditor;using UnityEngine;namespace Animancer.Editor{    /// <summary>[Editor-Only] An <see cref="ICustomGUI"/> for <see cref="MulticastDelegate"/>.</summary>    /// https://kybernetik.com.au/animancer/api/Animancer.Editor/DelegateGUI    [CustomGUI(typeof(MulticastDelegate))]    public class DelegateGUI : CustomGUI<MulticastDelegate>    {        /************************************************************************************************************************/        private static readonly HashSet<MulticastDelegate>            ExpandedItems = new();        /************************************************************************************************************************/        /// <summary>Calculates the number of vertical pixels required to draw the specified <see cref="MulticastDelegate"/>.</summary>        public static float CalculateHeight(MulticastDelegate del)            => AnimancerGUI.CalculateHeight(CalculateLineCount(del));        /// <summary>Calculates the number of lines required to draw the specified <see cref="MulticastDelegate"/>.</summary>        public static int CalculateLineCount(MulticastDelegate del)            => del == null || !ExpandedItems.Contains(del)            ? 1            : 1 + CalculateLineCount(AnimancerReflection.GetInvocationList(del));        /// <summary>Calculates the number of lines required to draw the specified `invocationList`.</summary>        public static int CalculateLineCount(Delegate[] invocationList)            => invocationList == null            ? 3            : invocationList.Length * 3;        /************************************************************************************************************************/        /// <inheritdoc/>        public override void DoGUI()        {            var area = AnimancerGUI.LayoutRect(CalculateHeight(Value));            DoGUI(ref area, Label, Value);        }        /// <summary>Draws the GUI for the given delegate.</summary>        public static void DoGUI(            ref Rect area,            GUIContent label,            MulticastDelegate del,            GUIContent valueLabel = null)        {            area.height = AnimancerGUI.LineHeight;            var delegates = AnimancerReflection.GetInvocationList(del);            var isExpanded = del != null && AnimancerGUI.DoHashedFoldoutGUI(area, ExpandedItems, del);            if (valueLabel != null)            {                EditorGUI.LabelField(area, label, valueLabel);            }            else            {                var count = delegates == null ? 0 : delegates.Length;                using (var countLabel = PooledGUIContent.Acquire(count.ToStringCached()))                    EditorGUI.LabelField(area, label, countLabel);            }            AnimancerGUI.NextVerticalArea(ref area);            if (!isExpanded)                return;            EditorGUI.indentLevel++;            if (delegates == null)            {                DoSingleGUI(ref area, del);            }            else            {                for (int i = 0; i < delegates.Length; i++)                    DoSingleGUI(ref area, delegates[i]);            }            EditorGUI.indentLevel--;        }        /************************************************************************************************************************/        private const int TargetFieldCacheCapacity = 128;        private static readonly Dictionary<object, FastObjectField>            TargetFieldCache = new(TargetFieldCacheCapacity);        /// <summary>Draws the target and name of the specified <see cref="Delegate"/>.</summary>        public static void DoSingleGUI(ref Rect area, Delegate del)        {            area.height = AnimancerGUI.LineHeight;            if (del == null)            {                EditorGUI.LabelField(area, "Delegate", "Null");                AnimancerGUI.NextVerticalArea(ref area);                return;            }            var method = del.Method;            EditorGUI.LabelField(area, "Method", method.ToString());            AnimancerGUI.NextVerticalArea(ref area);            EditorGUI.LabelField(area, "Declaring Type", method.DeclaringType.GetNameCS());            AnimancerGUI.NextVerticalArea(ref area);            var target = del.Target;            FastObjectField field;            if (target is not null)                TargetFieldCache.TryGetValue(target, out field);            else                field = FastObjectField.Null;            field.Draw(area, "Target", target);            if (target is not null)            {                if (TargetFieldCache.Count == TargetFieldCacheCapacity)                    TargetFieldCache.Clear();                TargetFieldCache[target] = field;            }            AnimancerGUI.NextVerticalArea(ref area);        }        /************************************************************************************************************************/    }}#endif
 |