123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
- #if UNITY_EDITOR
- using 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
|