ARSampleMenuManager.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. #if AR_FOUNDATION_PRESENT
  2. using UnityEngine.Events;
  3. using UnityEngine.EventSystems;
  4. using UnityEngine.UI;
  5. using UnityEngine.XR.Interaction.Toolkit.AR.Inputs;
  6. using UnityEngine.XR.Interaction.Toolkit.Inputs.Readers;
  7. using UnityEngine.XR.Interaction.Toolkit.Interactors;
  8. namespace UnityEngine.XR.Interaction.Toolkit.Samples.ARStarterAssets
  9. {
  10. /// <summary>
  11. /// Handles dismissing the object menu when clicking out the UI bounds, and showing the
  12. /// menu again when the create menu button is clicked after dismissal. Manages object deletion in the AR demo scene,
  13. /// and also handles the toggling between the object creation menu button and the delete button.
  14. /// </summary>
  15. public class ARSampleMenuManager : MonoBehaviour
  16. {
  17. [SerializeField]
  18. [Tooltip("Button that opens the create menu.")]
  19. Button m_CreateButton;
  20. /// <summary>
  21. /// Button that opens the create menu.
  22. /// </summary>
  23. public Button createButton
  24. {
  25. get => m_CreateButton;
  26. set => m_CreateButton = value;
  27. }
  28. [SerializeField]
  29. [Tooltip("Button that deletes a selected object.")]
  30. Button m_DeleteButton;
  31. /// <summary>
  32. /// Button that deletes a selected object.
  33. /// </summary>
  34. public Button deleteButton
  35. {
  36. get => m_DeleteButton;
  37. set => m_DeleteButton = value;
  38. }
  39. [SerializeField]
  40. [Tooltip("The menu with all the creatable objects.")]
  41. GameObject m_ObjectMenu;
  42. /// <summary>
  43. /// The menu with all the creatable objects.
  44. /// </summary>
  45. public GameObject objectMenu
  46. {
  47. get => m_ObjectMenu;
  48. set => m_ObjectMenu = value;
  49. }
  50. [SerializeField]
  51. [Tooltip("The animator for the object creation menu.")]
  52. Animator m_ObjectMenuAnimator;
  53. /// <summary>
  54. /// The animator for the object creation menu.
  55. /// </summary>
  56. public Animator objectMenuAnimator
  57. {
  58. get => m_ObjectMenuAnimator;
  59. set => m_ObjectMenuAnimator = value;
  60. }
  61. [SerializeField]
  62. [Tooltip("Button that closes the object creation menu.")]
  63. Button m_CancelButton;
  64. /// <summary>
  65. /// Button that closes the object creation menu.
  66. /// </summary>
  67. public Button cancelButton
  68. {
  69. get => m_CancelButton;
  70. set => m_CancelButton = value;
  71. }
  72. [SerializeField]
  73. [Tooltip("The interaction group for the AR demo scene.")]
  74. XRInteractionGroup m_InteractionGroup;
  75. /// <summary>
  76. /// The interaction group for the AR demo scene.
  77. /// </summary>
  78. public XRInteractionGroup interactionGroup
  79. {
  80. get => m_InteractionGroup;
  81. set => m_InteractionGroup = value;
  82. }
  83. [SerializeField]
  84. XRInputValueReader<Vector2> m_TapStartPositionInput = new XRInputValueReader<Vector2>("Tap Start Position");
  85. /// <summary>
  86. /// Input to use for the screen tap start position.
  87. /// </summary>
  88. /// <seealso cref="TouchscreenGestureInputController.tapStartPosition"/>
  89. public XRInputValueReader<Vector2> tapStartPositionInput
  90. {
  91. get => m_TapStartPositionInput;
  92. set => XRInputReaderUtility.SetInputProperty(ref m_TapStartPositionInput, value, this);
  93. }
  94. /// <summary>
  95. /// Calls the methods in its invocation list when the spawned object selection changes.
  96. /// </summary>
  97. public UnityEvent<int> spawnedObjectSelectionChanged
  98. {
  99. get => m_SpawnedObjectSelectionChanged;
  100. set => m_SpawnedObjectSelectionChanged = value;
  101. }
  102. [Header("Events")]
  103. [SerializeField]
  104. [Tooltip("Calls the methods in its invocation list when the spawned object selection changes.")]
  105. UnityEvent<int> m_SpawnedObjectSelectionChanged = new UnityEvent<int>();
  106. bool m_ShowObjectMenu;
  107. void OnEnable()
  108. {
  109. m_TapStartPositionInput.EnableDirectActionIfModeUsed();
  110. m_CreateButton.onClick.AddListener(ShowMenu);
  111. m_CancelButton.onClick.AddListener(HideMenu);
  112. m_DeleteButton.onClick.AddListener(DeleteFocusedObject);
  113. }
  114. void OnDisable()
  115. {
  116. m_TapStartPositionInput.DisableDirectActionIfModeUsed();
  117. m_ShowObjectMenu = false;
  118. m_CreateButton.onClick.RemoveListener(ShowMenu);
  119. m_CancelButton.onClick.RemoveListener(HideMenu);
  120. m_DeleteButton.onClick.RemoveListener(DeleteFocusedObject);
  121. }
  122. void Start()
  123. {
  124. HideMenu();
  125. }
  126. void Update()
  127. {
  128. if (m_ShowObjectMenu)
  129. {
  130. m_CreateButton.gameObject.SetActive(false);
  131. m_DeleteButton.gameObject.SetActive(false);
  132. var isPointerOverUI = EventSystem.current != null && EventSystem.current.IsPointerOverGameObject(-1);
  133. if (!isPointerOverUI && m_TapStartPositionInput.TryReadValue(out _))
  134. {
  135. HideMenu();
  136. }
  137. }
  138. else if (m_InteractionGroup is not null)
  139. {
  140. var currentFocusedObject = m_InteractionGroup.focusInteractable;
  141. if (currentFocusedObject != null && (!m_DeleteButton.isActiveAndEnabled || m_CreateButton.isActiveAndEnabled))
  142. {
  143. m_CreateButton.gameObject.SetActive(false);
  144. m_DeleteButton.gameObject.SetActive(true);
  145. }
  146. else if (currentFocusedObject == null && (!m_CreateButton.isActiveAndEnabled || m_DeleteButton.isActiveAndEnabled))
  147. {
  148. m_CreateButton.gameObject.SetActive(true);
  149. m_DeleteButton.gameObject.SetActive(false);
  150. }
  151. }
  152. }
  153. public void SetObjectToSpawn(int objectIndex)
  154. {
  155. m_SpawnedObjectSelectionChanged.Invoke(objectIndex);
  156. HideMenu();
  157. }
  158. void ShowMenu()
  159. {
  160. m_ShowObjectMenu = true;
  161. m_ObjectMenu.SetActive(true);
  162. if (!m_ObjectMenuAnimator.GetBool("Show"))
  163. {
  164. m_ObjectMenuAnimator.SetBool("Show", true);
  165. }
  166. }
  167. /// <summary>
  168. /// Triggers hide animation for menu.
  169. /// </summary>
  170. public void HideMenu()
  171. {
  172. m_ObjectMenuAnimator.SetBool("Show", false);
  173. m_ShowObjectMenu = false;
  174. }
  175. void DeleteFocusedObject()
  176. {
  177. if (m_InteractionGroup == null)
  178. return;
  179. var currentFocusedObject = m_InteractionGroup.focusInteractable;
  180. if (currentFocusedObject != null)
  181. {
  182. Destroy(currentFocusedObject.transform.gameObject);
  183. }
  184. }
  185. }
  186. }
  187. #endif