diff options
author | chai <chaifix@163.com> | 2021-05-08 23:15:13 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2021-05-08 23:15:13 +0800 |
commit | d07e14add74e017b52ab2371efeea1aa4ea10ced (patch) | |
tree | efd07869326e4c428f5bfe43fad0c2583d32a401 /Assets/uGUI-2017.1/Editor/UI/InterceptedEventsPreview.cs |
+init
Diffstat (limited to 'Assets/uGUI-2017.1/Editor/UI/InterceptedEventsPreview.cs')
-rw-r--r-- | Assets/uGUI-2017.1/Editor/UI/InterceptedEventsPreview.cs | 304 |
1 files changed, 304 insertions, 0 deletions
diff --git a/Assets/uGUI-2017.1/Editor/UI/InterceptedEventsPreview.cs b/Assets/uGUI-2017.1/Editor/UI/InterceptedEventsPreview.cs new file mode 100644 index 0000000..b02e37e --- /dev/null +++ b/Assets/uGUI-2017.1/Editor/UI/InterceptedEventsPreview.cs @@ -0,0 +1,304 @@ +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))] + 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 = new Styles(); + + public override void Initialize(UnityEngine.Object[] targets) + { + Profiler.BeginSample("ComponentInterceptedEvents.Initialize"); + + base.Initialize(targets); + m_TargetEvents = new Dictionary<GameObject, List<ComponentInterceptedEvents>>(targets.Count()); + 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 = new GUIContent("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>>(); + + foreach (var type in GetAccessibleTypesInLoadedAssemblies()) + { + if (!type.IsInterface) + continue; + + if (!typeof(IEventSystemHandler).IsAssignableFrom(type)) + 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); + } + } + + private static IEnumerable<Type> GetAccessibleTypesInLoadedAssemblies() + { + var assemblies = AppDomain.CurrentDomain.GetAssemblies(); + for (var i = 0; i < assemblies.Length; ++i) + { + Type[] types; + var assembly = assemblies[i]; + + if (assembly == null) + continue; + + try + { + types = assembly.GetTypes(); + } + catch (ReflectionTypeLoadException e) + { + // assembly.GetTypes() might fail in case the Assembly cannot resolve all its references, + // or in case it was built targetting a newer version of .NET. + // In case the resolution fails for some types, we can still access the ones that have been + // properly loaded. + types = e.Types; + } + + for (var j = 0; j < types.Length; ++j) + { + var type = types[j]; + if (type == null) + continue; + + yield return type; + } + } + } + } +} |