@@ -250,18 +250,49 @@ public override void HandleEvent<T>(BaseEventData eventData, ExecuteEvents.Event
250250 }
251251
252252 Debug . Assert ( eventData != null ) ;
253+ Debug . Assert ( ! ( eventData is MixedRealityPointerEventData ) , "HandleEvent called with a pointer event. All events raised by pointer should call HandlePointerEvent" ) ;
254+
253255 var baseInputEventData = ExecuteEvents . ValidateEventData < BaseInputEventData > ( eventData ) ;
254- Debug . Assert ( baseInputEventData != null ) ;
255- Debug . Assert ( ! baseInputEventData . used ) ;
256+ DispatchEventToGlobalListeners ( baseInputEventData , eventHandler ) ;
256257
257- if ( baseInputEventData . InputSource == null )
258+ if ( baseInputEventData . used )
258259 {
259- Debug . LogError ( $ "Failed to find an input source for { baseInputEventData } ") ;
260+ // All global listeners get a chance to see the event,
261+ // but if any of them marked it used,
262+ // we stop the event from going any further.
260263 return ;
261264 }
262265
263- // Send the event to global listeners
264- base . HandleEvent ( eventData , eventHandler ) ;
266+ Debug . Assert ( baseInputEventData . InputSource . Pointers != null , $ "InputSource { baseInputEventData . InputSource . SourceName } doesn't have any registered pointers! Input Sources without pointers should use the GazeProvider's pointer as a default fallback.") ;
267+
268+ var modalEventHandled = false ;
269+ // Get the focused object for each pointer of the event source
270+ for ( int i = 0 ; i < baseInputEventData . InputSource . Pointers . Length && ! baseInputEventData . used ; i ++ )
271+ {
272+ modalEventHandled = DispatchEventToObjectFocusedByPointer ( baseInputEventData . InputSource . Pointers [ i ] , baseInputEventData , modalEventHandled , eventHandler ) ;
273+ }
274+
275+ if ( ! baseInputEventData . used )
276+ {
277+ DispatchEventToFallbackHandlers ( baseInputEventData , eventHandler ) ;
278+ }
279+ }
280+
281+ /// <summary>
282+ /// Handles a pointer event
283+ /// Assumption: We only send pointer events to the objects that pointers are focusing, except for global event listeners (which listen to everything)
284+ /// In contract, all other events get sent to all other pointers attached to a given input source
285+ /// </summary>
286+ private void HandlePointerEvent < T > ( BaseEventData eventData , ExecuteEvents . EventFunction < T > eventHandler ) where T : IMixedRealityPointerHandler
287+ {
288+ if ( disabledRefCount > 0 )
289+ {
290+ return ;
291+ }
292+
293+ Debug . Assert ( eventData != null ) ;
294+ var baseInputEventData = ExecuteEvents . ValidateEventData < BaseInputEventData > ( eventData ) ;
295+ DispatchEventToGlobalListeners ( baseInputEventData , eventHandler ) ;
265296
266297 if ( baseInputEventData . used )
267298 {
@@ -271,70 +302,86 @@ public override void HandleEvent<T>(BaseEventData eventData, ExecuteEvents.Event
271302 return ;
272303 }
273304
274- if ( baseInputEventData . InputSource . Pointers == null )
305+ Debug . Assert ( pointerEventData . Pointer != null , "Trying to dispatch event on pointer but pointerEventData is null" ) ;
306+
307+ DispatchEventToObjectFocusedByPointer ( pointerEventData . Pointer , baseInputEventData , false , eventHandler ) ;
308+
309+ if ( ! baseInputEventData . used )
275310 {
276- Debug . LogError ( $ "InputSource { baseInputEventData . InputSource . SourceName } doesn't have any registered pointers! Input Sources without pointers should use the GazeProvider's pointer as a default fallback.") ;
277- return ;
311+ DispatchEventToFallbackHandlers ( baseInputEventData , eventHandler ) ;
278312 }
313+ }
279314
280- var modalEventHandled = false ;
315+ /// <summary>
316+ /// Dispatch an input event to all global event listeners
317+ /// Return true if the event has been handled by a global event listener
318+ /// </summary>
319+ private void DispatchEventToGlobalListeners < T > ( BaseInputEventData baseInputEventData , ExecuteEvents . EventFunction < T > eventHandler ) where T : IEventSystemHandler
320+ {
321+ Debug . Assert ( baseInputEventData != null ) ;
322+ Debug . Assert ( ! baseInputEventData . used ) ;
323+ Debug . Assert ( baseInputEventData . InputSource != null , $ "Failed to find an input source for { baseInputEventData } ") ;
281324
282- // Get the focused object for each pointer of the event source
283- for ( int i = 0 ; i < baseInputEventData . InputSource . Pointers . Length ; i ++ )
325+ // Send the event to global listeners
326+ base . HandleEvent ( baseInputEventData , eventHandler ) ;
327+ }
328+
329+ private void DispatchEventToFallbackHandlers < T > ( BaseInputEventData baseInputEventData , ExecuteEvents . EventFunction < T > eventHandler ) where T : IEventSystemHandler
330+ {
331+ // If event was not handled by the focused object, pass it on to any fallback handlers
332+ if ( ! baseInputEventData . used && fallbackInputStack . Count > 0 )
284333 {
285- GameObject focusedObject = FocusProvider ? . GetFocusedObject ( baseInputEventData . InputSource . Pointers [ i ] ) ;
334+ GameObject fallbackInput = fallbackInputStack . Peek ( ) ;
335+ ExecuteEvents . ExecuteHierarchy ( fallbackInput , baseInputEventData , eventHandler ) ;
336+ }
337+ }
286338
287- // Handle modal input if one exists
288- if ( modalInputStack . Count > 0 && ! modalEventHandled )
289- {
290- GameObject modalInput = modalInputStack . Peek ( ) ;
339+ /// <summary>
340+ /// Dispatch an input event to the object focused by the given IMixedRealityPointer.
341+ /// If a modal dialog is active, dispatch the pointer event to that modal dialog
342+ /// Returns true if the event was handled by a modal handler
343+ /// </summary>
344+ private bool DispatchEventToObjectFocusedByPointer < T > ( IMixedRealityPointer mixedRealityPointer , BaseInputEventData baseInputEventData ,
345+ bool modalEventHandled , ExecuteEvents . EventFunction < T > eventHandler ) where T : IEventSystemHandler
346+ {
347+ GameObject focusedObject = FocusProvider ? . GetFocusedObject ( mixedRealityPointer ) ;
291348
292- if ( modalInput != null )
293- {
294- modalEventHandled = true ;
349+ // Handle modal input if one exists
350+ if ( modalInputStack . Count > 0 && ! modalEventHandled )
351+ {
352+ GameObject modalInput = modalInputStack . Peek ( ) ;
295353
296- // If there is a focused object in the hierarchy of the modal handler, start the event bubble there
297- if ( focusedObject != null && focusedObject . transform . IsChildOf ( modalInput . transform ) )
298- {
299- if ( ExecuteEvents . ExecuteHierarchy ( focusedObject , baseInputEventData , eventHandler ) && baseInputEventData . used )
300- {
301- return ;
302- }
303- }
304- // Otherwise, just invoke the event on the modal handler itself
305- else
354+ if ( modalInput != null )
355+ {
356+ // If there is a focused object in the hierarchy of the modal handler, start the event bubble there
357+ if ( focusedObject != null && focusedObject . transform . IsChildOf ( modalInput . transform ) )
358+ {
359+ if ( ExecuteEvents . ExecuteHierarchy ( focusedObject , baseInputEventData , eventHandler ) && baseInputEventData . used )
306360 {
307- if ( ExecuteEvents . ExecuteHierarchy ( modalInput , baseInputEventData , eventHandler ) && baseInputEventData . used )
308- {
309- return ;
310- }
361+ return true ;
311362 }
312363 }
364+ // Otherwise, just invoke the event on the modal handler itself
313365 else
314366 {
315- Debug . LogError ( "ModalInput GameObject reference was null!\n Did this GameObject get destroyed?" ) ;
367+ if ( ExecuteEvents . ExecuteHierarchy ( modalInput , baseInputEventData , eventHandler ) && baseInputEventData . used )
368+ {
369+ return true ;
370+ }
316371 }
317372 }
318-
319- // If event was not handled by modal, pass it on to the current focused object
320- if ( focusedObject != null )
373+ else
321374 {
322- if ( ExecuteEvents . ExecuteHierarchy ( focusedObject , baseInputEventData , eventHandler ) && baseInputEventData . used )
323- {
324- return ;
325- }
375+ Debug . LogError ( "ModalInput GameObject reference was null!\n Did this GameObject get destroyed?" ) ;
326376 }
327377 }
328378
329- // If event was not handled by the focused object , pass it on to any fallback handlers
330- if ( fallbackInputStack . Count > 0 )
379+ // If event was not handled by modal , pass it on to the current focused object
380+ if ( focusedObject != null )
331381 {
332- GameObject fallbackInput = fallbackInputStack . Peek ( ) ;
333- if ( ExecuteEvents . ExecuteHierarchy ( fallbackInput , baseInputEventData , eventHandler ) && baseInputEventData . used )
334- {
335- // return;
336- }
382+ ExecuteEvents . ExecuteHierarchy ( focusedObject , baseInputEventData , eventHandler ) ;
337383 }
384+ return modalEventHandled ;
338385 }
339386
340387 /// <summary>
@@ -802,10 +849,7 @@ public void RaiseFocusExit(IMixedRealityPointer pointer, GameObject unfocusedObj
802849 /// <inheritdoc />
803850 public void RaisePointerDown ( IMixedRealityPointer pointer , Handedness handedness , MixedRealityInputAction inputAction )
804851 {
805- // Create input event
806- pointerEventData . Initialize ( pointer , handedness , inputAction ) ;
807-
808- ExecutePointerDown ( HandlePointerDown ( pointer ) ) ;
852+ RaisePointerDown ( pointer , inputAction , handedness ) ;
809853 }
810854
811855 /// <inheritdoc />
@@ -820,7 +864,8 @@ public void RaisePointerDown(IMixedRealityPointer pointer, MixedRealityInputActi
820864 private GraphicInputEventData HandlePointerDown ( IMixedRealityPointer pointer )
821865 {
822866 // Pass handler through HandleEvent to perform modal/fallback logic
823- HandleEvent ( pointerEventData , OnPointerDownEventHandler ) ;
867+ HandlePointerEvent ( pointerEventData , OnPointerDownEventHandler ) ;
868+
824869 GraphicInputEventData graphicEventData ;
825870 FocusProvider . TryGetSpecificPointerGraphicEventData ( pointer , out graphicEventData ) ;
826871 return graphicEventData ;
@@ -866,7 +911,7 @@ public void RaisePointerClicked(IMixedRealityPointer pointer, MixedRealityInputA
866911 private void HandleClick ( )
867912 {
868913 // Pass handler through HandleEvent to perform modal/fallback logic
869- HandleEvent ( pointerEventData , OnInputClickedEventHandler ) ;
914+ HandlePointerEvent ( pointerEventData , OnInputClickedEventHandler ) ;
870915
871916 // NOTE: In Unity UI, a "click" happens on every pointer up, so we have RaisePointerUp call the pointerClickHandler.
872917 }
@@ -885,10 +930,7 @@ private void HandleClick()
885930 /// <inheritdoc />
886931 public void RaisePointerUp ( IMixedRealityPointer pointer , Handedness handedness , MixedRealityInputAction inputAction )
887932 {
888- // Create input event
889- pointerEventData . Initialize ( pointer , handedness , inputAction ) ;
890-
891- ExecutePointerUp ( HandlePointerUp ( pointer ) ) ;
933+ RaisePointerUp ( pointer , inputAction , handedness ) ;
892934 }
893935
894936 /// <inheritdoc />
@@ -917,7 +959,7 @@ private static void ExecutePointerUp(GraphicInputEventData graphicInputEventData
917959 private GraphicInputEventData HandlePointerUp ( IMixedRealityPointer pointer )
918960 {
919961 // Pass handler through HandleEvent to perform modal/fallback logic
920- HandleEvent ( pointerEventData , OnPointerUpEventHandler ) ;
962+ HandlePointerEvent ( pointerEventData , OnPointerUpEventHandler ) ;
921963
922964 GraphicInputEventData graphicEventData ;
923965 FocusProvider . TryGetSpecificPointerGraphicEventData ( pointer , out graphicEventData ) ;
0 commit comments