private void AddHandlerToMap(Type handlerType, IEventSystemHandler handler) { bool isParentObjectRegistered = false; var componentHandler = handler as Component; if (componentHandler != null && EventListeners.Contains(componentHandler.gameObject)) { isParentObjectRegistered = true; WarnAboutConflictingApis(componentHandler.gameObject.name); } List <EventHandlerEntry> handlers; if (!EventHandlersByType.TryGetValue(handlerType, out handlers)) { handlers = new List <EventHandlerEntry> { new EventHandlerEntry(handler, isParentObjectRegistered) }; EventHandlersByType.Add(handlerType, handlers); return; } bool handlerExists = false; for (int i = handlers.Count - 1; i >= 0; i--) { if (handlers[i].handler == handler) { handlerExists = true; break; } } if (!handlerExists) { handlers.Add(new EventHandlerEntry(handler, isParentObjectRegistered)); } }
/// <inheritdoc /> private void RemoveHandlerFromMap(Type handlerType, IEventSystemHandler handler) { List <EventHandlerEntry> handlers; if (!EventHandlersByType.TryGetValue(handlerType, out handlers)) { return; } for (int i = handlers.Count - 1; i >= 0; i--) { if (handlers[i].handler == handler) { handlers.RemoveAt(i); } } if (handlers.Count == 0) { EventHandlersByType.Remove(handlerType); } }
/// <inheritdoc /> public virtual void HandleEvent <T>(BaseEventData eventData, ExecuteEvents.EventFunction <T> eventHandler) where T : IEventSystemHandler { Debug.Assert(!eventData.used); eventExecutionDepth++; // This sends the event to every component that implements the corresponding event handling interface, // regardless of whether it was the one registering the object as global listener or not. // This behavior is kept for backwards compatibility. Will be removed together with the IMixedRealityEventSystem.Register(GameObject listener) interface. for (int i = EventListeners.Count - 1; i >= 0; i--) { ExecuteEvents.Execute(EventListeners[i], eventData, eventHandler); } // Send events to all handlers registered via RegisterHandler API. List <EventHandlerEntry> handlers; if (EventHandlersByType.TryGetValue(typeof(T), out handlers)) { for (int i = handlers.Count - 1; i >= 0; i--) { var handlerEntry = handlers[i]; // If handler's parent is in object collection (traversed above), it has already received an event. if (handlerEntry.parentObjectIsInObjectCollection) { continue; } eventHandler.Invoke((T)handlerEntry.handler, eventData); } } eventExecutionDepth--; if (eventExecutionDepth == 0 && (postponedActions.Count > 0 || postponedObjectActions.Count > 0)) { foreach (var handler in postponedActions) { if (handler.Item1 == Action.Add) { AddHandlerToMap(handler.Item2, handler.Item3); } else if (handler.Item1 == Action.Remove) { RemoveHandlerFromMap(handler.Item2, handler.Item3); } } foreach (var obj in postponedObjectActions) { if (obj.Item1 == Action.Add) { // Can call it here, because guaranteed that eventExecutionDepth is 0 Register(obj.Item2); } else if (obj.Item1 == Action.Remove) { Unregister(obj.Item2); } } postponedActions.Clear(); postponedObjectActions.Clear(); } }
/// <inheritdoc /> public virtual void HandleEvent <T>(BaseEventData eventData, ExecuteEvents.EventFunction <T> eventHandler) where T : IEventSystemHandler { Debug.Assert(!eventData.used); eventExecutionDepth++; // This sends the event to every component that implements the corresponding event handling interface, // regardless of whether it was the one registering the object as global listener or not. // This behavior is kept for backwards compatibility. Will be removed together with the IMixedRealityEventSystem.Register(GameObject listener) interface. for (int i = EventListeners.Count - 1; i >= 0; i--) { // Ensure client code does not put the event dispatch system into a bad state. // Note that ExecuteEvents.Execute internally safeguards against exceptions, but // this is another layer to ensure that nothing below this layer can affect the state // of our eventExecutionDepth tracker. try { ExecuteEvents.Execute(EventListeners[i], eventData, eventHandler); } catch (Exception ex) { Debug.LogException(ex); } } // Send events to all handlers registered via RegisterHandler API. if (EventHandlersByType.TryGetValue(typeof(T), out List <EventHandlerEntry> handlers)) { for (int i = handlers.Count - 1; i >= 0; i--) { var handlerEntry = handlers[i]; // If handler's parent is in object collection (traversed above), it has already received an event. if (handlerEntry.parentObjectIsInObjectCollection) { continue; } // Ensure client code does not put the event dispatch system into a bad state. try { eventHandler.Invoke((T)handlerEntry.handler, eventData); } catch (Exception ex) { Debug.LogException(ex); } } } eventExecutionDepth--; if (eventExecutionDepth == 0) { int postponedActionsCount = postponedActions.Count; int postponedObjectActionsCount = postponedObjectActions.Count; if (postponedActionsCount <= 0 && postponedObjectActionsCount <= 0) { return; } for (int i = 0; i < postponedActionsCount; i++) { Tuple <Action, Type, IEventSystemHandler> handler = postponedActions[i]; if (handler.Item1 == Action.Add) { AddHandlerToMap(handler.Item2, handler.Item3); } else if (handler.Item1 == Action.Remove) { RemoveHandlerFromMap(handler.Item2, handler.Item3); } } for (int i = 0; i < postponedObjectActionsCount; i++) { Tuple <Action, GameObject> obj = postponedObjectActions[i]; if (obj.Item1 == Action.Add) { // Can call it here, because guaranteed that eventExecutionDepth is 0 Register(obj.Item2); } else if (obj.Item1 == Action.Remove) { Unregister(obj.Item2); } } postponedActions.Clear(); postponedObjectActions.Clear(); } }