CursorVisual.cs 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. using System;
  2. using Rokid.UXR.Utility;
  3. using UnityEngine;
  4. using UnityEngine.EventSystems;
  5. namespace Rokid.UXR.Interaction
  6. {
  7. public class CursorVisual : AutoInjectBehaviour
  8. {
  9. [SerializeField]
  10. private HandType hand;
  11. [SerializeField]
  12. private RayInteractor rayInteractor;
  13. [Tooltip("光标Size")]
  14. [SerializeField]
  15. private float cursorAngularSize = 100;
  16. [Autowrited("Cursor_Focus")]
  17. private Transform focusCursor;
  18. [Autowrited("Cursor_Press")]
  19. private Transform pressCursor;
  20. private bool dragging;
  21. private IBezierCurveDrag[] allCanDragObjs;
  22. private IBezierCurveDrag currentDragObj;
  23. private float scaleRelease = 1.5f;
  24. private float scalePress = 1.0f;
  25. private float startSmoothPinchDistance = 0.06f;
  26. private void Start()
  27. {
  28. InteractorStateChange.OnHandDragStatusChanged += OnHandDragStatusChanged;
  29. RKPointerLisener.OnPointerDragBegin += OnPointerDragBegin;
  30. RKPointerLisener.OnPointerDragEnd += OnPointerDragEnd;
  31. }
  32. private void OnHandDragStatusChanged(HandType hand, bool dragging)
  33. {
  34. if (hand == this.hand)
  35. {
  36. if (dragging)
  37. {
  38. this.dragging = true;
  39. if (rayInteractor.Interactable != null)
  40. {
  41. allCanDragObjs = rayInteractor.Interactable.GetComponentsInChildren<IBezierCurveDrag>();
  42. currentDragObj = GetCurrentDragObj();
  43. }
  44. }
  45. else
  46. {
  47. this.dragging = false;
  48. currentDragObj = null;
  49. allCanDragObjs = null;
  50. }
  51. }
  52. }
  53. private void OnDestroy()
  54. {
  55. InteractorStateChange.OnHandDragStatusChanged -= OnHandDragStatusChanged;
  56. RKPointerLisener.OnPointerDragBegin -= OnPointerDragBegin;
  57. RKPointerLisener.OnPointerDragEnd -= OnPointerDragEnd;
  58. }
  59. private void OnEnable()
  60. {
  61. rayInteractor.WhenPostprocessed += UpdateVisual;
  62. rayInteractor.WhenStateChanged += UpdateVisualState;
  63. RKPointerLisener.OnGraphicPointerEnter += OnPointerEnter;
  64. RKPointerLisener.OnGraphicPointerExit += OnPointerExit;
  65. RKPointerLisener.OnGraphicPointerHover += OnPointerHover;
  66. }
  67. private void OnDisable()
  68. {
  69. rayInteractor.WhenPostprocessed -= UpdateVisual;
  70. rayInteractor.WhenStateChanged -= UpdateVisualState;
  71. RKPointerLisener.OnGraphicPointerEnter -= OnPointerEnter;
  72. RKPointerLisener.OnGraphicPointerExit -= OnPointerExit;
  73. RKPointerLisener.OnGraphicPointerHover -= OnPointerHover;
  74. isInHover = false;
  75. }
  76. private void OnPointerDragEnd(PointerEventData eventData)
  77. {
  78. if (hand == HandType.None)
  79. {
  80. RKLog.Info("====CursorVisual====: OnPointerDragEnd");
  81. dragging = false;
  82. currentDragObj = null;
  83. allCanDragObjs = null;
  84. }
  85. }
  86. private void OnPointerDragBegin(PointerEventData eventData)
  87. {
  88. if (hand == HandType.None)
  89. {
  90. dragging = true;
  91. if (rayInteractor.Interactable != null)
  92. {
  93. allCanDragObjs = rayInteractor.Interactable.GetComponentsInChildren<IBezierCurveDrag>();
  94. currentDragObj = GetCurrentDragObj();
  95. }
  96. }
  97. }
  98. private bool HandDragging(GestureType GesType)
  99. {
  100. if (dragging && hand != HandType.None)
  101. {
  102. if (GesEventInput.Instance.GetGestureType(hand) == GesType)
  103. {
  104. return true;
  105. }
  106. }
  107. return false;
  108. }
  109. private IBezierCurveDrag GetCurrentDragObj()
  110. {
  111. if (allCanDragObjs == null || allCanDragObjs.Length == 0)
  112. {
  113. return null;
  114. }
  115. foreach (var dragObj in allCanDragObjs)
  116. {
  117. if (dragObj.IsInBezierCurveDragging())
  118. {
  119. return dragObj;
  120. }
  121. }
  122. return null;
  123. }
  124. private bool IsBezierDragging()
  125. {
  126. if (currentDragObj == null)
  127. {
  128. currentDragObj = GetCurrentDragObj();
  129. }
  130. if (dragging && currentDragObj != null)
  131. {
  132. return true;
  133. }
  134. return false;
  135. }
  136. private Vector3 ComputeScaleWithAngularScale(Vector3 targetPoint)
  137. {
  138. if (MainCameraCache.mainCamera != null)
  139. {
  140. float cursorDistance = Vector3.Distance(MainCameraCache.mainCamera.transform.position, targetPoint);
  141. float desiredScale = Utils.ScaleFromAngularSizeAndDistance(cursorAngularSize, cursorDistance);
  142. return Vector3.one * desiredScale;
  143. }
  144. return Vector3.zero;
  145. }
  146. private void UpdateVisual()
  147. {
  148. if (rayInteractor.CollisionInfo == null || rayInteractor.State == InteractorState.Disabled || IsBezierDragging())
  149. {
  150. focusCursor.gameObject.SetActive(false);
  151. pressCursor.gameObject.SetActive(false);
  152. return;
  153. }
  154. if (isInHover && hoverNormal != Vector3.zero && hoverPosition != Vector3.zero)
  155. {
  156. this.transform.position = hoverPosition;
  157. this.transform.rotation = Quaternion.LookRotation(hoverNormal, Vector3.up);
  158. this.transform.localScale = ComputeScaleWithAngularScale(hoverPosition);
  159. }
  160. else
  161. {
  162. Vector3 collisionNormal = IsBezierDragging() ? currentDragObj.GetBezierCurveEndNormal() : rayInteractor.CollisionInfo.Value.Normal;
  163. Vector3 collisionPosition = IsBezierDragging() ? currentDragObj.GetBezierCurveEndPoint() : rayInteractor.End;
  164. this.transform.position = collisionPosition + collisionNormal * 0.001f;
  165. this.transform.rotation = Quaternion.LookRotation(collisionNormal, Vector3.up);
  166. this.transform.localScale = ComputeScaleWithAngularScale(collisionPosition);
  167. }
  168. bool press = rayInteractor.State == InteractorState.Select || IsBezierDragging();
  169. focusCursor.gameObject.SetActive(!press);
  170. pressCursor.gameObject.SetActive(press);
  171. if (hand != HandType.None)
  172. {
  173. if (!press)
  174. {
  175. Vector3 index_tip = GesEventInput.Instance.GetSkeletonPose(SkeletonIndexFlag.INDEX_FINGER_TIP, hand).position;
  176. Vector3 thumb_tip = GesEventInput.Instance.GetSkeletonPose(SkeletonIndexFlag.THUMB_TIP, hand).position;
  177. float sqrDistance = Vector3.SqrMagnitude(index_tip - thumb_tip);
  178. if (sqrDistance > startSmoothPinchDistance * startSmoothPinchDistance)
  179. {
  180. this.transform.localScale *= scaleRelease;
  181. }
  182. else
  183. {
  184. float pow = Mathf.Max(scalePress, scaleRelease * (sqrDistance / (startSmoothPinchDistance * startSmoothPinchDistance)));
  185. this.transform.localScale *= pow;
  186. }
  187. }
  188. else
  189. {
  190. this.transform.localScale *= scalePress;
  191. }
  192. }
  193. }
  194. public void UpdateCursorVisual(Transform forcusCursor, Transform pressCursor)
  195. {
  196. Destroy(this.focusCursor);
  197. Destroy(this.pressCursor);
  198. this.focusCursor = forcusCursor;
  199. this.pressCursor = pressCursor;
  200. this.focusCursor.SetParent(this.transform);
  201. this.pressCursor.SetParent(this.transform);
  202. this.focusCursor.localPosition = Vector3.zero;
  203. this.pressCursor.localPosition = Vector3.zero;
  204. }
  205. private void UpdateVisualState(InteractorStateChangeArgs args) => UpdateVisual();
  206. #region ForCursorHoverPose
  207. private bool isInHover;
  208. private Vector3 hoverPosition;
  209. private Vector3 hoverNormal;
  210. private void OnPointerEnter(PointerEventData eventData)
  211. {
  212. if (RayInteractor.GetHandTypeByIdentifier(eventData.pointerId) == hand && eventData.pointerCurrentRaycast.gameObject != null)
  213. {
  214. isInHover = true;
  215. hoverPosition = Vector3.zero;
  216. hoverNormal = Vector3.zero;
  217. }
  218. }
  219. private void OnPointerExit(PointerEventData eventData)
  220. {
  221. if (RayInteractor.GetHandTypeByIdentifier(eventData.pointerId) == hand)
  222. {
  223. isInHover = false;
  224. hoverPosition = Vector3.zero;
  225. hoverNormal = Vector3.zero;
  226. }
  227. }
  228. private void OnPointerHover(PointerEventData eventData)
  229. {
  230. if (isInHover && RayInteractor.GetHandTypeByIdentifier(eventData.pointerId) == hand)
  231. {
  232. hoverPosition = eventData.pointerCurrentRaycast.worldPosition;
  233. hoverNormal = eventData.pointerCurrentRaycast.worldNormal;
  234. }
  235. }
  236. #endregion
  237. }
  238. }