using System.Collections.Generic; using UnityEngine.Scripting.APIUpdating; using UnityEngine.XR.Interaction.Toolkit.Interactors; namespace UnityEngine.XR.Interaction.Toolkit.Interactables { /// /// An interface that represents an Interactable component which /// an Interactor component can select. /// /// [MovedFrom("UnityEngine.XR.Interaction.Toolkit")] public interface IXRSelectInteractable : IXRInteractable { /// /// The event that is called only when the first Interactor begins selecting /// this Interactable as the sole selecting Interactor. Subsequent Interactors that /// begin selecting this Interactable will not cause this event to be invoked as /// long as any others are still selecting. /// /// /// The passed to each listener is only valid while the event is invoked, /// do not hold a reference to it. /// /// /// SelectEnterEvent firstSelectEntered { get; } /// /// The event that is called only when the last remaining selecting Interactor /// ends selecting this Interactable. /// /// /// The passed to each listener is only valid while the event is invoked, /// do not hold a reference to it. /// /// /// SelectExitEvent lastSelectExited { get; } /// /// The event that is called when an Interactor begins selecting this Interactable. /// /// /// The passed to each listener is only valid while the event is invoked, /// do not hold a reference to it. /// /// SelectEnterEvent selectEntered { get; } /// /// The event that is called when an Interactor ends selecting this Interactable. /// /// /// The passed to each listener is only valid while the event is invoked, /// do not hold a reference to it. /// /// SelectExitEvent selectExited { get; } /// /// (Read Only) The list of Interactors currently selecting this Interactable (may by empty). /// /// /// You should treat this as a read only view of the list and should not modify it. /// It is exposed as a rather than an to avoid GC Allocations /// when enumerating the list. /// /// /// List interactorsSelecting { get; } /// /// (Read Only) The first interactor that selected this interactable since not being selected by any interactor. /// The interactor may not currently be selecting this interactable, which would be the case /// when it released while multiple interactors were selecting this interactable. /// /// IXRSelectInteractor firstInteractorSelecting { get; } /// /// (Read Only) Indicates whether this interactable is currently being selected by any interactor. /// /// /// In other words, returns whether contains any interactors. /// /// /// interactorsSelecting.Count > 0 /// /// /// bool isSelected { get; } /// /// Indicates the selection policy of an Interactable. /// /// InteractableSelectMode selectMode { get; } /// /// Determines if a given Interactor can select this Interactable. /// /// Interactor to check for a valid selection with. /// Returns if selection is valid this frame. Returns if not. /// bool IsSelectableBy(IXRSelectInteractor interactor); /// /// Gets the world position and rotation of the Attach Transform captured during the moment of selection. /// /// The specific Interactor as context to get the attachment point for. /// Returns the world pose of the attachment point during the moment of selection, /// and otherwise the identity if it was not selected by it during the current selection stack. /// /// /// Pose GetAttachPoseOnSelect(IXRSelectInteractor interactor); /// /// Gets the local position and rotation of the Attach Transform captured during the moment of selection. /// /// The specific Interactor as context to get the attachment point for. /// Returns the local pose of the attachment point during the moment of selection, /// and otherwise the identity if it was not selected by it during the current selection stack. /// /// /// Pose GetLocalAttachPoseOnSelect(IXRSelectInteractor interactor); /// /// The calls this method /// right before the Interactor first initiates selection of an Interactable /// in a first pass. /// /// Event data containing the Interactor that is initiating the selection. /// /// is only valid during this method call, do not hold a reference to it. /// /// void OnSelectEntering(SelectEnterEventArgs args); /// /// The calls this method /// when the Interactor first initiates selection of an Interactable /// in a second pass. /// /// Event data containing the Interactor that is initiating the selection. /// /// is only valid during this method call, do not hold a reference to it. /// /// void OnSelectEntered(SelectEnterEventArgs args); /// /// The calls this method /// right before the Interactor ends selection of an Interactable /// in a first pass. /// /// Event data containing the Interactor that is ending the selection. /// /// is only valid during this method call, do not hold a reference to it. /// /// void OnSelectExiting(SelectExitEventArgs args); /// /// The calls this method /// when the Interactor ends selection of an Interactable /// in a second pass. /// /// Event data containing the Interactor that is ending the selection. /// /// is only valid during this method call, do not hold a reference to it. /// /// void OnSelectExited(SelectExitEventArgs args); } /// /// Extension methods for . /// /// [MovedFrom("UnityEngine.XR.Interaction.Toolkit")] public static class XRSelectInteractableExtensions { /// /// Gets the oldest interactor currently selecting this interactable. /// This is a convenience method for when the interactable does not support being selected by multiple interactors at a time. /// /// The interactable to operate on. /// Returns the oldest interactor currently selecting this interactable. /// /// Equivalent to interactorsSelecting.Count > 0 ? interactorsSelecting[0] : null /// /// public static IXRSelectInteractor GetOldestInteractorSelecting(this IXRSelectInteractable interactable) => interactable?.interactorsSelecting.Count > 0 ? interactable.interactorsSelecting[0] : null; /// /// Gets whether the interactable is currently being selected by an interactor associated with the left hand or controller. /// /// The interactable to operate on. /// Returns if any interactor currently selecting this interactable has of . /// /// This method will return even if it is not exclusively being selected by the left hand or controller. /// In other words, it will still return if the interactable is also being selected by /// an interactor associated with the right hand or controller. /// /// /// public static bool IsSelectedByLeft(this IXRSelectInteractable interactable) => IsSelectedBy(interactable, InteractorHandedness.Left); /// /// Gets whether the interactable is currently being selected by an interactor associated with the right hand or controller. /// /// The interactable to operate on. /// Returns if any interactor currently selecting this interactable has of . /// /// This method will return even if it is not exclusively being selected by the right hand or controller. /// In other words, it will still return if the interactable is also being selected by /// an interactor associated with the left hand or controller. /// /// /// public static bool IsSelectedByRight(this IXRSelectInteractable interactable) => IsSelectedBy(interactable, InteractorHandedness.Right); static bool IsSelectedBy(IXRSelectInteractable interactable, InteractorHandedness handedness) { var interactorsSelecting = interactable.interactorsSelecting; for (var i = 0; i < interactorsSelecting.Count; ++i) { if (interactorsSelecting[i].handedness == handedness) return true; } return false; } } /// /// Options for the selection policy of an Interactable. /// /// [MovedFrom("UnityEngine.XR.Interaction.Toolkit")] public enum InteractableSelectMode { /// /// Allows the Interactable to only be selected by a single Interactor at a time /// and allows other Interactors to take selection by automatically deselecting. /// Single, /// /// Allows for multiple Interactors at a time to select the Interactable. /// /// /// This option can be disabled in the Inspector window by adding the /// with a value of to a derived class of . /// Multiple, } }