//-------------------------------------------------------------------------------------- #region Monobehaviour Functions protected virtual void Awake() { FocusList = new List <GameObject>(); FocusExitList = new List <GameObject>(); FocusEnterList = new List <GameObject>(); FocusHitInfo = new FocusInfo(); if (CursorPrefab != null) { SetCursor(CursorPrefab); } }
/// <summary> /// Will fill the list with UI elements from EventSystem raycast. /// </summary> /// <param name="focusedItems">The list to be filled.</param> /// <returns>Did the raycast hit anything.</returns> private bool GetUIRaycasts(ref List <FocusInfo> focusedItems) { bool hit = false; // Get UI raycasts m_UIRaycastResults.Clear(); if (EventSystem.current != null) { EventSystem.current.RaycastAll(GetPointerData(), m_UIRaycastResults); hit = hit ? hit : (m_UIRaycastResults != null && m_UIRaycastResults.Count > 0); if (hit) { // Add UI hits for (int i = 0; i < m_UIRaycastResults.Count; ++i) { UnityEngine.EventSystems.RaycastResult raycastResult = m_UIRaycastResults[i]; float distance = raycastResult.distance; if (distance <= FocusManager.Instance.MaxGazeDistance) { FocusInfo focusInfo = m_FocusInfoPool.GetObject(); focusInfo.SetUI(raycastResult.gameObject, true, raycastResult.index, distance, TargetOrigin + (TargetDirection.normalized * distance), -raycastResult.gameObject.transform.forward, raycastResult.gameObject.transform, Vector2.zero, raycastResult); focusedItems.Add(focusInfo); } } // Sort via render order focusedItems.Sort((FocusInfo a, FocusInfo b) => { if (a.raycastResult.sortingLayer != b.raycastResult.sortingLayer) { return(a.raycastResult.sortingLayer.CompareTo(b.raycastResult.sortingLayer)); } if (a.raycastResult.sortingOrder != b.raycastResult.sortingOrder) { return(b.raycastResult.sortingOrder.CompareTo(a.raycastResult.sortingOrder)); } bool distanceSimilar = Mathf.Approximately(a.distance, b.distance); if (distanceSimilar) { return(a.raycastResult.index.CompareTo(b.raycastResult.index)); } return(a.distance.CompareTo(b.distance)); }); } } return(hit); }
private bool GetLookAtFace(Quaternion anchorRotation, ref Face face) { HUX.Focus.FocusManager focusManager = HUX.Focus.FocusManager.Instance; HUX.Focus.FocusInfo focusHitInfo = focusManager.GazeFocuser.FocusHitInfo; // Early out if did not hit or did not hit anchor if (focusHitInfo.gameObject == null || focusHitInfo.gameObject != m_Anchor.AnchorObj.gameObject) { face = m_CurrentFace; return(focusHitInfo.gameObject != null?IsCollidingWithAnchor(focusHitInfo.gameObject) : false); } // Return closest face to normal Vector3 faceNormal = focusHitInfo.normal; face = GetClosestFace(-faceNormal, anchorRotation); return(true); }
/// <summary> /// Will fill the list will all colliders from physics raycast. /// </summary> /// <param name="focusedItems">The list to be filled.</param> /// <returns>Did the raycast hit anything.</returns> private bool GetColliderRaycasts(ref List <FocusInfo> focusedItems) { // Get world collider raycasts int numberOfHits = Physics.RaycastNonAlloc(FocusRay, m_ColliderRaycastHits, FocusManager.Instance.MaxGazeDistance, FocusManager.Instance.RaycastLayerMask); bool hit = numberOfHits > 0; if (hit) { for (int i = 0; i < numberOfHits; ++i) { RaycastHit raycastHit = m_ColliderRaycastHits[i]; FocusInfo focusInfo = m_FocusInfoPool.GetObject(); focusInfo.Set(raycastHit.transform.gameObject, raycastHit.distance, raycastHit.point, raycastHit.normal, raycastHit.transform, raycastHit.textureCoord); focusedItems.Add(focusInfo); } } return(hit); }
public virtual bool CastRayStep(RayStep step) { FocusInfo hitInfo = null; // Set our FocusRay to this step FocusRay = step; // Add UI items bool hitUI = GetUIRaycasts(ref m_FocusedItems); FocusInfo mainUIFocus = null; if (hitUI && m_FocusedItems.Count > 0) { mainUIFocus = m_FocusedItems[0]; } // Perform a preemptive raycast to determine if we are looking at the SR or nothing. // If we are doing either, return out of the function early to avoid doing the extra raycast. // Bug-Fix: This also fixed a bug where the SR would not allow the pins panel to be opened. if (!hitUI) { RaycastHit hit; bool hitSomething = Physics.Raycast(FocusRay.origin, FocusRay.direction, out hit, FocusRay.length, FocusManager.Instance.RaycastLayerMask); Debug.DrawLine(FocusRay.origin, FocusRay.terminus, hitSomething ? Color.green : Color.red); if (!hitSomething || hit.transform.gameObject.layer == LayerMask.NameToLayer("SR")) // TODO remove this reference or make it a const var { if (hitSomething) { Position = hit.point; Normal = hit.normal; } else { Position = step.terminus; // TargetOrigin + TargetDirection * FocusManager.Instance.MaxGazeDistance; Normal = step.direction; // TargetDirection; } return(false); } } // Add colliders bool hitCollider = GetColliderRaycasts(ref m_FocusedItems); // Check if we hit anything if (hitCollider || hitUI) { // Sort via distance m_FocusedItems.Sort((FocusInfo focusInfo1, FocusInfo focusInfo2) => { int ret = focusInfo1.distance.CompareTo(focusInfo2.distance); if (ret == 0) { Graphic graph1 = focusInfo1.gameObject.GetComponent <Graphic>(); Graphic graph2 = focusInfo2.gameObject.GetComponent <Graphic>(); if (graph1 != null && graph2 != null) { ret = graph2.depth.CompareTo(graph1.depth); } } return(ret); }); // Get the closest valid collider for (int i = 0; i < m_FocusedItems.Count; ++i) { FocusInfo focusInfo = m_FocusedItems[i]; // Check if the transform has a valid filter if (FocusManager.Instance.ContainsValidFilter(focusInfo.transform)) { if (focusInfo.isUI && mainUIFocus != null) { focusInfo = mainUIFocus; } hitInfo = focusInfo; Hit = true; break; } } } if (hitInfo != null) { // The raycast hit a valid hologram FocusHitInfo = hitInfo; Position = hitInfo.point; Normal = hitInfo.normal; } else { // If raycast did not hit a hologram... Save defaults Position = TargetOrigin + (TargetDirection * FocusManager.Instance.MaxGazeDistance); Normal = TargetDirection; } return(Hit); }
/// <summary> /// Calculates the Focus hit position and normal. /// </summary> public void UpdateRaycast() { OnPreRaycast(); Hit = false; FocusInfo hitInfo = null; FocusRay = new Ray(TargetOrigin, TargetDirection); // This must be called at the start of the function, as functions called later in the frame rely on the data. CleanFocusedItemCollection(); // Add UI items bool hitUI = GetUIRaycasts(ref m_FocusedItems); FocusInfo mainUIFocus = null; if (hitUI && m_FocusedItems.Count > 0) { mainUIFocus = m_FocusedItems[0]; } // Perform a preemptive raycast to determine if we are looking at the SR or nothing. // If we are doing either, return out of the function early to avoid doing the extra raycast. // Bug-Fix: This also fixed a bug where the SR would not allow the pins panel to be opened. if (!hitUI) { RaycastHit hit; bool hitSomething = Physics.Raycast(FocusRay, out hit, FocusManager.Instance.MaxGazeDistance, FocusManager.Instance.RaycastLayerMask); if (!hitSomething || hit.transform.gameObject.layer == LayerMask.NameToLayer("SR")) { if (hitSomething) { Position = hit.point; Normal = hit.normal; } else { Position = TargetOrigin + TargetDirection * FocusManager.Instance.MaxGazeDistance; Normal = TargetDirection; } return; } } // Add colliders bool hitCollider = GetColliderRaycasts(ref m_FocusedItems); // Check if we hit anything if (hitCollider || hitUI) { // Sort via distance m_FocusedItems.Sort((FocusInfo focusInfo1, FocusInfo focusInfo2) => { int ret = focusInfo1.distance.CompareTo(focusInfo2.distance); if (ret == 0) { Graphic graph1 = focusInfo1.gameObject.GetComponent <Graphic>(); Graphic graph2 = focusInfo2.gameObject.GetComponent <Graphic>(); if (graph1 != null && graph2 != null) { ret = graph2.depth.CompareTo(graph1.depth); } } return(ret); }); // Get the closest valid collider for (int i = 0; i < m_FocusedItems.Count; ++i) { FocusInfo focusInfo = m_FocusedItems[i]; // Check if the transform has a valid filter if (FocusManager.Instance.ContainsValidFilter(focusInfo.transform)) { if (focusInfo.isUI && mainUIFocus != null) { focusInfo = mainUIFocus; } hitInfo = focusInfo; Hit = true; break; } } } if (hitInfo != null) { // The raycast hit a valid hologram FocusHitInfo = hitInfo; Position = hitInfo.point; Normal = hitInfo.normal; } else { // If raycast did not hit a hologram... Save defaults Position = TargetOrigin + (TargetDirection * FocusManager.Instance.MaxGazeDistance); Normal = TargetDirection; } OnPostRaycast(); }