public override void Process() { raycaster.eventMask = layerMask; foreach (var pair in _controllerData) { IUILaserPointer controller = pair.Key; ControllerData data = pair.Value; // Test if UICamera is looking at a GUI element UpdateCameraPosition(controller); if (data.pointerEvent == null) { data.pointerEvent = new LaserPointerEventData(eventSystem); } else { data.pointerEvent.Reset(); } data.pointerEvent.controller = controller; data.pointerEvent.delta = Vector2.zero; data.pointerEvent.position = new Vector2(UICamera.pixelWidth * 0.5f, UICamera.pixelHeight * 0.5f); //data.pointerEvent.scrollDelta = Vector2.zero; // trigger a raycast eventSystem.RaycastAll(data.pointerEvent, m_RaycastResultCache); data.pointerEvent.pointerCurrentRaycast = FindFirstRaycast(m_RaycastResultCache); m_RaycastResultCache.Clear(); // make sure our controller knows about the raycast result // we add 0.01 because that is the near plane distance of our camera and we want the correct distance if (data.pointerEvent.pointerCurrentRaycast.distance > 0.0f) { controller.LimitLaserDistance(data.pointerEvent.pointerCurrentRaycast.distance + 0.01f); } // stop if no UI element was hit //if(pointerEvent.pointerCurrentRaycast.gameObject == null) //return; // Send control enter and exit events to our controller var hitControl = data.pointerEvent.pointerCurrentRaycast.gameObject; if (data.currentPoint != hitControl) { if (data.currentPoint != null) { controller.OnExitControl(data.currentPoint); } if (hitControl != null) { controller.OnEnterControl(hitControl); } } data.currentPoint = hitControl; // Handle enter and exit events on the GUI controlls that are hit base.HandlePointerExitAndEnter(data.pointerEvent, data.currentPoint); if (controller.ButtonDown()) { ClearSelection(); data.pointerEvent.pressPosition = data.pointerEvent.position; data.pointerEvent.pointerPressRaycast = data.pointerEvent.pointerCurrentRaycast; data.pointerEvent.pointerPress = null; // update current pressed if the curser is over an element if (data.currentPoint != null) { data.currentPressed = data.currentPoint; data.pointerEvent.current = data.currentPressed; GameObject newPressed = ExecuteEvents.ExecuteHierarchy(data.currentPressed, data.pointerEvent, ExecuteEvents.pointerDownHandler); ExecuteEvents.Execute(controller.gameObject, data.pointerEvent, ExecuteEvents.pointerDownHandler); if (newPressed == null) { // some UI elements might only have click handler and not pointer down handler newPressed = ExecuteEvents.ExecuteHierarchy(data.currentPressed, data.pointerEvent, ExecuteEvents.pointerClickHandler); ExecuteEvents.Execute(controller.gameObject, data.pointerEvent, ExecuteEvents.pointerClickHandler); if (newPressed != null) { data.currentPressed = newPressed; } } else { data.currentPressed = newPressed; // we want to do click on button down at same time, unlike regular mouse processing // which does click when mouse goes up over same object it went down on // reason to do this is head tracking might be jittery and this makes it easier to click buttons ExecuteEvents.Execute(newPressed, data.pointerEvent, ExecuteEvents.pointerClickHandler); ExecuteEvents.Execute(controller.gameObject, data.pointerEvent, ExecuteEvents.pointerClickHandler); } if (newPressed != null) { data.pointerEvent.pointerPress = newPressed; data.currentPressed = newPressed; Select(data.currentPressed); } ExecuteEvents.Execute(data.currentPressed, data.pointerEvent, ExecuteEvents.beginDragHandler); ExecuteEvents.Execute(controller.gameObject, data.pointerEvent, ExecuteEvents.beginDragHandler); data.pointerEvent.pointerDrag = data.currentPressed; data.currentDragging = data.currentPressed; } }// button down end if (controller.ButtonUp()) { if (data.currentDragging != null) { data.pointerEvent.current = data.currentDragging; ExecuteEvents.Execute(data.currentDragging, data.pointerEvent, ExecuteEvents.endDragHandler); ExecuteEvents.Execute(controller.gameObject, data.pointerEvent, ExecuteEvents.endDragHandler); if (data.currentPoint != null) { ExecuteEvents.ExecuteHierarchy(data.currentPoint, data.pointerEvent, ExecuteEvents.dropHandler); } data.pointerEvent.pointerDrag = null; data.currentDragging = null; } if (data.currentPressed) { data.pointerEvent.current = data.currentPressed; ExecuteEvents.Execute(data.currentPressed, data.pointerEvent, ExecuteEvents.pointerUpHandler); ExecuteEvents.Execute(controller.gameObject, data.pointerEvent, ExecuteEvents.pointerUpHandler); data.pointerEvent.rawPointerPress = null; data.pointerEvent.pointerPress = null; data.currentPressed = null; } } // drag handling if (data.currentDragging != null) { data.pointerEvent.current = data.currentPressed; ExecuteEvents.Execute(data.currentDragging, data.pointerEvent, ExecuteEvents.dragHandler); ExecuteEvents.Execute(controller.gameObject, data.pointerEvent, ExecuteEvents.dragHandler); } // update selected element for keyboard focus if (base.eventSystem.currentSelectedGameObject != null) { data.pointerEvent.current = eventSystem.currentSelectedGameObject; ExecuteEvents.Execute(eventSystem.currentSelectedGameObject, GetBaseEventData(), ExecuteEvents.updateSelectedHandler); //ExecuteEvents.Execute(controller.gameObject, GetBaseEventData(), ExecuteEvents.updateSelectedHandler); } } }
// walk up the tree till a common root between the last entered and the current entered is foung // send exit events up to (but not inluding) the common root. Then send enter events up to // (but not including the common root). protected new void HandlePointerExitAndEnter(PointerEventData currentPointerData, GameObject newEnterTarget, IUILaserPointer controller) { // if we have no target / pointerEnter has been deleted // just send exit events to anything we are tracking // then exit if (newEnterTarget == null || currentPointerData.pointerEnter == null) { for (var i = 0; i < currentPointerData.hovered.Count; ++i) { ExecuteEvents.Execute(currentPointerData.hovered[i], currentPointerData, ExecuteEvents.pointerExitHandler); controller.OnExitControl(currentPointerData.hovered[i]); } currentPointerData.hovered.Clear(); if (newEnterTarget == null) { currentPointerData.pointerEnter = newEnterTarget; return; } } // if we have not changed hover target if (currentPointerData.pointerEnter == newEnterTarget && newEnterTarget) { return; } GameObject commonRoot = FindCommonRoot(currentPointerData.pointerEnter, newEnterTarget); // and we already an entered object from last time if (currentPointerData.pointerEnter != null) { // send exit handler call to all elements in the chain // until we reach the new target, or null! Transform t = currentPointerData.pointerEnter.transform; while (t != null) { // if we reach the common root break out! if (commonRoot != null && commonRoot.transform == t) { break; } ExecuteEvents.Execute(t.gameObject, currentPointerData, ExecuteEvents.pointerExitHandler); controller.OnExitControl(t.gameObject); currentPointerData.hovered.Remove(t.gameObject); t = t.parent; } } // now issue the enter call up to but not including the common root currentPointerData.pointerEnter = newEnterTarget; if (newEnterTarget != null) { Transform t = newEnterTarget.transform; while (t != null && t.gameObject != commonRoot) { ExecuteEvents.Execute(t.gameObject, currentPointerData, ExecuteEvents.pointerEnterHandler); controller.OnEnterControl(t.gameObject); currentPointerData.hovered.Add(t.gameObject); t = t.parent; } } }