Beispiel #1
0
 /// <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);
     }
 }
Beispiel #3
0
 /// <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);
        }
Beispiel #5
0
 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);
         }
     }
 }
Beispiel #13
0
 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);
         }
     }
 }
Beispiel #14
0
        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
            }
        }
Beispiel #15
0
        /// <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();
        }
Beispiel #17
0
        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);
        }
Beispiel #18
0
        /// <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);
        }
Beispiel #19
0
 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]);
             }
         }
     }
 }
Beispiel #20
0
        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);
        }
Beispiel #21
0
 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();
        }
Beispiel #24
0
        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
            }
        }
Beispiel #25
0
        /// <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
            }
        }
Beispiel #28
0
 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);
 }
Beispiel #29
0
        /// <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);
        }