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,
}
}