using System; using System.Collections.Generic; using UnityEngine.UI; namespace UnityEngine.EventSystems { public static class ExecuteEvents { public delegate void EventFunction(T1 handler, BaseEventData eventData); public static T ValidateEventData(BaseEventData data) where T : class { if ((data as T) == null) throw new ArgumentException(String.Format("Invalid type: {0} passed to event expecting {1}", data.GetType(), typeof(T))); return data as T; } private static readonly EventFunction s_PointerEnterHandler = Execute; private static void Execute(IPointerEnterHandler handler, BaseEventData eventData) { handler.OnPointerEnter(ValidateEventData(eventData)); } private static readonly EventFunction s_PointerExitHandler = Execute; private static void Execute(IPointerExitHandler handler, BaseEventData eventData) { handler.OnPointerExit(ValidateEventData(eventData)); } private static readonly EventFunction s_PointerDownHandler = Execute; private static void Execute(IPointerDownHandler handler, BaseEventData eventData) { handler.OnPointerDown(ValidateEventData(eventData)); } private static readonly EventFunction s_PointerUpHandler = Execute; private static void Execute(IPointerUpHandler handler, BaseEventData eventData) { handler.OnPointerUp(ValidateEventData(eventData)); } private static readonly EventFunction s_PointerClickHandler = Execute; private static void Execute(IPointerClickHandler handler, BaseEventData eventData) { handler.OnPointerClick(ValidateEventData(eventData)); } private static readonly EventFunction s_InitializePotentialDragHandler = Execute; private static void Execute(IInitializePotentialDragHandler handler, BaseEventData eventData) { handler.OnInitializePotentialDrag(ValidateEventData(eventData)); } private static readonly EventFunction s_BeginDragHandler = Execute; private static void Execute(IBeginDragHandler handler, BaseEventData eventData) { handler.OnBeginDrag(ValidateEventData(eventData)); } private static readonly EventFunction s_DragHandler = Execute; private static void Execute(IDragHandler handler, BaseEventData eventData) { handler.OnDrag(ValidateEventData(eventData)); } private static readonly EventFunction s_EndDragHandler = Execute; private static void Execute(IEndDragHandler handler, BaseEventData eventData) { handler.OnEndDrag(ValidateEventData(eventData)); } private static readonly EventFunction s_DropHandler = Execute; private static void Execute(IDropHandler handler, BaseEventData eventData) { handler.OnDrop(ValidateEventData(eventData)); } private static readonly EventFunction s_ScrollHandler = Execute; private static void Execute(IScrollHandler handler, BaseEventData eventData) { handler.OnScroll(ValidateEventData(eventData)); } private static readonly EventFunction s_UpdateSelectedHandler = Execute; private static void Execute(IUpdateSelectedHandler handler, BaseEventData eventData) { handler.OnUpdateSelected(eventData); } private static readonly EventFunction s_SelectHandler = Execute; private static void Execute(ISelectHandler handler, BaseEventData eventData) { handler.OnSelect(eventData); } private static readonly EventFunction s_DeselectHandler = Execute; private static void Execute(IDeselectHandler handler, BaseEventData eventData) { handler.OnDeselect(eventData); } private static readonly EventFunction s_MoveHandler = Execute; private static void Execute(IMoveHandler handler, BaseEventData eventData) { handler.OnMove(ValidateEventData(eventData)); } private static readonly EventFunction s_SubmitHandler = Execute; private static void Execute(ISubmitHandler handler, BaseEventData eventData) { handler.OnSubmit(eventData); } private static readonly EventFunction s_CancelHandler = Execute; private static void Execute(ICancelHandler handler, BaseEventData eventData) { handler.OnCancel(eventData); } public static EventFunction pointerEnterHandler { get { return s_PointerEnterHandler; } } public static EventFunction pointerExitHandler { get { return s_PointerExitHandler; } } public static EventFunction pointerDownHandler { get { return s_PointerDownHandler; } } public static EventFunction pointerUpHandler { get { return s_PointerUpHandler; } } public static EventFunction pointerClickHandler { get { return s_PointerClickHandler; } } public static EventFunction initializePotentialDrag { get { return s_InitializePotentialDragHandler; } } public static EventFunction beginDragHandler { get { return s_BeginDragHandler; } } public static EventFunction dragHandler { get { return s_DragHandler; } } public static EventFunction endDragHandler { get { return s_EndDragHandler; } } public static EventFunction dropHandler { get { return s_DropHandler; } } public static EventFunction scrollHandler { get { return s_ScrollHandler; } } public static EventFunction updateSelectedHandler { get { return s_UpdateSelectedHandler; } } public static EventFunction selectHandler { get { return s_SelectHandler; } } public static EventFunction deselectHandler { get { return s_DeselectHandler; } } public static EventFunction moveHandler { get { return s_MoveHandler; } } public static EventFunction submitHandler { get { return s_SubmitHandler; } } public static EventFunction cancelHandler { get { return s_CancelHandler; } } private static void GetEventChain(GameObject root, IList eventChain) { eventChain.Clear(); if (root == null) return; var t = root.transform; while (t != null) { eventChain.Add(t); t = t.parent; } } private static readonly ObjectPool> s_HandlerListPool = new ObjectPool>(null, l => l.Clear()); public static bool Execute(GameObject target, BaseEventData eventData, EventFunction functor) where T : IEventSystemHandler { var internalHandlers = s_HandlerListPool.Get(); GetEventList(target, internalHandlers); // if (s_InternalHandlers.Count > 0) // Debug.Log("Executinng " + typeof (T) + " on " + target); for (var i = 0; i < internalHandlers.Count; i++) { T arg; try { arg = (T)internalHandlers[i]; } catch (Exception e) { var temp = internalHandlers[i]; Debug.LogException(new Exception(string.Format("Type {0} expected {1} received.", typeof(T).Name, temp.GetType().Name), e)); continue; } try { functor(arg, eventData); } catch (Exception e) { Debug.LogException(e); } } var handlerCount = internalHandlers.Count; s_HandlerListPool.Release(internalHandlers); return handlerCount > 0; } /// /// Execute the specified event on the first game object underneath the current touch. /// private static readonly List s_InternalTransformList = new List(30); public static GameObject ExecuteHierarchy(GameObject root, BaseEventData eventData, EventFunction callbackFunction) where T : IEventSystemHandler { GetEventChain(root, s_InternalTransformList); for (var i = 0; i < s_InternalTransformList.Count; i++) { var transform = s_InternalTransformList[i]; if (Execute(transform.gameObject, eventData, callbackFunction)) return transform.gameObject; } return null; } private static bool ShouldSendToComponent(Component component) where T : IEventSystemHandler { var valid = component is T; if (!valid) return false; var behaviour = component as Behaviour; if (behaviour != null) return behaviour.isActiveAndEnabled; return true; } /// /// Get the specified object's event event. /// private static void GetEventList(GameObject go, IList results) where T : IEventSystemHandler { // Debug.LogWarning("GetEventList<" + typeof(T).Name + ">"); if (results == null) throw new ArgumentException("Results array is null", "results"); if (go == null || !go.activeInHierarchy) return; var components = ListPool.Get(); go.GetComponents(components); for (var i = 0; i < components.Count; i++) { if (!ShouldSendToComponent(components[i])) continue; // Debug.Log(string.Format("{2} found! On {0}.{1}", go, s_GetComponentsScratch[i].GetType(), typeof(T))); results.Add(components[i] as IEventSystemHandler); } ListPool.Release(components); // Debug.LogWarning("end GetEventList<" + typeof(T).Name + ">"); } /// /// Whether the specified game object will be able to handle the specified event. /// public static bool CanHandleEvent(GameObject go) where T : IEventSystemHandler { var internalHandlers = s_HandlerListPool.Get(); GetEventList(go, internalHandlers); var handlerCount = internalHandlers.Count; s_HandlerListPool.Release(internalHandlers); return handlerCount != 0; } /// /// Bubble the specified event on the game object, figuring out which object will actually receive the event. /// public static GameObject GetEventHandler(GameObject root) where T : IEventSystemHandler { if (root == null) return null; Transform t = root.transform; while (t != null) { if (CanHandleEvent(t.gameObject)) return t.gameObject; t = t.parent; } return null; } } }