using UnityEngine.Events; using UnityEngine.XR.Interaction.Toolkit; namespace UnityEngine.XR.Content.Interaction { /// /// An interactable that can be pressed by a direct interactor /// public class XRGripButton : XRBaseInteractable { [SerializeField] [Tooltip("The object that is visually pressed down")] Transform m_Button = null; [SerializeField] [Tooltip("The distance the button can be pressed")] float m_PressDistance = 0.1f; [SerializeField] [Tooltip("Treat this button like an on/off toggle")] bool m_ToggleButton = false; [SerializeField] [Tooltip("Events to trigger when the button is pressed")] UnityEvent m_OnPress; [SerializeField] [Tooltip("Events to trigger when the button is released")] UnityEvent m_OnRelease; bool m_Hovered = false; bool m_Selected = false; bool m_Toggled = false; /// /// The object that is visually pressed down /// public Transform button { get => m_Button; set => m_Button = value; } /// /// The distance the button can be pressed /// public float pressDistance { get => m_PressDistance; set => m_PressDistance = value; } /// /// Events to trigger when the button is pressed /// public UnityEvent onPress => m_OnPress; /// /// Events to trigger when the button is released /// public UnityEvent onRelease => m_OnRelease; void Start() { SetButtonHeight(0.0f); } protected override void OnEnable() { base.OnEnable(); if (m_ToggleButton) selectEntered.AddListener(StartTogglePress); else { selectEntered.AddListener(StartPress); selectExited.AddListener(EndPress); hoverEntered.AddListener(StartHover); hoverExited.AddListener(EndHover); } } protected override void OnDisable() { if (m_ToggleButton) selectEntered.RemoveListener(StartTogglePress); else { selectEntered.RemoveListener(StartPress); selectExited.RemoveListener(EndPress); hoverEntered.RemoveListener(StartHover); hoverExited.RemoveListener(EndHover); base.OnDisable(); } } void StartTogglePress(SelectEnterEventArgs args) { m_Toggled = !m_Toggled; if (m_Toggled) { SetButtonHeight(-m_PressDistance); m_OnPress.Invoke(); } else { SetButtonHeight(0.0f); m_OnRelease.Invoke(); } } void StartPress(SelectEnterEventArgs args) { SetButtonHeight(-m_PressDistance); m_OnPress.Invoke(); m_Selected = true; } void EndPress(SelectExitEventArgs args) { if (m_Hovered) m_OnRelease.Invoke(); SetButtonHeight(0.0f); m_Selected = false; } void StartHover(HoverEnterEventArgs args) { m_Hovered = true; if (m_Selected) SetButtonHeight(-m_PressDistance); } void EndHover(HoverExitEventArgs args) { m_Hovered = false; SetButtonHeight(0.0f); } void SetButtonHeight(float height) { if (m_Button == null) return; Vector3 newPosition = m_Button.localPosition; newPosition.y = height; m_Button.localPosition = newPosition; } void OnDrawGizmosSelected() { var pressStartPoint = transform.position; var pressDownDirection = -transform.up; if (m_Button != null) { pressStartPoint = m_Button.position; pressDownDirection = -m_Button.up; } Gizmos.color = Color.green; Gizmos.DrawLine(pressStartPoint, pressStartPoint + (pressDownDirection * m_PressDistance)); } void OnValidate() { SetButtonHeight(0.0f); } } }