123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Reflection;
- using UnityEngine;
- using UnityEngine.Profiling;
- using UnityEngine.EventSystems;
-
- namespace UnityEditor.Events
- {
- [CustomPreview(typeof(GameObject))]
- /// <summary>
- /// Custom preview drawing that will draw the intercepted events of a given object.
- /// </summary>
- class InterceptedEventsPreview : ObjectPreview
- {
- protected class ComponentInterceptedEvents
- {
- public GUIContent componentName;
- public int[] interceptedEvents;
- }
-
- class Styles
- {
- public GUIStyle labelStyle = new GUIStyle(EditorStyles.label);
- public GUIStyle componentName = new GUIStyle(EditorStyles.boldLabel);
-
- public Styles()
- {
- Color fontColor = new Color(0.7f, 0.7f, 0.7f);
- labelStyle.padding.right += 20;
- labelStyle.normal.textColor = fontColor;
- labelStyle.active.textColor = fontColor;
- labelStyle.focused.textColor = fontColor;
- labelStyle.hover.textColor = fontColor;
- labelStyle.onNormal.textColor = fontColor;
- labelStyle.onActive.textColor = fontColor;
- labelStyle.onFocused.textColor = fontColor;
- labelStyle.onHover.textColor = fontColor;
-
- componentName.normal.textColor = fontColor;
- componentName.active.textColor = fontColor;
- componentName.focused.textColor = fontColor;
- componentName.hover.textColor = fontColor;
- componentName.onNormal.textColor = fontColor;
- componentName.onActive.textColor = fontColor;
- componentName.onFocused.textColor = fontColor;
- componentName.onHover.textColor = fontColor;
- }
- }
-
- private Dictionary<GameObject, List<ComponentInterceptedEvents>> m_TargetEvents;
- private bool m_InterceptsAnyEvent = false;
- private GUIContent m_Title;
- private Styles m_Styles;
-
- public override void Initialize(UnityEngine.Object[] targets)
- {
- Profiler.BeginSample("ComponentInterceptedEvents.Initialize");
-
- base.Initialize(targets);
- m_TargetEvents = new Dictionary<GameObject, List<ComponentInterceptedEvents>>(targets.Length);
- m_InterceptsAnyEvent = false;
- for (int i = 0; i < targets.Length; ++i)
- {
- GameObject go = targets[i] as GameObject;
- List<ComponentInterceptedEvents> interceptedEvents = GetEventsInfo(go);
- m_TargetEvents.Add(go, interceptedEvents);
- if (interceptedEvents.Any())
- m_InterceptsAnyEvent = true;
- }
- Profiler.EndSample();
- }
-
- public override GUIContent GetPreviewTitle()
- {
- if (m_Title == null)
- {
- m_Title = EditorGUIUtility.TrTextContent("Intercepted Events");
- }
- return m_Title;
- }
-
- public override bool HasPreviewGUI()
- {
- return m_TargetEvents != null && m_InterceptsAnyEvent;
- }
-
- public override void OnPreviewGUI(Rect r, GUIStyle background)
- {
- if (Event.current.type != EventType.Repaint)
- return;
- Profiler.BeginSample("InterceptedEventsPreview.OnPreviewGUI");
-
-
- if (m_Styles == null)
- m_Styles = new Styles();
-
- Vector2 maxEventLabelSize = Vector2.zero;
- int totalInterceptedEvents = 0;
-
- List<ComponentInterceptedEvents> componentIncerceptedEvents = m_TargetEvents[target as GameObject];
-
- // Find out the maximum size needed for any given label.
- foreach (ComponentInterceptedEvents componentInterceptedEvents in componentIncerceptedEvents)
- {
- foreach (int eventIndex in componentInterceptedEvents.interceptedEvents)
- {
- GUIContent eventContent = s_PossibleEvents[eventIndex];
- ++totalInterceptedEvents;
- Vector2 labelSize = m_Styles.labelStyle.CalcSize(eventContent);
- if (maxEventLabelSize.x < labelSize.x)
- {
- maxEventLabelSize.x = labelSize.x;
- }
- if (maxEventLabelSize.y < labelSize.y)
- {
- maxEventLabelSize.y = labelSize.y;
- }
- }
- }
-
- // Apply padding
- RectOffset previewPadding = new RectOffset(-5, -5, -5, -5);
- r = previewPadding.Add(r);
-
- // Figure out how many rows and columns we can/should have
- int columns = Mathf.Max(Mathf.FloorToInt(r.width / maxEventLabelSize.x), 1);
- int rows = Mathf.Max(totalInterceptedEvents / columns, 1) + componentIncerceptedEvents.Count;
-
- // Centering
- float initialX = r.x + Mathf.Max(0, (r.width - (maxEventLabelSize.x * columns)) / 2);
- float initialY = r.y + Mathf.Max(0, (r.height - (maxEventLabelSize.y * rows)) / 2);
-
- Rect labelRect = new Rect(initialX, initialY, maxEventLabelSize.x, maxEventLabelSize.y);
- int currentColumn = 0;
- foreach (ComponentInterceptedEvents componentInterceptedEvents in componentIncerceptedEvents)
- {
- GUI.Label(labelRect, componentInterceptedEvents.componentName, m_Styles.componentName);
- labelRect.y += labelRect.height;
- labelRect.x = initialX;
- foreach (int eventIndex in componentInterceptedEvents.interceptedEvents)
- {
- GUIContent eventContent = s_PossibleEvents[eventIndex];
- GUI.Label(labelRect, eventContent, m_Styles.labelStyle);
- if (currentColumn < columns - 1)
- {
- labelRect.x += labelRect.width;
- }
- else
- {
- labelRect.y += labelRect.height;
- labelRect.x = initialX;
- }
-
- currentColumn = (currentColumn + 1) % columns;
- }
-
- if (labelRect.x != initialX)
- {
- labelRect.y += labelRect.height;
- labelRect.x = initialX;
- }
- }
- Profiler.EndSample();
- }
-
- //Lookup cache to avoid recalculating which types uses which events:
- //Caches all interfaces that inherit from IEventSystemHandler
- static List<Type> s_EventSystemInterfaces = null;
- //Caches all GUIContents in a single list to avoid creating too much GUIContent and strings.
- private static List<GUIContent> s_PossibleEvents = null;
- //Caches all events used by each interface
- static Dictionary<Type, List<int>> s_InterfaceEventSystemEvents = null;
- //Caches each concrete type and it's events
- static readonly Dictionary<Type, ComponentInterceptedEvents> s_ComponentEvents2 = new Dictionary<Type, ComponentInterceptedEvents>();
-
-
- protected static List<ComponentInterceptedEvents> GetEventsInfo(GameObject gameObject)
- {
- InitializeEvetnsInterfaceCacheIfNeeded();
-
- List<ComponentInterceptedEvents> componentEvents = new List<ComponentInterceptedEvents>();
-
- MonoBehaviour[] mbs = gameObject.GetComponents<MonoBehaviour>();
-
- for (int i = 0, imax = mbs.Length; i < imax; ++i)
- {
- ComponentInterceptedEvents componentEvent = null;
-
- MonoBehaviour mb = mbs[i];
- if (mb == null)
- continue;
-
- Type type = mb.GetType();
-
- if (!s_ComponentEvents2.ContainsKey(type))
- {
- List<int> events = null;
- Profiler.BeginSample("ComponentInterceptedEvents.GetEventsInfo.NewType");
- if (typeof(IEventSystemHandler).IsAssignableFrom(type))
- {
- for (int index = 0; index < s_EventSystemInterfaces.Count; index++)
- {
- var eventInterface = s_EventSystemInterfaces[index];
- if (!eventInterface.IsAssignableFrom(type))
- continue;
-
- if (events == null)
- events = new List<int>();
-
- events.AddRange(s_InterfaceEventSystemEvents[eventInterface]);
- }
- }
-
- if (events != null)
- {
- componentEvent = new ComponentInterceptedEvents();
- componentEvent.componentName = new GUIContent(type.Name);
- componentEvent.interceptedEvents = events.OrderBy(index => s_PossibleEvents[index].text).ToArray();
- }
- s_ComponentEvents2.Add(type, componentEvent);
-
- Profiler.EndSample();
- }
- else
- {
- componentEvent = s_ComponentEvents2[type];
- }
-
-
- if (componentEvent != null)
- {
- componentEvents.Add(componentEvent);
- }
- }
-
- return componentEvents;
- }
-
- private static void InitializeEvetnsInterfaceCacheIfNeeded()
- {
- if (s_EventSystemInterfaces != null)
- return;
-
- s_EventSystemInterfaces = new List<Type>();
- s_PossibleEvents = new List<GUIContent>();
- s_InterfaceEventSystemEvents = new Dictionary<Type, List<int>>();
-
- TypeCache.TypeCollection types = TypeCache.GetTypesDerivedFrom<IEventSystemHandler>();
- foreach (var type in types)
- {
- if (!type.IsInterface)
- continue;
-
- s_EventSystemInterfaces.Add(type);
- List<int> eventIndexList = new List<int>();
-
- MethodInfo[] methodInfos = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
- for (int mi = 0; mi < methodInfos.Length; mi++)
- {
- MethodInfo methodInfo = methodInfos[mi];
- eventIndexList.Add(s_PossibleEvents.Count);
- s_PossibleEvents.Add(new GUIContent(methodInfo.Name));
- }
- s_InterfaceEventSystemEvents.Add(type, eventIndexList);
- }
- }
- }
- }
|