protected virtual List <RaycastResult> CheckRaycasts(VRTK4_UIPointer pointer) { RaycastResult raycastResult = new RaycastResult(); raycastResult.worldPosition = pointer.GetOriginPosition(); raycastResult.worldNormal = pointer.GetOriginForward(); pointer.pointerEventData.pointerCurrentRaycast = raycastResult; VRTK4_UIGraphicRaycaster.CurrentPointer = pointer; VRTK4_3DGraphicRaycaster.CurrentPointer = pointer; raycasts.Clear(); eventSystem.RaycastAll(pointer.pointerEventData, raycasts); raycasts.Sort(ComparisonInversedDistance); if (raycasts.Count > 0) { var toUse = raycasts[0]; var lastKnownPosition = pointer.pointerEventData.position; pointer.pointerEventData.position = toUse.screenPosition; pointer.pointerEventData.delta = pointer.pointerEventData.position - lastKnownPosition; pointer.pointerEventData.pointerCurrentRaycast = toUse; } VRTK4_UIGraphicRaycaster.CurrentPointer = null; VRTK4_3DGraphicRaycaster.CurrentPointer = null; return(raycasts); }
protected virtual bool IsEligibleClick(VRTK4_UIPointer pointer, List <RaycastResult> results) { if (pointer.pointerEventData.eligibleForClick) { for (int i = 0; i < 1 && i < results.Count; i++) { RaycastResult result = results[i]; GameObject target = ExecuteEvents.ExecuteHierarchy(result.gameObject, pointer.pointerEventData, ExecuteEvents.pointerDownHandler); pointer.pointerEventData.delta = Vector2.zero; if (!ValidElement(result.gameObject)) { return(false); } if (target != null) { pointer.pointerEventData.pressPosition = pointer.pointerEventData.position; pointer.pointerEventData.pointerPressRaycast = result; pointer.pointerEventData.pointerPress = target; return(true); } } } return(false); }
protected virtual void Drag(VRTK4_UIPointer pointer, List <RaycastResult> results) { pointer.pointerEventData.dragging = pointer.IsSelectionButtonPressed() && pointer.pointerEventData.delta != Vector2.zero; if (pointer.pointerEventData.pointerDrag) { if (!ValidElement(pointer.pointerEventData.pointerDrag)) { pointer.pointerEventData.pointerDrag = null; return; } if (pointer.pointerEventData.dragging) { if (IsHovering(pointer)) { ExecuteEvents.ExecuteHierarchy(pointer.pointerEventData.pointerDrag, pointer.pointerEventData, ExecuteEvents.dragHandler); } } else { ExecuteEvents.ExecuteHierarchy(pointer.pointerEventData.pointerDrag, pointer.pointerEventData, ExecuteEvents.dragHandler); ExecuteEvents.ExecuteHierarchy(pointer.pointerEventData.pointerDrag, pointer.pointerEventData, ExecuteEvents.endDragHandler); for (int i = 0; i < results.Count; i++) { ExecuteEvents.ExecuteHierarchy(results[i].gameObject, pointer.pointerEventData, ExecuteEvents.dropHandler); } pointer.pointerEventData.pointerDrag = null; } } else if (pointer.pointerEventData.dragging) { for (int i = 0; i < results.Count; i++) { RaycastResult result = results[i]; if (!ValidElement(result.gameObject)) { continue; } ExecuteEvents.ExecuteHierarchy(result.gameObject, pointer.pointerEventData, ExecuteEvents.initializePotentialDrag); ExecuteEvents.ExecuteHierarchy(result.gameObject, pointer.pointerEventData, ExecuteEvents.beginDragHandler); GameObject target = ExecuteEvents.ExecuteHierarchy(result.gameObject, pointer.pointerEventData, ExecuteEvents.dragHandler); if (target != null) { pointer.pointerEventData.pointerDrag = target; break; } } } }
protected virtual void ClickOnUp(VRTK4_UIPointer pointer, List <RaycastResult> results) { pointer.pointerEventData.eligibleForClick = pointer.ValidClick(false); if (!AttemptClick(pointer)) { IsEligibleClick(pointer, results); } }
public override void Process() { if (poolOfLists.Count == 0) { poolOfLists.Add(new List <RaycastResult>(30)); poolOfLists.Add(new List <RaycastResult>(30)); } while (poolOfLists.Count < Pointers.Count) { poolOfLists.Add(new List <RaycastResult>(30)); } for (int i = 0; i < poolOfLists.Count; i++) { poolOfLists[i].Clear(); } PointersWithRaycasts.Clear(); for (int i = 0; i < Pointers.Count; i++) { PointersWithRaycasts.Add(Pointers[i], poolOfLists[i]); } for (int i = 0; i < Pointers.Count; i++) { VRTK4_UIPointer pointer = Pointers[i]; if (pointer != null && pointer.gameObject.activeInHierarchy && pointer.enabled) { if (pointer.PointerActive() || pointer.autoActivatingCanvas != null) { PointersWithRaycasts[pointer].AddRange(CheckRaycasts(pointer)); } } } //Process Hover events Hover(); // Process events for (int i = 0; i < Pointers.Count; i++) { VRTK4_UIPointer pointer = Pointers[i]; if (pointer != null && pointer.gameObject.activeInHierarchy && pointer.enabled) { Click(pointer, PointersWithRaycasts[pointer]); Drag(pointer, PointersWithRaycasts[pointer]); Scroll(pointer, PointersWithRaycasts[pointer]); } } for (int i = 0; i < poolOfLists.Count; i++) { poolOfLists[i].Clear(); } PointersWithRaycasts.Clear(); }
protected virtual void OnTriggerExit(Collider currentCollider) { VRTK4_PlayerObject colliderCheck = currentCollider.GetComponentInParent <VRTK4_PlayerObject>(); VRTK4_UIPointer pointerCheck = colliderCheck == null ? null : colliderCheck.GetPointer(); if (pointerCheck != null) { pointerCheck.collisionClick = false; } }
protected virtual void OnTriggerEnter(Collider currentCollider) { VRTK4_PlayerObject colliderCheck = currentCollider.GetComponentInParent <VRTK4_PlayerObject>(); VRTK4_UIPointer pointerCheck = colliderCheck == null ? null : colliderCheck.GetPointer(); if (pointerCheck != null && colliderCheck != null && colliderCheck.objectType == VRTK4_PlayerObject.ObjectTypes.Pointer) { pointerCheck.collisionClick = clickOnPointerCollision; } }
protected virtual void ClickOnDown(VRTK4_UIPointer pointer, List <RaycastResult> results, bool forceClick = false) { pointer.pointerEventData.eligibleForClick = (forceClick ? true : pointer.ValidClick(true)); if (IsEligibleClick(pointer, results)) { pointer.pointerEventData.eligibleForClick = false; AttemptClick(pointer); } }
protected virtual void OnTriggerExit(Collider collider) { VRTK4_PlayerObject colliderCheck = collider.GetComponentInParent <VRTK4_PlayerObject>(); VRTK4_UIPointer pointerCheck = colliderCheck == null? null: colliderCheck.GetPointer(); if (pointerCheck != null && pointerCheck.autoActivatingCanvas == gameObject && colliderCheck.objectType == VRTK4_PlayerObject.ObjectTypes.Pointer) { pointerCheck.autoActivatingCanvas = null; } }
public virtual void OnEndDrag(PointerEventData eventData) { canvasGroup.blocksRaycasts = true; dragTransform = null; transform.position += (transform.forward * forwardOffset); bool validDragEnd = true; if (restrictToDropZone) { if (validDropZone != null && validDropZone != startDropZone) { transform.SetParent(validDropZone.transform); } else { ResetElement(); validDragEnd = false; } } Canvas destinationCanvas = (eventData.pointerEnter != null ? eventData.pointerEnter.GetComponentInParent <Canvas>() : null); if (restrictToOriginalCanvas) { if (destinationCanvas != null && destinationCanvas != startCanvas) { ResetElement(); validDragEnd = false; } } if (destinationCanvas == null) { //We've been dropped off of a canvas ResetElement(); validDragEnd = false; } if (validDragEnd) { VRTK4_UIPointer pointer = GetPointer(eventData); if (pointer != null) { pointer.OnUIPointerElementDragEnd(pointer.SetUIPointerEvent(pointer.pointerEventData.pointerPressRaycast, gameObject)); } OnDraggableItemDropped(SetEventPayload(validDropZone)); } validDropZone = null; startParent = null; startCanvas = null; }
protected virtual void Click(VRTK4_UIPointer pointer, List <RaycastResult> results) { switch (pointer.clickMethod) { case VRTK4_UIPointer.ClickMethods.ClickOnButtonUp: ClickOnUp(pointer, results); break; case VRTK4_UIPointer.ClickMethods.ClickOnButtonDown: ClickOnDown(pointer, results); break; } }
private void CheckPointerHoverClick(VRTK4_UIPointer pointer, List <RaycastResult> results) { if (pointer.hoverDurationTimer > 0f) { pointer.hoverDurationTimer -= Time.deltaTime; } if (pointer.canClickOnHover && pointer.hoverDurationTimer <= 0f) { pointer.canClickOnHover = false; ClickOnDown(pointer, results, true); } }
private void HoverEnter(VRTK4_UIPointer interactable, VRTK4_UIPointer.VRTK4UIPointerEventArgs eventdata) { temporalList.Clear(); temporalList.Add(eventdata.raycastResult.worldPosition); FillInEventData(); pointerCastEventData.IsValid = true; var data = eventData; data.CurrentHoverDuration = 0.1f; data.IsCurrentlyHovering = true; data.CurrentPointsCastData = pointerCastEventData; data.CurrentPointsCastData.Points = new HeapAllocationFreeReadOnlyList <Vector3>(temporalList, 0, temporalList.Count); pointerFacade.Configuration.EmitHoverChanged(data); }
/// <summary> /// Can only be used after the processing! /// </summary> /// <param name="pointer"></param> /// <returns></returns> protected virtual bool IsHovering(VRTK4_UIPointer pointer) { for (int i = 0; i < pointer.pointerEventData.hovered.Count; i++) { GameObject hoveredObject = pointer.pointerEventData.hovered[i]; if (pointer.pointerEventData.pointerEnter != null && hoveredObject != null && CheckTransformTree(hoveredObject.transform, pointer.pointerEventData.pointerEnter.transform)) { return(true); } } return(false); }
// Still required to scroll over all elements protected virtual void Scroll(VRTK4_UIPointer pointer, List <RaycastResult> results) { if (pointer.axisAction == null) { return; } pointer.pointerEventData.scrollDelta = pointer.axisAction.Value; for (int i = 0; i < results.Count; i++) { if (pointer.pointerEventData.scrollDelta != Vector2.zero) { ExecuteEvents.ExecuteHierarchy(results[i].gameObject, pointer.pointerEventData, ExecuteEvents.scrollHandler); } } }
private static void AddOrChange(Dictionary <GameObject, UsageHoverLast> dict, GameObject go, VRTK4_UIPointer pointer, UsageOfHover hoverUsage) { if (!dict.ContainsKey(go)) { dict.Add(go, new UsageHoverLast()); } dict[go].lastUsage = hoverUsage; dict[go].gameObject = go; if (hoverUsage == UsageOfHover.OnEnter) { dict[go].pointerEnter = pointer; } else { dict[go].pointerExit = pointer; } }
protected virtual bool AttemptClick(VRTK4_UIPointer pointer) { if (pointer.pointerEventData.pointerPress != null) { if (!ValidElement(pointer.pointerEventData.pointerPress)) { pointer.pointerEventData.pointerPress = null; return(true); } if (pointer.pointerEventData.eligibleForClick) { bool isHoveringBool = IsHovering(pointer); if (!isHoveringBool) { ExecuteEvents.ExecuteHierarchy(pointer.pointerEventData.pointerPress, pointer.pointerEventData, ExecuteEvents.pointerUpHandler); pointer.pointerEventData.pointerPress = null; } } else { pointer.OnUIPointerElementClick(pointer.SetUIPointerEvent( pointer.pointerEventData.pointerPressRaycast, pointer.pointerEventData.pointerPress)); if (pointer.IsValidStateForClickFromHover && !pointer.ExplicitBlockClickOnce) { ExecuteEvents.ExecuteHierarchy(pointer.pointerEventData.pointerPress, pointer.pointerEventData, ExecuteEvents.pointerClickHandler); } pointer.ExplicitBlockClickOnce = false; ExecuteEvents.ExecuteHierarchy(pointer.pointerEventData.pointerPress, pointer.pointerEventData, ExecuteEvents.pointerUpHandler); pointer.pointerEventData.pointerPress = null; } return(true); } return(false); }
public virtual void OnBeginDrag(PointerEventData eventData) { startPosition = transform.position; startRotation = transform.rotation; startParent = transform.parent; startCanvas = GetComponentInParent <Canvas>(); canvasGroup.blocksRaycasts = false; if (restrictToDropZone) { startDropZone = GetComponentInParent <VRTK4_UIDropZone>().gameObject; validDropZone = startDropZone; } SetDragPosition(eventData); VRTK4_UIPointer pointer = GetPointer(eventData); if (pointer != null) { pointer.OnUIPointerElementDragStart(pointer.SetUIPointerEvent(pointer.pointerEventData.pointerPressRaycast, gameObject)); } }
/// <summary> /// Changes - ignore displays. /// </summary> /// <param name="eventCameraIn"></param> /// <param name="eventData"></param> /// <param name="ray"></param> /// <param name="helperList"></param> protected virtual void Raycast(Camera eventCameraIn, PointerEventData eventData, Ray ray, ref List <RaycastResult> helperList) { RaycastHit hitResult = default; float hitDistance = VRTK4_UIPointer.GetPointerLength(eventData.pointerId); bool isSuccesfullRaycasted = TryGetHitDistance(ray, ref hitDistance, out hitResult); ClearArrNonAlloc3D(); if (isSuccesfullRaycasted) { Transform graphicTransform = hitResult.transform; Vector3 graphicForward = graphicTransform.forward; float distance = Vector3.Dot(graphicForward, graphicTransform.position - ray.origin) / Vector3.Dot(graphicForward, ray.direction); if (distance < 0) { return; } Vector3 position = ray.GetPoint(distance); Vector2 pointerPosition = eventCameraIn.WorldToScreenPoint(position); var result = new RaycastResult { gameObject = hitResult.collider.gameObject, module = this, distance = hitResult.distance, worldPosition = hitResult.point, worldNormal = hitResult.normal, screenPosition = pointerPosition, depth = 0, sortingLayer = 0, sortingOrder = 7 }; VRTK4_SharedMethods.AddListValue(helperList, result); helperList.Sort(ComparisonInversedDistance); } }
protected virtual bool NoValidCollision(VRTK4_UIPointer pointer, List <RaycastResult> results) { return(results.Count == 0 || !CheckTransformTree(results[0].gameObject.transform, pointer.pointerEventData.pointerEnter.transform)); }
/// <summary> /// Changes - ignore displays. Improved Performance : no need to sort graphics only, we can sort all raycast once. /// </summary> /// <param name="canvasIn"></param> /// <param name="eventCameraIn"></param> /// <param name="eventData"></param> /// <param name="ray"></param> /// <param name="helperList"></param> protected virtual void Raycast(Canvas canvasIn, Camera eventCameraIn, PointerEventData eventData, Ray ray, ref List <RaycastResult> helperList) { // bool checkRaycastGraphic = false; float hitDistance = GetHitDistance(ray, VRTK4_UIPointer.GetPointerLength(eventData.pointerId)); IList <Graphic> canvasGraphics = null; #if UNITY_2020_3_OR_NEWER canvasGraphics = GraphicRegistry.GetRaycastableGraphicsForCanvas(canvasIn); #else canvasGraphics = GraphicRegistry.GetGraphicsForCanvas(canvasIn); #endif int totalCount = canvasGraphics.Count; for (int i = 0; i < totalCount; ++i) { Graphic graphic = canvasGraphics[i]; if (graphic.depth == -1 || !graphic.raycastTarget || graphic.canvasRenderer.cull) { continue; } Transform graphicTransform = graphic.transform; Vector3 graphicForward = graphicTransform.forward; float distance = Vector3.Dot(graphicForward, graphicTransform.position - ray.origin) / Vector3.Dot(graphicForward, ray.direction); if (distance < 0) { continue; } //Prevents "flickering hover" on items near canvas center. if ((distance - UI_CONTROL_OFFSET) > hitDistance) { continue; } Vector3 position = ray.GetPoint(distance); Vector2 pointerPosition = eventCameraIn.WorldToScreenPoint(position); #if UNITY_2020_3_OR_NEWER if (!RectTransformUtility.RectangleContainsScreenPoint( graphic.rectTransform, pointerPosition, eventCameraIn, graphic.raycastPadding)) { continue; } #else if (!RectTransformUtility.RectangleContainsScreenPoint( graphic.rectTransform, pointerPosition, eventCameraIn)) { continue; } #endif if (graphic.Raycast(pointerPosition, eventCameraIn)) { RaycastResult result = new RaycastResult() { gameObject = graphic.gameObject, module = this, distance = distance, worldPosition = position, worldNormal = -graphicForward, screenPosition = pointerPosition, depth = graphic.depth + canvasIn.sortingLayerID * 1000 + canvasIn.sortingOrder, sortingLayer = canvasIn.sortingLayerID, sortingOrder = canvasIn.sortingOrder, }; VRTK4_SharedMethods.AddListValue(helperList, result); } } helperList.Sort(ComparisonInversed); }
protected virtual VRTK4_UIPointer GetPointer(PointerEventData eventData) { return(VRTK4_UIPointer.GetByEventData(eventData)); }
protected virtual void Hover() { listPointerEnterExit.Clear(); _alreadyEntered.Clear(); foreach (var item in PointersWithRaycasts) { VRTK4_UIPointer pointer = item.Key; if (pointer.pointerEventData.pointerEnter != null) { _alreadyEntered.Add(pointer, pointer.pointerEventData.pointerEnter); CheckPointerHoverClick(pointer, item.Value); } if (pointer.pointerEventData.pointerEnter != null && !ValidElement(pointer.pointerEventData.pointerEnter)) { AddOrChange(listPointerEnterExit, pointer.pointerEventData.pointerEnter, pointer, UsageOfHover.OnExit); pointer.OnUIPointerElementExit(pointer.SetUIPointerEvent(new RaycastResult(), null, pointer.pointerEventData.pointerEnter)); pointer.pointerEventData.pointerEnter = null; continue; } if (pointer.pointerEventData.pointerEnter != null && NoValidCollision(pointer, item.Value)) { pointer.pointerEventData.hovered.Remove(pointer.pointerEventData.pointerEnter); AddOrChange(listPointerEnterExit, pointer.pointerEventData.pointerEnter, pointer, UsageOfHover.OnExit); pointer.OnUIPointerElementExit(pointer.SetUIPointerEvent(new RaycastResult(), null, pointer.pointerEventData.pointerEnter)); pointer.pointerEventData.pointerEnter = null; } } foreach (var item in PointersWithRaycasts) { VRTK4_UIPointer pointer = item.Key; for (int i = 0; i < 1 && i < item.Value.Count; i++) { RaycastResult result = item.Value[i]; if (!ValidElement(result.gameObject)) { continue; } GameObject target = ExecuteEvents.GetEventHandler <IPointerEnterHandler>(result.gameObject); // listPointerEnter.Add(pointer.pointerEventData.pointerEnter); target = (target == null ? result.gameObject : target); if (target != null) { if (pointer.hoveringElement != null && pointer.hoveringElement != target) { AddOrChange(listPointerEnterExit, pointer.hoveringElement, pointer, UsageOfHover.OnExit); pointer.OnUIPointerElementExit(pointer.SetUIPointerEvent(result, null, pointer.hoveringElement)); } pointer.OnUIPointerElementEnter(pointer.SetUIPointerEvent(result, target, pointer.hoveringElement)); pointer.hoveringElement = target; pointer.pointerEventData.pointerCurrentRaycast = result; pointer.pointerEventData.pointerEnter = target; AddCheckForDuplicates(pointer.pointerEventData.hovered, pointer.pointerEventData.pointerEnter); AddOrChange(listPointerEnterExit, pointer.pointerEventData.pointerEnter, pointer, UsageOfHover.OnEnter); break; } if (result.gameObject != pointer.hoveringElement) { AddOrChange(listPointerEnterExit, result.gameObject, pointer, UsageOfHover.OnEnter); pointer.OnUIPointerElementEnter(pointer.SetUIPointerEvent(result, result.gameObject, pointer.hoveringElement)); } pointer.hoveringElement = result.gameObject; } if (pointer.hoveringElement != null && item.Value.Count == 0) { pointer.pointerEventData.hovered.Clear(); AddOrChange(listPointerEnterExit, pointer.hoveringElement, pointer, UsageOfHover.OnExit); pointer.OnUIPointerElementExit(pointer.SetUIPointerEvent(new RaycastResult(), null, pointer.hoveringElement)); pointer.hoveringElement = null; } } foreach (var item in listPointerEnterExit) { if (item.Value.lastUsage == UsageOfHover.OnEnter) { if (_alreadyEntered.ContainsKey(item.Value.pointerEnter) && _alreadyEntered[item.Value.pointerEnter] == item.Value.gameObject) { continue; } ExecuteEvents.ExecuteHierarchy(item.Value.gameObject, item.Value.pointerEnter.pointerEventData, ExecuteEvents.pointerEnterHandler); } else { ExecuteEvents.ExecuteHierarchy(item.Value.gameObject, item.Value.pointerExit.pointerEventData, ExecuteEvents.pointerExitHandler); } } listPointerEnterExit.Clear(); _alreadyEntered.Clear(); }