forked from cgvr/DeltaVR
		
	
		
			
				
	
	
		
			587 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			587 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using System;
 | 
						|
using System.Collections.Generic;
 | 
						|
using UnityEngine;
 | 
						|
using UnityEngine.Events;
 | 
						|
using UnityEngine.XR.Interaction.Toolkit;
 | 
						|
using UnityEngine.InputSystem;
 | 
						|
using UnityEngine.Serialization;
 | 
						|
 | 
						|
/// <summary>
 | 
						|
/// Use this class to map input actions to each controller state (mode)
 | 
						|
/// and set up the transitions between controller states (modes).
 | 
						|
/// </summary>
 | 
						|
[AddComponentMenu("XR/Action Based Controller Manager")]
 | 
						|
[DefaultExecutionOrder(kControllerManagerUpdateOrder)]
 | 
						|
public class ActionBasedControllerManager : MonoBehaviour
 | 
						|
{
 | 
						|
    public const int kControllerManagerUpdateOrder = 10;
 | 
						|
 | 
						|
    public enum StateId
 | 
						|
    {
 | 
						|
        None,
 | 
						|
        Select,
 | 
						|
        Teleport,
 | 
						|
        Interact,
 | 
						|
    }
 | 
						|
 | 
						|
    [Serializable]
 | 
						|
    public class StateEnterEvent : UnityEvent<StateId>
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    [Serializable]
 | 
						|
    public class StateUpdateEvent : UnityEvent
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    [Serializable]
 | 
						|
    public class StateExitEvent : UnityEvent<StateId>
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Use this class to create a controller state and set up its enter, update, and exit events.
 | 
						|
    /// </summary>
 | 
						|
    [Serializable]
 | 
						|
    public class ControllerState
 | 
						|
    {
 | 
						|
        [SerializeField]
 | 
						|
        [Tooltip("Sets the controller state to be active. " +
 | 
						|
                 "For the default states, setting this value to true will automatically update their StateUpdateEvent.")]
 | 
						|
        bool m_Enabled;
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Sets the controller state to be active.
 | 
						|
        /// For the default states, setting this value to true will automatically update their <see cref="StateUpdateEvent"/>.
 | 
						|
        /// </summary>
 | 
						|
        public bool enabled
 | 
						|
        {
 | 
						|
            get => m_Enabled;
 | 
						|
            set => m_Enabled = value;
 | 
						|
        }
 | 
						|
 | 
						|
        [SerializeField] [HideInInspector] StateId m_Id;
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Sets the identifier of the <see cref="ControllerState"/> from all the optional Controller States that the <see cref="ActionBasedControllerManager"/> holds.
 | 
						|
        /// </summary>
 | 
						|
        public StateId id
 | 
						|
        {
 | 
						|
            get => m_Id;
 | 
						|
            set => m_Id = value;
 | 
						|
        }
 | 
						|
 | 
						|
        [SerializeField] StateEnterEvent m_OnEnter = new StateEnterEvent();
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// The <see cref="StateEnterEvent"/> that will be invoked when entering the controller state.
 | 
						|
        /// </summary>
 | 
						|
        public StateEnterEvent onEnter
 | 
						|
        {
 | 
						|
            get => m_OnEnter;
 | 
						|
            set => m_OnEnter = value;
 | 
						|
        }
 | 
						|
 | 
						|
        [SerializeField] StateUpdateEvent m_OnUpdate = new StateUpdateEvent();
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// The <see cref="StateUpdateEvent"/> that will be invoked when updating the controller state.
 | 
						|
        /// </summary>
 | 
						|
        public StateUpdateEvent onUpdate
 | 
						|
        {
 | 
						|
            get => m_OnUpdate;
 | 
						|
            set => m_OnUpdate = value;
 | 
						|
        }
 | 
						|
 | 
						|
        [SerializeField] StateExitEvent m_OnExit = new StateExitEvent();
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// The <see cref="StateExitEvent"/> that will be invoked when exiting the controller state.
 | 
						|
        /// </summary>
 | 
						|
        public StateExitEvent onExit
 | 
						|
        {
 | 
						|
            get => m_OnExit;
 | 
						|
            set => m_OnExit = value;
 | 
						|
        }
 | 
						|
 | 
						|
        public ControllerState(StateId defaultId = StateId.None) => this.id = defaultId;
 | 
						|
    }
 | 
						|
 | 
						|
    [Space]
 | 
						|
    [Header("Controller GameObjects")]
 | 
						|
    [SerializeField, FormerlySerializedAs("m_BaseControllerGO")]
 | 
						|
    [Tooltip(
 | 
						|
        "The base controller GameObject, used for changing default settings on its components during state transitions.")]
 | 
						|
    GameObject m_BaseControllerGameObject;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// The base controller <see cref="GameObject"/>, used for changing default settings on its components during state transitions.
 | 
						|
    /// </summary>
 | 
						|
    public GameObject baseControllerGameObject
 | 
						|
    {
 | 
						|
        get => m_BaseControllerGameObject;
 | 
						|
        set => m_BaseControllerGameObject = value;
 | 
						|
    }
 | 
						|
 | 
						|
    [SerializeField, FormerlySerializedAs("m_TeleportControllerGO")]
 | 
						|
    [Tooltip(
 | 
						|
        "The teleport controller GameObject, used for changing default settings on its components during state transitions.")]
 | 
						|
    GameObject m_TeleportControllerGameObject;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// The teleport controller <see cref="GameObject"/>, used for changing default settings on its components during state transitions.
 | 
						|
    /// </summary>
 | 
						|
    public GameObject teleportControllerGameObject
 | 
						|
    {
 | 
						|
        get => m_TeleportControllerGameObject;
 | 
						|
        set => m_TeleportControllerGameObject = value;
 | 
						|
    }
 | 
						|
 | 
						|
    [Space]
 | 
						|
    [Header("Controller Actions")]
 | 
						|
 | 
						|
    // State transition actions
 | 
						|
    [SerializeField]
 | 
						|
    [Tooltip("The reference to the action of activating the teleport mode for this controller.")]
 | 
						|
    InputActionReference m_TeleportModeActivate;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// The reference to the action of activating the teleport mode for this controller."
 | 
						|
    /// </summary>
 | 
						|
    public InputActionReference teleportModeActivate
 | 
						|
    {
 | 
						|
        get => m_TeleportModeActivate;
 | 
						|
        set => m_TeleportModeActivate = value;
 | 
						|
    }
 | 
						|
 | 
						|
    [SerializeField] [Tooltip("The reference to the action of canceling the teleport mode for this controller.")]
 | 
						|
    InputActionReference m_TeleportModeCancel;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// The reference to the action of canceling the teleport mode for this controller."
 | 
						|
    /// </summary>
 | 
						|
    public InputActionReference teleportModeCancel
 | 
						|
    {
 | 
						|
        get => m_TeleportModeCancel;
 | 
						|
        set => m_TeleportModeCancel = value;
 | 
						|
    }
 | 
						|
 | 
						|
    // Character movement actions
 | 
						|
    [SerializeField] [Tooltip("The reference to the action of turning the XR rig with this controller.")]
 | 
						|
    InputActionReference m_Turn;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// The reference to the action of turning the XR rig with this controller.
 | 
						|
    /// </summary>
 | 
						|
    public InputActionReference turn
 | 
						|
    {
 | 
						|
        get => m_Turn;
 | 
						|
        set => m_Turn = value;
 | 
						|
    }
 | 
						|
 | 
						|
    [SerializeField] [Tooltip("The reference to the action of moving the XR rig with this controller.")]
 | 
						|
    InputActionReference m_Move;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// The reference to the action of moving the XR rig with this controller.
 | 
						|
    /// </summary>
 | 
						|
    public InputActionReference move
 | 
						|
    {
 | 
						|
        get => m_Move;
 | 
						|
        set => m_Move = value;
 | 
						|
    }
 | 
						|
 | 
						|
    // Object control actions
 | 
						|
    [SerializeField, FormerlySerializedAs("m_TranslateObject")]
 | 
						|
    [Tooltip("The reference to the action of translating the selected object of this controller.")]
 | 
						|
    InputActionReference m_TranslateAnchor;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// The reference to the action of translating the selected object of this controller.
 | 
						|
    /// </summary>
 | 
						|
    public InputActionReference translateAnchor
 | 
						|
    {
 | 
						|
        get => m_TranslateAnchor;
 | 
						|
        set => m_TranslateAnchor = value;
 | 
						|
    }
 | 
						|
 | 
						|
    [SerializeField, FormerlySerializedAs("m_RotateObject")]
 | 
						|
    [Tooltip("The reference to the action of rotating the selected object of this controller.")]
 | 
						|
    InputActionReference m_RotateAnchor;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// The reference to the action of rotating the selected object of this controller.
 | 
						|
    /// </summary>
 | 
						|
    public InputActionReference rotateAnchor
 | 
						|
    {
 | 
						|
        get => m_RotateAnchor;
 | 
						|
        set => m_RotateAnchor = value;
 | 
						|
    }
 | 
						|
 | 
						|
    [Space]
 | 
						|
    [Header("Default States")]
 | 
						|
#pragma warning disable IDE0044 // Add readonly modifier -- readonly fields cannot be serialized by Unity
 | 
						|
    [SerializeField]
 | 
						|
    [Tooltip("The default Select state and events for the controller.")]
 | 
						|
    ControllerState m_SelectState = new ControllerState(StateId.Select);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// (Read Only) The default Select state.
 | 
						|
    /// </summary>
 | 
						|
    public ControllerState selectState => m_SelectState;
 | 
						|
 | 
						|
    [SerializeField] [Tooltip("The default Teleport state and events for the controller.")]
 | 
						|
    ControllerState m_TeleportState = new ControllerState(StateId.Teleport);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// (Read Only) The default Teleport state.
 | 
						|
    /// </summary>
 | 
						|
    public ControllerState teleportState => m_TeleportState;
 | 
						|
 | 
						|
    [SerializeField] [Tooltip("The default Interact state and events for the controller.")]
 | 
						|
    ControllerState m_InteractState = new ControllerState(StateId.Interact);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// (Read Only) The default Interact state.
 | 
						|
    /// </summary>
 | 
						|
    public ControllerState interactState => m_InteractState;
 | 
						|
#pragma warning restore IDE0044
 | 
						|
 | 
						|
    // The list to store and run the default states
 | 
						|
    readonly List<ControllerState> m_DefaultStates = new List<ControllerState>();
 | 
						|
 | 
						|
    // Components of the controller to switch on and off for different states
 | 
						|
    XRBaseController m_BaseController;
 | 
						|
    XRBaseInteractor m_BaseInteractor;
 | 
						|
    XRInteractorLineVisual m_BaseLineVisual;
 | 
						|
 | 
						|
    XRBaseController m_TeleportController;
 | 
						|
    XRBaseInteractor m_TeleportInteractor;
 | 
						|
    XRInteractorLineVisual m_TeleportLineVisual;
 | 
						|
 | 
						|
    protected void OnEnable()
 | 
						|
    {
 | 
						|
        FindBaseControllerComponents();
 | 
						|
        FindTeleportControllerComponents();
 | 
						|
 | 
						|
        // Add default state events.
 | 
						|
        m_SelectState.onEnter.AddListener(OnEnterSelectState);
 | 
						|
        m_SelectState.onUpdate.AddListener(OnUpdateSelectState);
 | 
						|
        m_SelectState.onExit.AddListener(OnExitSelectState);
 | 
						|
 | 
						|
        m_TeleportState.onEnter.AddListener(OnEnterTeleportState);
 | 
						|
        m_TeleportState.onUpdate.AddListener(OnUpdateTeleportState);
 | 
						|
        m_TeleportState.onExit.AddListener(OnExitTeleportState);
 | 
						|
 | 
						|
        m_InteractState.onEnter.AddListener(OnEnterInteractState);
 | 
						|
        m_InteractState.onUpdate.AddListener(OnUpdateInteractState);
 | 
						|
        m_InteractState.onExit.AddListener(OnExitInteractState);
 | 
						|
    }
 | 
						|
 | 
						|
    protected void OnDisable()
 | 
						|
    {
 | 
						|
        // Remove default state events.
 | 
						|
        m_SelectState.onEnter.RemoveListener(OnEnterSelectState);
 | 
						|
        m_SelectState.onUpdate.RemoveListener(OnUpdateSelectState);
 | 
						|
        m_SelectState.onExit.RemoveListener(OnExitSelectState);
 | 
						|
 | 
						|
        m_TeleportState.onEnter.RemoveListener(OnEnterTeleportState);
 | 
						|
        m_TeleportState.onUpdate.RemoveListener(OnUpdateTeleportState);
 | 
						|
        m_TeleportState.onExit.RemoveListener(OnExitTeleportState);
 | 
						|
 | 
						|
        m_InteractState.onEnter.RemoveListener(OnEnterInteractState);
 | 
						|
        m_InteractState.onUpdate.RemoveListener(OnUpdateInteractState);
 | 
						|
        m_InteractState.onExit.RemoveListener(OnExitInteractState);
 | 
						|
    }
 | 
						|
 | 
						|
    // Start is called before the first frame update
 | 
						|
    protected void Start()
 | 
						|
    {
 | 
						|
        // Add states to the list
 | 
						|
        m_DefaultStates.Add(m_SelectState);
 | 
						|
        m_DefaultStates.Add(m_TeleportState);
 | 
						|
        m_DefaultStates.Add(m_InteractState);
 | 
						|
 | 
						|
        // Initialize to start in m_SelectState
 | 
						|
        TransitionState(null, m_SelectState);
 | 
						|
    }
 | 
						|
 | 
						|
    // Update is called once per frame
 | 
						|
    protected void Update()
 | 
						|
    {
 | 
						|
        foreach (var state in m_DefaultStates)
 | 
						|
        {
 | 
						|
            if (state.enabled)
 | 
						|
            {
 | 
						|
                state.onUpdate.Invoke();
 | 
						|
                return;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    void TransitionState(ControllerState fromState, ControllerState toState)
 | 
						|
    {
 | 
						|
        if (fromState != null)
 | 
						|
        {
 | 
						|
            fromState.enabled = false;
 | 
						|
            fromState.onExit.Invoke(toState?.id ?? StateId.None);
 | 
						|
        }
 | 
						|
 | 
						|
        if (toState != null)
 | 
						|
        {
 | 
						|
            toState.onEnter.Invoke(fromState?.id ?? StateId.None);
 | 
						|
            toState.enabled = true;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    void FindBaseControllerComponents()
 | 
						|
    {
 | 
						|
        if (m_BaseControllerGameObject == null)
 | 
						|
        {
 | 
						|
            Debug.LogWarning("Missing reference to Base Controller GameObject.", this);
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        if (m_BaseController == null)
 | 
						|
        {
 | 
						|
            m_BaseController = m_BaseControllerGameObject.GetComponent<XRBaseController>();
 | 
						|
            if (m_BaseController == null)
 | 
						|
                Debug.LogWarning(
 | 
						|
                    $"Cannot find any {nameof(XRBaseController)} component on the Base Controller GameObject.", this);
 | 
						|
        }
 | 
						|
 | 
						|
        if (m_BaseInteractor == null)
 | 
						|
        {
 | 
						|
            m_BaseInteractor = m_BaseControllerGameObject.GetComponent<XRBaseInteractor>();
 | 
						|
            if (m_BaseInteractor == null)
 | 
						|
                Debug.LogWarning(
 | 
						|
                    $"Cannot find any {nameof(XRBaseInteractor)} component on the Base Controller GameObject.", this);
 | 
						|
        }
 | 
						|
 | 
						|
        // Only check the line visual component for RayInteractor, since DirectInteractor does not use the line visual component
 | 
						|
        if (m_BaseInteractor is XRRayInteractor && m_BaseLineVisual == null)
 | 
						|
        {
 | 
						|
            m_BaseLineVisual = m_BaseControllerGameObject.GetComponent<XRInteractorLineVisual>();
 | 
						|
            if (m_BaseLineVisual == null)
 | 
						|
                Debug.LogWarning(
 | 
						|
                    $"Cannot find any {nameof(XRInteractorLineVisual)} component on the Base Controller GameObject.",
 | 
						|
                    this);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    void FindTeleportControllerComponents()
 | 
						|
    {
 | 
						|
        if (m_TeleportControllerGameObject == null)
 | 
						|
        {
 | 
						|
            Debug.LogWarning("Missing reference to the Teleport Controller GameObject.", this);
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        if (m_TeleportController == null)
 | 
						|
        {
 | 
						|
            m_TeleportController = m_TeleportControllerGameObject.GetComponent<XRBaseController>();
 | 
						|
            if (m_TeleportController == null)
 | 
						|
                Debug.LogWarning(
 | 
						|
                    $"Cannot find {nameof(XRBaseController)} component on the Teleport Controller GameObject.", this);
 | 
						|
        }
 | 
						|
 | 
						|
        if (m_TeleportLineVisual == null)
 | 
						|
        {
 | 
						|
            m_TeleportLineVisual = m_TeleportControllerGameObject.GetComponent<XRInteractorLineVisual>();
 | 
						|
            if (m_TeleportLineVisual == null)
 | 
						|
                Debug.LogWarning(
 | 
						|
                    $"Cannot find {nameof(XRInteractorLineVisual)} component on the Teleport Controller GameObject.",
 | 
						|
                    this);
 | 
						|
        }
 | 
						|
 | 
						|
        if (m_TeleportInteractor == null)
 | 
						|
        {
 | 
						|
            m_TeleportInteractor = m_TeleportControllerGameObject.GetComponent<XRRayInteractor>();
 | 
						|
            if (m_TeleportInteractor == null)
 | 
						|
                Debug.LogWarning(
 | 
						|
                    $"Cannot find {nameof(XRRayInteractor)} component on the Teleport Controller GameObject.", this);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Find and configure the components on the base controller.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="enable"> Set it true to enable the base controller, false to disable it. </param>
 | 
						|
    void SetBaseController(bool enable)
 | 
						|
    {
 | 
						|
        FindBaseControllerComponents();
 | 
						|
 | 
						|
        if (m_BaseController != null)
 | 
						|
            m_BaseController.enableInputActions = enable;
 | 
						|
 | 
						|
        if (m_BaseInteractor != null)
 | 
						|
            m_BaseInteractor.enabled = enable;
 | 
						|
 | 
						|
        if (m_BaseInteractor is XRRayInteractor && m_BaseLineVisual != null)
 | 
						|
            m_BaseLineVisual.enabled = enable;
 | 
						|
    }
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Find and configure the components on the teleport controller.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="enable"> Set it true to enable the teleport controller, false to disable it. </param>
 | 
						|
    void SetTeleportController(bool enable)
 | 
						|
    {
 | 
						|
        FindTeleportControllerComponents();
 | 
						|
 | 
						|
        if (m_TeleportLineVisual != null)
 | 
						|
            m_TeleportLineVisual.enabled = enable;
 | 
						|
 | 
						|
        if (m_TeleportController != null)
 | 
						|
            m_TeleportController.enableInputActions = enable;
 | 
						|
 | 
						|
        if (m_TeleportInteractor != null)
 | 
						|
            m_TeleportInteractor.enabled = enable;
 | 
						|
    }
 | 
						|
 | 
						|
    void OnEnterSelectState(StateId previousStateId)
 | 
						|
    {
 | 
						|
        // Change controller and enable actions depending on the previous state
 | 
						|
        switch (previousStateId)
 | 
						|
        {
 | 
						|
            case StateId.None:
 | 
						|
                // Enable transitions to Teleport state 
 | 
						|
                EnableAction(m_TeleportModeActivate);
 | 
						|
                EnableAction(m_TeleportModeCancel);
 | 
						|
 | 
						|
                // Enable turn and move actions
 | 
						|
                EnableAction(m_Turn);
 | 
						|
                EnableAction(m_Move);
 | 
						|
 | 
						|
                // Enable base controller components
 | 
						|
                SetBaseController(true);
 | 
						|
                break;
 | 
						|
            case StateId.Select:
 | 
						|
                break;
 | 
						|
            case StateId.Teleport:
 | 
						|
                EnableAction(m_Turn);
 | 
						|
                EnableAction(m_Move);
 | 
						|
                SetBaseController(true);
 | 
						|
                break;
 | 
						|
            case StateId.Interact:
 | 
						|
                EnableAction(m_Turn);
 | 
						|
                EnableAction(m_Move);
 | 
						|
                break;
 | 
						|
            default:
 | 
						|
                Debug.Assert(false, $"Unhandled case when entering Select from {previousStateId}.");
 | 
						|
                break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    void OnExitSelectState(StateId nextStateId)
 | 
						|
    {
 | 
						|
        // Change controller and disable actions depending on the next state
 | 
						|
        switch (nextStateId)
 | 
						|
        {
 | 
						|
            case StateId.None:
 | 
						|
                break;
 | 
						|
            case StateId.Select:
 | 
						|
                break;
 | 
						|
            case StateId.Teleport:
 | 
						|
                DisableAction(m_Turn);
 | 
						|
                DisableAction(m_Move);
 | 
						|
                SetBaseController(false);
 | 
						|
                break;
 | 
						|
            case StateId.Interact:
 | 
						|
                DisableAction(m_Turn);
 | 
						|
                DisableAction(m_Move);
 | 
						|
                break;
 | 
						|
            default:
 | 
						|
                Debug.Assert(false, $"Unhandled case when exiting Select to {nextStateId}.");
 | 
						|
                break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    void OnEnterTeleportState(StateId previousStateId) => SetTeleportController(true);
 | 
						|
 | 
						|
    void OnExitTeleportState(StateId nextStateId) => SetTeleportController(false);
 | 
						|
 | 
						|
    void OnEnterInteractState(StateId previousStateId)
 | 
						|
    {
 | 
						|
        // Enable object control actions
 | 
						|
        EnableAction(m_TranslateAnchor);
 | 
						|
        EnableAction(m_RotateAnchor);
 | 
						|
    }
 | 
						|
 | 
						|
    void OnExitInteractState(StateId nextStateId)
 | 
						|
    {
 | 
						|
        // Disable object control actions
 | 
						|
        DisableAction(m_TranslateAnchor);
 | 
						|
        DisableAction(m_RotateAnchor);
 | 
						|
    }
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// This method is automatically called each frame to handle initiating transitions out of the Select state.
 | 
						|
    /// </summary>
 | 
						|
    void OnUpdateSelectState()
 | 
						|
    {
 | 
						|
        // Transition from Select state to Teleport state when the user triggers the "Teleport Mode Activate" action but not the "Cancel Teleport" action
 | 
						|
        var teleportModeAction = GetInputAction(m_TeleportModeActivate);
 | 
						|
        var cancelTeleportModeAction = GetInputAction(m_TeleportModeCancel);
 | 
						|
 | 
						|
        var triggerTeleportMode = teleportModeAction != null && teleportModeAction.triggered;
 | 
						|
        var cancelTeleport = cancelTeleportModeAction != null && cancelTeleportModeAction.triggered;
 | 
						|
 | 
						|
        if (triggerTeleportMode && !cancelTeleport)
 | 
						|
        {
 | 
						|
            TransitionState(m_SelectState, m_TeleportState);
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        // Transition from Select state to Interact state when the interactor has a selectTarget
 | 
						|
        FindBaseControllerComponents();
 | 
						|
 | 
						|
        if (m_BaseInteractor.selectTarget != null)
 | 
						|
            TransitionState(m_SelectState, m_InteractState);
 | 
						|
    }
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Updated every frame to handle the transition to m_SelectState state.
 | 
						|
    /// </summary>
 | 
						|
    void OnUpdateTeleportState()
 | 
						|
    {
 | 
						|
        // Transition from Teleport state to Select state when we release the Teleport trigger or cancel Teleport mode
 | 
						|
 | 
						|
        var teleportModeAction = GetInputAction(m_TeleportModeActivate);
 | 
						|
        var cancelTeleportModeAction = GetInputAction(m_TeleportModeCancel);
 | 
						|
 | 
						|
        var cancelTeleport = cancelTeleportModeAction != null && cancelTeleportModeAction.triggered;
 | 
						|
        var releasedTeleport = teleportModeAction != null && teleportModeAction.phase == InputActionPhase.Waiting;
 | 
						|
 | 
						|
        if (cancelTeleport || releasedTeleport)
 | 
						|
            TransitionState(m_TeleportState, m_SelectState);
 | 
						|
    }
 | 
						|
 | 
						|
    void OnUpdateInteractState()
 | 
						|
    {
 | 
						|
        // Transition from Interact state to Select state when the base interactor no longer has a select target
 | 
						|
        if (m_BaseInteractor.selectTarget == null)
 | 
						|
            TransitionState(m_InteractState, m_SelectState);
 | 
						|
    }
 | 
						|
 | 
						|
    static void EnableAction(InputActionReference actionReference)
 | 
						|
    {
 | 
						|
        var action = GetInputAction(actionReference);
 | 
						|
        if (action != null && !action.enabled)
 | 
						|
            action.Enable();
 | 
						|
    }
 | 
						|
 | 
						|
    static void DisableAction(InputActionReference actionReference)
 | 
						|
    {
 | 
						|
        var action = GetInputAction(actionReference);
 | 
						|
        if (action != null && action.enabled)
 | 
						|
            action.Disable();
 | 
						|
    }
 | 
						|
 | 
						|
    static InputAction GetInputAction(InputActionReference actionReference)
 | 
						|
    {
 | 
						|
#pragma warning disable IDE0031 // Use null propagation -- Do not use for UnityEngine.Object types
 | 
						|
        return actionReference != null ? actionReference.action : null;
 | 
						|
#pragma warning restore IDE0031
 | 
						|
    }
 | 
						|
} |