///<summary> /// A class that contains the base event data that is common to all event types in the new EventSystem. ///</summary> publicclassBaseEventData : AbstractEventData { privatereadonly EventSystem m_EventSystem; publicBaseEventData(EventSystem eventSystem) { m_EventSystem = eventSystem; }
///<summary> /// >A reference to the BaseInputModule that sent this event. ///</summary> public BaseInputModule currentInputModule { get { return m_EventSystem.currentInputModule; } }
///<summary> /// The object currently considered selected by the EventSystem. ///</summary> public GameObject selectedObject { get { return m_EventSystem.currentSelectedGameObject; } set { m_EventSystem.SetSelectedGameObject(value, this); } } }
///<summary> /// Process the current tick for the module. ///</summary> publicabstractvoidProcess();
...
///<summary> /// Should the module be activated. ///</summary> publicvirtualboolShouldActivateModule() { return enabled && gameObject.activeInHierarchy; }
///<summary> /// Called when the module is deactivated. Override this if you want custom code to execute when you deactivate your module. ///</summary> publicvirtualvoidDeactivateModule() {}
///<summary> /// Called when the module is activated. Override this if you want custom code to execute when you activate your module. ///</summary> publicvirtualvoidActivateModule() {}
///<summary> /// Update the internal state of the Module. ///</summary> publicvirtualvoidUpdateModule() {}
///<summary> /// Check to see if the module is supported. Override this if you have a platform specific module (eg. TouchInputModule that you do not want to activate on standalone.) ///</summary> ///<returns>Is the module supported.</returns> publicvirtualboolIsModuleSupported() { returntrue; }
///<summary> /// Process all mouse events. ///</summary> protectedvoidProcessMouseEvent(int id) { var mouseData = GetMousePointerEventData(id); var leftButtonData = mouseData.GetButtonState(PointerEventData.InputButton.Left).eventData;
// Process the first mouse button fully ProcessMousePress(leftButtonData); ProcessMove(leftButtonData.buttonData); ProcessDrag(leftButtonData.buttonData);
// Now process right / middle clicks ProcessMousePress(mouseData.GetButtonState(PointerEventData.InputButton.Right).eventData); ProcessDrag(mouseData.GetButtonState(PointerEventData.InputButton.Right).eventData.buttonData); ProcessMousePress(mouseData.GetButtonState(PointerEventData.InputButton.Middle).eventData); ProcessDrag(mouseData.GetButtonState(PointerEventData.InputButton.Middle).eventData.buttonData);
if (!Mathf.Approximately(leftButtonData.buttonData.scrollDelta.sqrMagnitude, 0.0f)) { var scrollHandler = ExecuteEvents.GetEventHandler<IScrollHandler>(leftButtonData.buttonData.pointerCurrentRaycast.gameObject); ExecuteEvents.ExecuteHierarchy(scrollHandler, leftButtonData.buttonData, ExecuteEvents.scrollHandler); } }
if (pointerEvent.pointerEnter != currentOverGo) { // send a pointer enter to the touched element if it isn't the one to select... HandlePointerExitAndEnter(pointerEvent, currentOverGo); pointerEvent.pointerEnter = currentOverGo; }
// search for the control that will receive the press // if we can't find a press handler set the press // handler to be what would receive a click. var newPressed = ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.pointerDownHandler);
// didnt find a press handler... search for a click handler if (newPressed == null) newPressed = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
// Debug.Log("Pressed: " + newPressed);
float time = Time.unscaledTime;
if (newPressed == pointerEvent.lastPress) { var diffTime = time - pointerEvent.clickTime; if (diffTime < 0.3f) ++pointerEvent.clickCount; else pointerEvent.clickCount = 1;
// see if we mouse up on the same element that we clicked on... var pointerUpHandler = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
// PointerClick and Drop events if (pointerEvent.pointerPress == pointerUpHandler && pointerEvent.eligibleForClick) { ExecuteEvents.Execute(pointerEvent.pointerPress, pointerEvent, ExecuteEvents.pointerClickHandler); } elseif (pointerEvent.pointerDrag != null && pointerEvent.dragging) { ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.dropHandler); }
// send exit events as we need to simulate this on touch up on touch device ExecuteEvents.ExecuteHierarchy(pointerEvent.pointerEnter, pointerEvent, ExecuteEvents.pointerExitHandler); pointerEvent.pointerEnter = null;
///<summary> /// Process all touch events. ///</summary> privatevoidProcessTouchEvents() { for (int i = 0; i < input.touchCount; ++i) { Touch touch = input.GetTouch(i);
if (touch.type == TouchType.Indirect) continue;
bool released; bool pressed; var pointer = GetTouchPointerEventData(touch, out pressed, out released);
ProcessTouchPress(pointer, pressed, released);
if (!released) { ProcessMove(pointer); ProcessDrag(pointer); } else RemovePointerData(pointer); } }
///<summary> /// Perform a raycast into the screen and collect all graphics underneath it. ///</summary> [NonSerialized] staticreadonly List<Graphic> s_SortedGraphics = new List<Graphic>(); privatestaticvoidRaycast(Canvas canvas, Camera eventCamera, Vector2 pointerPosition, IList<Graphic> foundGraphics, List<Graphic> results) { // Necessary for the event system int totalCount = foundGraphics.Count; for (int i = 0; i < totalCount; ++i) { Graphic graphic = foundGraphics[i];
// -1 means it hasn't been processed by the canvas, which means it isn't actually drawn if (graphic.depth == -1 || !graphic.raycastTarget || graphic.canvasRenderer.cull) continue;
if (!RectTransformUtility.RectangleContainsScreenPoint(graphic.rectTransform, pointerPosition, eventCamera)) continue;
if (eventCamera != null && eventCamera.WorldToScreenPoint(graphic.rectTransform.position).z > eventCamera.farClipPlane) continue;
if (graphic.Raycast(pointerPosition, eventCamera)) { s_SortedGraphics.Add(graphic); } }
s_SortedGraphics.Sort((g1, g2) => g2.depth.CompareTo(g1.depth)); totalCount = s_SortedGraphics.Count; for (int i = 0; i < totalCount; ++i) results.Add(s_SortedGraphics[i]);
EventSystem.cs publicvoidRaycastAll(PointerEventData eventData, List<RaycastResult> raycastResults) { raycastResults.Clear(); //获取BaseRaycast对象 var modules = RaycasterManager.GetRaycasters(); var modulesCount = modules.Count; for (int i = 0; i < modulesCount; ++i) { var module = modules[i]; if (module == null || !module.IsActive()) continue; //调用Raycast方法, module.Raycast(eventData, raycastResults); } raycastResults.Sort(s_RaycastComparer); }
privatestaticintRaycastComparer(RaycastResult lhs, RaycastResult rhs) { if (lhs.module != rhs.module) { var lhsEventCamera = lhs.module.eventCamera; var rhsEventCamera = rhs.module.eventCamera;
// 深度排序 if (lhsEventCamera != null && rhsEventCamera != null && lhsEventCamera.depth != rhsEventCamera.depth) { // need to reverse the standard compareTo if (lhsEventCamera.depth < rhsEventCamera.depth) return1; if (lhsEventCamera.depth == rhsEventCamera.depth) return0;
return-1; } if (lhs.module.sortOrderPriority != rhs.module.sortOrderPriority) return rhs.module.sortOrderPriority.CompareTo(lhs.module.sortOrderPriority);
if (lhs.module.renderOrderPriority != rhs.module.renderOrderPriority) return rhs.module.renderOrderPriority.CompareTo(lhs.module.renderOrderPriority); }
// 排序顺序 if (lhs.sortingLayer != rhs.sortingLayer) { // Uses the layer value to properly compare the relative order of the layers. var rid = SortingLayer.GetLayerValueFromID(rhs.sortingLayer); var lid = SortingLayer.GetLayerValueFromID(lhs.sortingLayer); return rid.CompareTo(lid); }
///<summary> /// The SortingOrder for the hit object. ///</summary> ///<remarks> /// For Graphic elements this will be the values from that graphics Canvas /// For 3D objects this will always be 0. /// For 2D objects if a SpriteRenderer is attached to the same object as the hit collider that SpriteRenderer sortingOrder will be used. ///</remarks> // public int sortingOrder; if (lhs.sortingOrder != rhs.sortingOrder) return rhs.sortingOrder.CompareTo(lhs.sortingOrder);
// comparing depth only makes sense if the two raycast results have the same root canvas (case 912396) if (lhs.depth != rhs.depth && lhs.module.rootRaycaster == rhs.module.rootRaycaster) return rhs.depth.CompareTo(lhs.depth);
if (lhs.distance != rhs.distance) return lhs.distance.CompareTo(rhs.distance);
return lhs.index.CompareTo(rhs.index); }
BaseRaycaster.cs ///<summary> /// Raycast against the scene. ///</summary> ///<param name="eventData">Current event data.</param> ///<param name="resultAppendList">List of hit Objects.</param> publicabstractvoidRaycast(PointerEventData eventData, List<RaycastResult> resultAppendList);
PhysicsRaycaster.cs ///<summary> /// Returns a ray going from camera through the event position and the distance between the near and far clipping planes along that ray. ///</summary> ///<param name="eventData">The pointer event for which we will cast a ray.</param> ///<param name="ray">The ray to use.</param> ///<param name="distanceToClipPlane">The distance between the near and far clipping planes along the ray.</param> ///<returns>True if the operation was successful. false if it was not possible to compute, such as the eventPosition being outside of the view.</returns> protectedboolComputeRayAndDistance(PointerEventData eventData, ref Ray ray, reffloat distanceToClipPlane) { if (eventCamera == null) returnfalse;
var eventPosition = Display.RelativeMouseAt(eventData.position); if (eventPosition != Vector3.zero) { // We support multiple display and display identification based on event position. int eventDisplayIndex = (int)eventPosition.z;
// Discard events that are not part of this display so the user does not interact with multiple displays at once. if (eventDisplayIndex != eventCamera.targetDisplay) returnfalse; } else { // The multiple display system is not supported on all platforms, when it is not supported the returned position // will be all zeros so when the returned index is 0 we will default to the event data to be safe. eventPosition = eventData.position; }
// Cull ray casts that are outside of the view rect. (case 636595) if (!eventCamera.pixelRect.Contains(eventPosition)) returnfalse;
ray = eventCamera.ScreenPointToRay(eventPosition); // compensate far plane distance - see MouseEvents.cs float projectionDirection = ray.direction.z; distanceToClipPlane = Mathf.Approximately(0.0f, projectionDirection) ? Mathf.Infinity : Mathf.Abs((eventCamera.farClipPlane - eventCamera.nearClipPlane) / projectionDirection); returntrue; }
publicoverridevoidRaycast(PointerEventData eventData, List<RaycastResult> resultAppendList) { Ray ray = new Ray(); float distanceToClipPlane = 0; if (!ComputeRayAndDistance(eventData, ref ray, ref distanceToClipPlane)) return;
int hitCount = 0;
if (m_MaxRayIntersections == 0) { if (ReflectionMethodsCache.Singleton.raycast3DAll == null) return;
if (hitCount > 1) System.Array.Sort(m_Hits, (r1, r2) => r1.distance.CompareTo(r2.distance));
if (hitCount != 0) { for (int b = 0, bmax = hitCount; b < bmax; ++b) { var result = new RaycastResult { gameObject = m_Hits[b].collider.gameObject, module = this, distance = m_Hits[b].distance, worldPosition = m_Hits[b].point, worldNormal = m_Hits[b].normal, screenPosition = eventData.position, index = resultAppendList.Count, sortingLayer = 0, sortingOrder = 0 }; resultAppendList.Add(result); } } }
Physics2DRaycaster.cs ///<summary> /// Raycast against 2D elements in the scene. ///</summary> publicoverridevoidRaycast(PointerEventData eventData, List<RaycastResult> resultAppendList) { Ray ray = new Ray(); float distanceToClipPlane = 0; if (!ComputeRayAndDistance(eventData, ref ray, ref distanceToClipPlane)) return;
int hitCount = 0;
if (maxRayIntersections == 0) { if (ReflectionMethodsCache.Singleton.getRayIntersectionAll == null) return;