/// <summary> /// Automatically called each frame during Update to clear the selection of the Interactor if necessary due to current conditions. /// </summary> /// <param name="interactor">The Interactor to potentially exit its selection state.</param> public virtual void ClearInteractorSelection(XRBaseInteractor interactor) { if (interactor.selectTarget != null && (!interactor.isSelectActive || !interactor.CanSelect(interactor.selectTarget) || !interactor.selectTarget.IsSelectableBy(interactor))) { SelectExit(interactor, interactor.selectTarget); } }
/// <summary> /// Automatically called when an Interactor is unregistered to cancel the hover state of the Interactor if necessary. /// </summary> /// <param name="interactor">The Interactor to potentially exit its hover state due to cancellation.</param> public virtual void CancelInteractorHover(XRBaseInteractor interactor) { interactor.GetHoverTargets(m_HoverTargetList); for (var i = m_HoverTargetList.Count - 1; i >= 0; --i) { var target = m_HoverTargetList[i]; HoverCancel(interactor, target); } }
/// <summary> /// Register a new Interactor to be processed. /// </summary> /// <param name="interactor">The Interactor to be registered.</param> public virtual void RegisterInteractor(XRBaseInteractor interactor) { if (m_Interactors.Register(interactor)) { m_InteractorRegisteredEventArgs.manager = this; m_InteractorRegisteredEventArgs.interactor = interactor; OnRegistered(m_InteractorRegisteredEventArgs); } }
protected internal override void OnSelectExit(XRBaseInteractor interactor) { if (m_TeleportTrigger == TeleportTrigger.OnSelectExit) { SendTeleportRequest(interactor); } base.OnSelectExit(interactor); }
void ClearInteractorSelection(XRBaseInteractor interactor) { // TODO: Make sure SelectExit is called if the selectTarget of the interactor is destroyed (and write a test around this). if (interactor.selectTarget && (!interactor.isSelectActive || !interactor.CanSelect(interactor.selectTarget) || !interactor.selectTarget.IsSelectableBy(interactor))) { SelectExit(interactor, interactor.selectTarget); } }
protected internal override void OnDeactivate(XRBaseInteractor interactor) { if (m_TeleportTrigger == TeleportTrigger.OnDeactivate) { SendTeleportRequest(interactor); } base.OnDeactivate(interactor); }
/// <summary> /// Initiates ending hovering of an Interactable by an Interactor, passing the given <paramref name="args"/>. /// </summary> /// <param name="interactor">The Interactor that is no longer hovering.</param> /// <param name="interactable">The Interactable that is no longer being hovered over.</param> /// <param name="args">Event data containing the Interactor and Interactable involved in the event.</param> protected virtual void HoverExit(XRBaseInteractor interactor, XRBaseInteractable interactable, HoverExitEventArgs args) { Debug.Assert(args.interactor == interactor, this); Debug.Assert(args.interactable == interactable, this); interactor.OnHoverExiting(args); interactable.OnHoverExiting(args); interactor.OnHoverExited(args); interactable.OnHoverExited(args); }
/// <summary> /// Initiates selection of an Interactable by an Interactor, passing the given <paramref name="args"/>. /// </summary> /// <param name="interactor">The Interactor that is selecting.</param> /// <param name="interactable">The Interactable being selected.</param> /// <param name="args">Event data containing the Interactor and Interactable involved in the event.</param> protected virtual void SelectEnter(XRBaseInteractor interactor, XRBaseInteractable interactable, SelectEnterEventArgs args) { Debug.Assert(args.interactor == interactor, this); Debug.Assert(args.interactable == interactable, this); interactor.OnSelectEntering(args); interactable.OnSelectEntering(args); interactor.OnSelectEntered(args); interactable.OnSelectEntered(args); }
void Awake() { m_Interactor = GetComponent <XRBaseInteractor>(); if (m_Interactor) { m_Interactor.onSelectEnter.AddListener(OnSelectEnter); m_Interactor.onSelectExit.AddListener(OnSelectExit); } SetupReticlePrefab(); reticleActive = false; }
public virtual void SelectCancel(XRBaseInteractor interactor, XRBaseInteractable interactable) { // TODO Add an OnSelectCancel function to XRBaseInteractor? interactor.OnSelectExiting(interactable); interactor.OnSelectExited(interactable); if (interactable != null) { interactable.OnSelectCanceling(interactor); interactable.OnSelectCanceled(interactor); } }
public virtual void ClearInteractorHover(XRBaseInteractor interactor, List <XRBaseInteractable> validTargets) { interactor.GetHoverTargets(m_HoverTargetList); foreach (var target in m_HoverTargetList) { if (!interactor.isHoverActive || !interactor.CanHover(target) || !target.IsHoverableBy(interactor) || ((validTargets != null && !validTargets.Contains(target)) || validTargets == null)) { HoverExit(interactor, target); } } }
/// <summary> /// Automatically called each frame during Update to clear the hover state of the Interactor if necessary due to current conditions. /// </summary> /// <param name="interactor">The Interactor to potentially exit its hover state.</param> /// <param name="validTargets">The list of interactables that this Interactor could possibly interact with this frame.</param> public virtual void ClearInteractorHover(XRBaseInteractor interactor, List <XRBaseInteractable> validTargets) { interactor.GetHoverTargets(m_HoverTargetList); for (var i = m_HoverTargetList.Count - 1; i >= 0; --i) { var target = m_HoverTargetList[i]; if (!interactor.isHoverActive || !interactor.CanHover(target) || !target.IsHoverableBy(interactor) || validTargets == null || !validTargets.Contains(target)) { HoverExit(interactor, target); } } }
void ClearInteractorHover(XRBaseInteractor interactor, List <XRBaseInteractable> validTargets) { interactor.GetHoverTargets(m_HoverTargetList); for (int i = 0; i < m_HoverTargetList.Count; i++) { var target = m_HoverTargetList[i]; if (!interactor.isHoverActive || !interactor.CanHover(target) || !target.IsHoverableBy(interactor) || ((validTargets != null && !validTargets.Contains(target)) || validTargets == null)) { HoverExit(interactor, target); } } }
internal void RegisterInteractor(XRBaseInteractor interactor) { if (!m_Interactors.Contains(interactor)) { m_Interactors.Add(interactor); #if AR_FOUNDATION_PRESENT if (interactor is ARGestureInteractor) { m_GestureInteractablesNeedReconnect = true; } #endif } }
/// <summary> /// Sorts the Interactables in <paramref name="unsortedTargets"/> by distance to the <paramref name="interactor"/>, /// storing the ordered result in <paramref name="results"/>. /// </summary> /// <param name="interactor">The Interactor to calculate distance against.</param> /// <param name="unsortedTargets">The read only list of Interactables to sort. This list is not modified.</param> /// <param name="results">The results list to populate with the sorted results.</param> /// <remarks> /// Clears <paramref name="results"/> before adding to it. /// This method is not thread safe. /// </remarks> public static void SortByDistanceToInteractor(XRBaseInteractor interactor, List <XRBaseInteractable> unsortedTargets, List <XRBaseInteractable> results) { results.Clear(); results.AddRange(unsortedTargets); s_InteractableDistanceSqrMap.Clear(); foreach (var interactable in unsortedTargets) { s_InteractableDistanceSqrMap[interactable] = interactable.GetDistanceSqrToInteractor(interactor); } results.Sort(s_InteractableDistanceComparison); }
/// <summary>This method is called by the interaction manager /// when the interactor ends selection of an interactable.</summary> /// <param name="interactor">Interactor that is ending the selection.</param> protected internal override void OnSelectExit(XRBaseInteractor interactor) { base.OnSelectExit(interactor); // reset RididBody settings m_RigidBody.isKinematic = m_WasKinematic; m_RigidBody.useGravity = m_UsedGravity | m_GravityOnDetach; m_CurrentMovementType = m_MovementType; m_SelectingInteractor = null; m_DetachInLateUpdate = true; SmoothVelocityEnd(); }
protected override bool GenerateTeleportRequest(XRBaseInteractor interactor, RaycastHit raycastHit, ref TeleportRequest teleportRequest) { if (teleportAnchorTransform == null) { return(false); } teleportRequest.destinationPosition = m_TeleportAnchorTransform.position; teleportRequest.destinationUpVector = m_TeleportAnchorTransform.up; teleportRequest.destinationRotation = m_TeleportAnchorTransform.rotation; teleportRequest.destinationForwardVector = m_TeleportAnchorTransform.forward; return(true); }
/// <summary> /// Register a new Interactor to be processed. /// </summary> /// <param name="interactor">The Interactor to be registered.</param> public virtual void RegisterInteractor(XRBaseInteractor interactor) { if (m_Interactors.Contains(interactor)) { return; } m_Interactors.Add(interactor); m_InteractorRegisteredEventArgs.manager = this; m_InteractorRegisteredEventArgs.interactor = interactor; interactor.OnRegistered(m_InteractorRegisteredEventArgs); interactorRegistered?.Invoke(m_InteractorRegisteredEventArgs); }
void InteractorSelectValidTargets(XRBaseInteractor interactor, List <XRBaseInteractable> validTargets) { if (interactor.isSelectActive) { for (var i = 0; i < validTargets.Count && interactor.isSelectActive; ++i) { if (interactor.CanSelect(validTargets[i]) && validTargets[i].IsSelectableBy(interactor) && interactor.selectTarget != validTargets[i]) { SelectEnter(interactor, validTargets[i]); } } } }
internal List <XRBaseInteractable> GetValidTargets(XRBaseInteractor interactor, List <XRBaseInteractable> validTargets) { interactor.GetValidTargets(validTargets); // Remove interactables that are not being handled by this manager. for (int i = validTargets.Count - 1; i >= 0; --i) { if (!m_Interactables.Contains(validTargets[i])) { validTargets.RemoveAt(i); } } return(validTargets); }
void InteractorHoverValidTargets(XRBaseInteractor interactor, List <XRBaseInteractable> validTargets) { if (interactor.isHoverActive) { for (var i = 0; i < validTargets.Count && interactor.isHoverActive; ++i) { interactor.GetHoverTargets(m_HoverTargetList); if (interactor.CanHover(validTargets[i]) && validTargets[i].IsHoverableBy(interactor) && !m_HoverTargetList.Contains(validTargets[i])) { HoverEnter(interactor, validTargets[i]); } } } }
// In order to move the Interactable to the Interactor we need to // calculate the Interactable attach point in the coordinate system of the // Interactor's attach point. void UpdateInteractorLocalPose(XRBaseInteractor interactor) { var attachTransform = m_AttachTransform ? m_AttachTransform : transform; var attachPosition = m_AttachTransform ? m_AttachTransform.position : m_RigidBody.worldCenterOfMass; var attachOffset = m_RigidBody.worldCenterOfMass - attachPosition; var localAttachOffset = attachTransform.InverseTransformDirection(attachOffset); var inverseLocalScale = interactor.attachTransform.lossyScale; inverseLocalScale = new Vector3(1f / inverseLocalScale.x, 1f / inverseLocalScale.y, 1f / inverseLocalScale.z); localAttachOffset.Scale(inverseLocalScale); m_InteractorLocalPosition = localAttachOffset; m_InteractorLocalRotation = Quaternion.Inverse(Quaternion.Inverse(m_RigidBody.rotation) * attachTransform.rotation); }
/// <summary>This method is called by the interaction manager /// when the interactor first initiates selection of an interactable.</summary> /// <param name="interactor">Interactor that is initiating the selection.</param> protected internal override void OnSelectEnter(XRBaseInteractor interactor) { if (!interactor) { return; } base.OnSelectEnter(interactor); // Only do this on the first select, because otherwise the original parent will be overwritten as null. if (m_SelectingInteractor == null) { m_OriginalSceneParent = transform.parent; transform.parent = null; } m_SelectingInteractor = interactor; // special case where the interactor will override this objects movement type (used for Sockets and other absolute interactors) m_CurrentMovementType = (interactor.selectedInteractableMovementTypeOverride != null) ? interactor.selectedInteractableMovementTypeOverride.Value : m_MovementType; // remember RigidBody settings and setup to move m_WasKinematic = m_RigidBody.isKinematic; m_UsedGravity = m_RigidBody.useGravity; m_RigidBody.isKinematic = (m_CurrentMovementType == XRBaseInteractable.MovementType.Kinematic); m_RigidBody.useGravity = false; m_RigidBody.drag = 0f; m_RigidBody.angularDrag = 0f; // forget if we have previous detach velocities m_DetachVelocity = m_DetachAngularVelocity = Vector3.zero; UpdateInteractorLocalPose(interactor); var teleportOnSelect = false; if (teleportOnSelect) { Teleport(m_SelectingInteractor.attachTransform); } else if (m_AttachEaseInTime > 0.0f) { m_TargetWorldPosition = m_RigidBody.worldCenterOfMass; m_TargetWorldRotation = transform.rotation; m_CurrentAttachEaseTime = 0f; } SmoothVelocityStart(); }
internal void UnregisterInteractor(XRBaseInteractor interactor) { if (m_Interactors.Contains(interactor)) { ClearInteractorHover(interactor, null); ClearInteractorSelection(interactor); m_Interactors.Remove(interactor); #if AR_FOUNDATION_PRESENT if (interactor is ARGestureInteractor) { m_GestureInteractablesNeedReconnect = true; } #endif } }
/// <summary> /// Initiates selection of an Interactable by an Interactor. This method may cause the Interactable to first exit being selected. /// </summary> /// <param name="interactor">The Interactor that is selecting.</param> /// <param name="interactable">The Interactable being selected.</param> /// <remarks> /// This attempt will be ignored if the Interactor requires exclusive selection of an Interactable and that /// Interactable is already selected by another Interactor. /// </remarks> public virtual void SelectEnter(XRBaseInteractor interactor, XRBaseInteractable interactable) { if (interactable.isSelected && interactable.selectingInteractor != interactor) { if (interactor.requireSelectExclusive) { return; } SelectExit(interactable.selectingInteractor, interactable); } m_SelectEnterEventArgs.interactor = interactor; m_SelectEnterEventArgs.interactable = interactable; SelectEnter(interactor, interactable, m_SelectEnterEventArgs); }
/// <summary> /// Calculates distance squared to interactor (based on colliders). /// </summary> /// <param name="interactor">Interactor to calculate distance against.</param> /// <returns>Minimum distance between the interactor and this interactable's colliders.</returns> public float GetDistanceSqrToInteractor(XRBaseInteractor interactor) { if (!interactor) { return(float.MaxValue); } float minDistanceSqr = float.MaxValue; foreach (var col in m_Colliders) { var offset = (interactor.attachTransform.position - col.transform.position); minDistanceSqr = Mathf.Min(offset.sqrMagnitude, minDistanceSqr); } return(minDistanceSqr); }
public virtual void UnregisterInteractor(XRBaseInteractor interactor) { if (m_Interactors.Contains(interactor)) { ClearInteractorHover(interactor, null); SelectCancel(interactor, interactor.selectTarget); m_Interactors.Remove(interactor); #if AR_FOUNDATION_PRESENT if (interactor is ARGestureInteractor) { m_GestureInteractablesNeedReconnect = true; } #endif } }
void SelectEnter(XRBaseInteractor interactor, XRBaseInteractable interactable) { // allow new exclusive selection to take precedence over previous non-exclusive selection (useful Interactors like Sockets) if (interactor.isSelectExclusive) { for (int i = 0; i < m_Interactors.Count; i++) { if (m_Interactors[i].selectTarget == interactable && !m_Interactors[i].isSelectExclusive) { SelectExit(m_Interactors[i], interactable); } } } interactor.OnSelectEnter(interactable); interactable.OnSelectEnter(interactor); }
/// <summary> /// Unregister an Interactor so it is no longer processed. /// </summary> /// <param name="interactor">The Interactor to be unregistered.</param> public virtual void UnregisterInteractor(XRBaseInteractor interactor) { if (!m_Interactors.Contains(interactor)) { return; } CancelInteractorSelection(interactor); CancelInteractorHover(interactor); m_Interactors.Remove(interactor); m_InteractorUnregisteredEventArgs.manager = this; m_InteractorUnregisteredEventArgs.interactor = interactor; interactor.OnUnregistered(m_InteractorUnregisteredEventArgs); interactorUnregistered?.Invoke(m_InteractorUnregisteredEventArgs); }
/// <summary>This method is called by the interaction manager /// when the interactor first initiates hovering over an interactable.</summary> /// <param name="interactor">Interactor that is initiating the hover.</param> protected internal virtual void OnHoverEnter(XRBaseInteractor interactor) { if (m_CustomReticle) { AttachCustomReticle(interactor); } isHovered = true; m_HoveringInteractors.Add(interactor); if (m_HoveringInteractors.Count == 1) { m_OnFirstHoverEnter?.Invoke(interactor); } m_OnHoverEnter?.Invoke(interactor); }