暂无描述
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

InterceptedEventsPreview.cs 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reflection;
  5. using UnityEngine;
  6. using UnityEngine.Profiling;
  7. using UnityEngine.EventSystems;
  8. namespace UnityEditor.Events
  9. {
  10. [CustomPreview(typeof(GameObject))]
  11. /// <summary>
  12. /// Custom preview drawing that will draw the intercepted events of a given object.
  13. /// </summary>
  14. class InterceptedEventsPreview : ObjectPreview
  15. {
  16. protected class ComponentInterceptedEvents
  17. {
  18. public GUIContent componentName;
  19. public int[] interceptedEvents;
  20. }
  21. class Styles
  22. {
  23. public GUIStyle labelStyle = new GUIStyle(EditorStyles.label);
  24. public GUIStyle componentName = new GUIStyle(EditorStyles.boldLabel);
  25. public Styles()
  26. {
  27. Color fontColor = new Color(0.7f, 0.7f, 0.7f);
  28. labelStyle.padding.right += 20;
  29. labelStyle.normal.textColor = fontColor;
  30. labelStyle.active.textColor = fontColor;
  31. labelStyle.focused.textColor = fontColor;
  32. labelStyle.hover.textColor = fontColor;
  33. labelStyle.onNormal.textColor = fontColor;
  34. labelStyle.onActive.textColor = fontColor;
  35. labelStyle.onFocused.textColor = fontColor;
  36. labelStyle.onHover.textColor = fontColor;
  37. componentName.normal.textColor = fontColor;
  38. componentName.active.textColor = fontColor;
  39. componentName.focused.textColor = fontColor;
  40. componentName.hover.textColor = fontColor;
  41. componentName.onNormal.textColor = fontColor;
  42. componentName.onActive.textColor = fontColor;
  43. componentName.onFocused.textColor = fontColor;
  44. componentName.onHover.textColor = fontColor;
  45. }
  46. }
  47. private Dictionary<GameObject, List<ComponentInterceptedEvents>> m_TargetEvents;
  48. private bool m_InterceptsAnyEvent = false;
  49. private GUIContent m_Title;
  50. private Styles m_Styles;
  51. public override void Initialize(UnityEngine.Object[] targets)
  52. {
  53. Profiler.BeginSample("ComponentInterceptedEvents.Initialize");
  54. base.Initialize(targets);
  55. m_TargetEvents = new Dictionary<GameObject, List<ComponentInterceptedEvents>>(targets.Length);
  56. m_InterceptsAnyEvent = false;
  57. for (int i = 0; i < targets.Length; ++i)
  58. {
  59. GameObject go = targets[i] as GameObject;
  60. List<ComponentInterceptedEvents> interceptedEvents = GetEventsInfo(go);
  61. m_TargetEvents.Add(go, interceptedEvents);
  62. if (interceptedEvents.Any())
  63. m_InterceptsAnyEvent = true;
  64. }
  65. Profiler.EndSample();
  66. }
  67. public override GUIContent GetPreviewTitle()
  68. {
  69. if (m_Title == null)
  70. {
  71. m_Title = EditorGUIUtility.TrTextContent("Intercepted Events");
  72. }
  73. return m_Title;
  74. }
  75. public override bool HasPreviewGUI()
  76. {
  77. return m_TargetEvents != null && m_InterceptsAnyEvent;
  78. }
  79. public override void OnPreviewGUI(Rect r, GUIStyle background)
  80. {
  81. if (Event.current.type != EventType.Repaint)
  82. return;
  83. Profiler.BeginSample("InterceptedEventsPreview.OnPreviewGUI");
  84. if (m_Styles == null)
  85. m_Styles = new Styles();
  86. Vector2 maxEventLabelSize = Vector2.zero;
  87. int totalInterceptedEvents = 0;
  88. List<ComponentInterceptedEvents> componentIncerceptedEvents = m_TargetEvents[target as GameObject];
  89. // Find out the maximum size needed for any given label.
  90. foreach (ComponentInterceptedEvents componentInterceptedEvents in componentIncerceptedEvents)
  91. {
  92. foreach (int eventIndex in componentInterceptedEvents.interceptedEvents)
  93. {
  94. GUIContent eventContent = s_PossibleEvents[eventIndex];
  95. ++totalInterceptedEvents;
  96. Vector2 labelSize = m_Styles.labelStyle.CalcSize(eventContent);
  97. if (maxEventLabelSize.x < labelSize.x)
  98. {
  99. maxEventLabelSize.x = labelSize.x;
  100. }
  101. if (maxEventLabelSize.y < labelSize.y)
  102. {
  103. maxEventLabelSize.y = labelSize.y;
  104. }
  105. }
  106. }
  107. // Apply padding
  108. RectOffset previewPadding = new RectOffset(-5, -5, -5, -5);
  109. r = previewPadding.Add(r);
  110. // Figure out how many rows and columns we can/should have
  111. int columns = Mathf.Max(Mathf.FloorToInt(r.width / maxEventLabelSize.x), 1);
  112. int rows = Mathf.Max(totalInterceptedEvents / columns, 1) + componentIncerceptedEvents.Count;
  113. // Centering
  114. float initialX = r.x + Mathf.Max(0, (r.width - (maxEventLabelSize.x * columns)) / 2);
  115. float initialY = r.y + Mathf.Max(0, (r.height - (maxEventLabelSize.y * rows)) / 2);
  116. Rect labelRect = new Rect(initialX, initialY, maxEventLabelSize.x, maxEventLabelSize.y);
  117. int currentColumn = 0;
  118. foreach (ComponentInterceptedEvents componentInterceptedEvents in componentIncerceptedEvents)
  119. {
  120. GUI.Label(labelRect, componentInterceptedEvents.componentName, m_Styles.componentName);
  121. labelRect.y += labelRect.height;
  122. labelRect.x = initialX;
  123. foreach (int eventIndex in componentInterceptedEvents.interceptedEvents)
  124. {
  125. GUIContent eventContent = s_PossibleEvents[eventIndex];
  126. GUI.Label(labelRect, eventContent, m_Styles.labelStyle);
  127. if (currentColumn < columns - 1)
  128. {
  129. labelRect.x += labelRect.width;
  130. }
  131. else
  132. {
  133. labelRect.y += labelRect.height;
  134. labelRect.x = initialX;
  135. }
  136. currentColumn = (currentColumn + 1) % columns;
  137. }
  138. if (labelRect.x != initialX)
  139. {
  140. labelRect.y += labelRect.height;
  141. labelRect.x = initialX;
  142. }
  143. }
  144. Profiler.EndSample();
  145. }
  146. //Lookup cache to avoid recalculating which types uses which events:
  147. //Caches all interfaces that inherit from IEventSystemHandler
  148. static List<Type> s_EventSystemInterfaces = null;
  149. //Caches all GUIContents in a single list to avoid creating too much GUIContent and strings.
  150. private static List<GUIContent> s_PossibleEvents = null;
  151. //Caches all events used by each interface
  152. static Dictionary<Type, List<int>> s_InterfaceEventSystemEvents = null;
  153. //Caches each concrete type and it's events
  154. static readonly Dictionary<Type, ComponentInterceptedEvents> s_ComponentEvents2 = new Dictionary<Type, ComponentInterceptedEvents>();
  155. protected static List<ComponentInterceptedEvents> GetEventsInfo(GameObject gameObject)
  156. {
  157. InitializeEvetnsInterfaceCacheIfNeeded();
  158. List<ComponentInterceptedEvents> componentEvents = new List<ComponentInterceptedEvents>();
  159. MonoBehaviour[] mbs = gameObject.GetComponents<MonoBehaviour>();
  160. for (int i = 0, imax = mbs.Length; i < imax; ++i)
  161. {
  162. ComponentInterceptedEvents componentEvent = null;
  163. MonoBehaviour mb = mbs[i];
  164. if (mb == null)
  165. continue;
  166. Type type = mb.GetType();
  167. if (!s_ComponentEvents2.ContainsKey(type))
  168. {
  169. List<int> events = null;
  170. Profiler.BeginSample("ComponentInterceptedEvents.GetEventsInfo.NewType");
  171. if (typeof(IEventSystemHandler).IsAssignableFrom(type))
  172. {
  173. for (int index = 0; index < s_EventSystemInterfaces.Count; index++)
  174. {
  175. var eventInterface = s_EventSystemInterfaces[index];
  176. if (!eventInterface.IsAssignableFrom(type))
  177. continue;
  178. if (events == null)
  179. events = new List<int>();
  180. events.AddRange(s_InterfaceEventSystemEvents[eventInterface]);
  181. }
  182. }
  183. if (events != null)
  184. {
  185. componentEvent = new ComponentInterceptedEvents();
  186. componentEvent.componentName = new GUIContent(type.Name);
  187. componentEvent.interceptedEvents = events.OrderBy(index => s_PossibleEvents[index].text).ToArray();
  188. }
  189. s_ComponentEvents2.Add(type, componentEvent);
  190. Profiler.EndSample();
  191. }
  192. else
  193. {
  194. componentEvent = s_ComponentEvents2[type];
  195. }
  196. if (componentEvent != null)
  197. {
  198. componentEvents.Add(componentEvent);
  199. }
  200. }
  201. return componentEvents;
  202. }
  203. private static void InitializeEvetnsInterfaceCacheIfNeeded()
  204. {
  205. if (s_EventSystemInterfaces != null)
  206. return;
  207. s_EventSystemInterfaces = new List<Type>();
  208. s_PossibleEvents = new List<GUIContent>();
  209. s_InterfaceEventSystemEvents = new Dictionary<Type, List<int>>();
  210. TypeCache.TypeCollection types = TypeCache.GetTypesDerivedFrom<IEventSystemHandler>();
  211. foreach (var type in types)
  212. {
  213. if (!type.IsInterface)
  214. continue;
  215. s_EventSystemInterfaces.Add(type);
  216. List<int> eventIndexList = new List<int>();
  217. MethodInfo[] methodInfos = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
  218. for (int mi = 0; mi < methodInfos.Length; mi++)
  219. {
  220. MethodInfo methodInfo = methodInfos[mi];
  221. eventIndexList.Add(s_PossibleEvents.Count);
  222. s_PossibleEvents.Add(new GUIContent(methodInfo.Name));
  223. }
  224. s_InterfaceEventSystemEvents.Add(type, eventIndexList);
  225. }
  226. }
  227. }
  228. }