123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
- #if UNITY_EDITOR
- using System.Runtime.CompilerServices;
- using UnityEditor;
- using UnityEngine;
- using Sequence = Animancer.AnimancerEvent.Sequence;
- namespace Animancer.Editor
- {
- /// <summary>[Editor-Only] Draws the Inspector GUI for a <see cref="Sequence"/>.</summary>
- /// https://kybernetik.com.au/animancer/api/Animancer.Editor/EventSequenceDrawer
- public class EventSequenceDrawer
- {
- /************************************************************************************************************************/
- private static readonly ConditionalWeakTable<Sequence, EventSequenceDrawer>
- SequenceToDrawer = new();
- /// <summary>Returns a cached <see cref="EventSequenceDrawer"/> for the `events`.</summary>
- /// <remarks>
- /// The cache uses a <see cref="ConditionalWeakTable{TKey, TValue}"/> so it doesn't prevent the `events`
- /// from being garbage collected.
- /// </remarks>
- public static EventSequenceDrawer Get(Sequence events)
- {
- if (events == null)
- return null;
- if (!SequenceToDrawer.TryGetValue(events, out var drawer))
- SequenceToDrawer.Add(events, drawer = new());
- return drawer;
- }
- /************************************************************************************************************************/
- /// <summary>Calculates the number of vertical pixels required to draw the contents of the `events`.</summary>
- public float CalculateHeight(Sequence events)
- => AnimancerGUI.CalculateHeight(CalculateLineCount(events));
- /// <summary>Calculates the number of lines required to draw the contents of the `events`.</summary>
- public int CalculateLineCount(Sequence events)
- {
- if (events == null)
- return 0;
- if (!IsExpanded)
- return 1;
- var count = 1;
- for (int i = 0; i < events.Count; i++)
- count += DelegateGUI.CalculateLineCount(events[i].callback);
- count += DelegateGUI.CalculateLineCount(events.EndEvent.callback);
- return count;
- }
- /************************************************************************************************************************/
- /// <summary>Should the target's default be shown?</summary>
- public bool IsExpanded { get; set; }
- private static ConversionCache<int, string> _EventNumberCache;
- private static float _LogButtonWidth = float.NaN;
- /************************************************************************************************************************/
- /// <summary>Draws the GUI for the `events`.</summary>
- public void DoGUI(ref Rect area, Sequence events, GUIContent label)
- {
- using (var content = PooledGUIContent.Acquire(GetSummary(events)))
- DoGUI(ref area, events, label, content);
- }
- /// <summary>Draws the GUI for the `events`.</summary>
- public void DoGUI(ref Rect area, Sequence events, GUIContent label, GUIContent summary)
- {
- if (events == null)
- return;
- area.height = AnimancerGUI.LineHeight;
- var headerArea = area;
- const string LogLabel = "Log";
- if (float.IsNaN(_LogButtonWidth))
- _LogButtonWidth = EditorStyles.miniButton.CalculateWidth(LogLabel);
- var logArea = AnimancerGUI.StealFromRight(ref headerArea, _LogButtonWidth);
- if (GUI.Button(logArea, LogLabel, EditorStyles.miniButton))
- Debug.Log(events.DeepToString());
- IsExpanded = EditorGUI.Foldout(headerArea, IsExpanded, GUIContent.none, true);
- EditorGUI.LabelField(headerArea, label, summary);
- AnimancerGUI.NextVerticalArea(ref area);
- if (!IsExpanded)
- return;
- var enabled = GUI.enabled;
- GUI.enabled = false;
- EditorGUI.indentLevel++;
- for (int i = 0; i < events.Count; i++)
- {
- var name = events.GetName(i);
- if (string.IsNullOrEmpty(name))
- {
- _EventNumberCache ??= new(index => $"Event {index}");
- name = _EventNumberCache.Convert(i);
- }
- Draw(ref area, name, events[i]);
- }
- Draw(ref area, "End Event", events.EndEvent);
- EditorGUI.indentLevel--;
- GUI.enabled = enabled;
- }
- /************************************************************************************************************************/
- private static readonly ConversionCache<int, string>
- SummaryCache = new((count) => $"[{count}]"),
- EndSummaryCache = new((count) => $"[{count}] + End");
- /// <summary>Returns a summary of the `events`.</summary>
- public static string GetSummary(Sequence events)
- {
- var cache = float.IsNaN(events.NormalizedEndTime) && AnimancerEvent.IsNullOrDummy(events.OnEnd)
- ? SummaryCache
- : EndSummaryCache;
- return cache.Convert(events.Count);
- }
- /************************************************************************************************************************/
- private static ConversionCache<float, string> _EventTimeCache;
- /// <summary>Draws the GUI for the `animancerEvent`.</summary>
- public static void Draw(ref Rect area, string name, AnimancerEvent animancerEvent)
- {
- _EventTimeCache ??= new((time)
- => float.IsNaN(time) ? "Time = Auto" : $"Time = {time.ToStringCached()}x");
- var timeText = _EventTimeCache.Convert(animancerEvent.normalizedTime);
- using (var label = PooledGUIContent.Acquire(name))
- using (var value = PooledGUIContent.Acquire(timeText))
- DelegateGUI.DoGUI(ref area, label, animancerEvent.callback, value);
- }
- /************************************************************************************************************************/
- }
- }
- #endif
|