TouchPointer.cs 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using UnityEngine;
  7. using UnityEngine.EventSystems;
  8. namespace SC.XR.Unity.Module_InputSystem.InputDeviceHand {
  9. public class TouchPointer : PointerBase, INearPointer
  10. {
  11. public HandDetector handDetector {
  12. get {
  13. return detectorBase as HandDetector;
  14. }
  15. }
  16. public float TouchRadius { get => 0.2f; }
  17. public bool IsNearObject { get => newClosestTouchable!=null; }
  18. public override PointerType PointerType => PointerType.Touch;
  19. private Collider[] queryBuffer=new Collider[60];
  20. public Action<bool> TargetDetectModelChange;
  21. SCPointEventData scPointEventData {
  22. get {
  23. return handDetector.inputDevicePartBase.inputDataBase.SCPointEventData;
  24. }
  25. }
  26. private Vector3 mPreviousTouchPosition;
  27. public Vector3 PreviousTouchPosition {
  28. get {
  29. if(mPreviousTouchPosition == Vector3.zero) {
  30. mPreviousTouchPosition = TouchPosition;
  31. }
  32. return mPreviousTouchPosition;
  33. }
  34. private set {
  35. mPreviousTouchPosition = value;
  36. }
  37. }
  38. public Vector3 TouchPosition {
  39. get {
  40. //return gT26DofDetector.inputDeviceGT26DofPart.inputDeviceGT26DofPartUI.modelGT26Dof.TouchCursor.transform.position;
  41. return handDetector.inputDeviceHandPart.inputDeviceHandPartUI.modelHand.ActiveHandModel.GetJointTransform(FINGER.forefinger, JOINT.One).transform.position;
  42. }
  43. }
  44. public float DistToTouchable {
  45. get;
  46. private set;
  47. }
  48. float closestDistance;
  49. Vector3 closestNormal;
  50. BaseNearInteractionTouchable newClosestTouchable;
  51. Vector3 start, end;
  52. public override void OnSCStart() {
  53. //base.OnSCStart();
  54. cursorBase?.ModuleStart();
  55. }
  56. public override void OnSCDisable() {
  57. base.OnSCDisable();
  58. if(currentPokeDownObject) {
  59. PokeUp(ref currentPokeDownObject, ref currentTouchableObject);
  60. }
  61. IsFocusLocked = false;
  62. PreviousTouchPosition = Vector3.zero;
  63. }
  64. protected override void UpdateTransform() {
  65. start = TouchPosition + TouchRadius * closestNormal;
  66. end = TouchPosition - TouchRadius * closestNormal;
  67. transform.rotation = Quaternion.LookRotation(end - start);
  68. transform.position = start;
  69. }
  70. private GameObject currentPokeDownObject = null;
  71. private BaseNearInteractionTouchable currentTouchableObject = null;
  72. protected override void DoTargetDetect() {
  73. SCInputModule.Instance.ProcessCS(scPointEventData, transform, LayerMask, (end - start).magnitude);
  74. IsFocusLocked = currentPokeDownObject != null;
  75. //Debug.Log(scPointEventData.pointerCurrentRaycast.gameObject);
  76. if(scPointEventData.pointerCurrentRaycast.gameObject) {
  77. DistToTouchable = Vector3.Distance(transform.position, scPointEventData.pointerCurrentRaycast.worldPosition) - TouchRadius;
  78. bool newIsDown = (DistToTouchable < 0.0f);
  79. bool newIsUp = (DistToTouchable > newClosestTouchable.DebounceThreshold);
  80. if(newIsDown && currentPokeDownObject == null) {
  81. if(IsObjectPartOfTouchable(scPointEventData.pointerCurrentRaycast.gameObject, newClosestTouchable)) {
  82. currentPokeDownObject = scPointEventData.pointerCurrentRaycast.gameObject;
  83. currentTouchableObject = newClosestTouchable;
  84. PokeDown(currentPokeDownObject, currentTouchableObject);
  85. }
  86. } else if(currentPokeDownObject) {
  87. if(newIsUp) {
  88. PokeUp(ref currentPokeDownObject, ref currentTouchableObject);
  89. } else {
  90. PokeUpdated(currentPokeDownObject, currentTouchableObject);
  91. }
  92. }
  93. } else {
  94. if(currentPokeDownObject) {
  95. PokeUp(ref currentPokeDownObject, ref currentTouchableObject);
  96. }
  97. }
  98. PreviousTouchPosition = TouchPosition;
  99. }
  100. private void PokeDown(GameObject _target, BaseNearInteractionTouchable touchableObj) {
  101. if(touchableObj.EventsToReceive == TouchableEventType.Pointer) {
  102. handDetector.inputDevicePartBase.inputDataBase.inputKeys.InputDataAddKey(InputKeyCode.Enter, InputKeyState.DOWN);
  103. } else if(touchableObj.EventsToReceive == TouchableEventType.Touch) {
  104. HandDispatcher.OnPokeDown(touchableObj.gameObject, this, scPointEventData);
  105. }
  106. }
  107. private void PokeUp(ref GameObject _target, ref BaseNearInteractionTouchable touchableObj) {
  108. if(touchableObj.EventsToReceive == TouchableEventType.Pointer) {
  109. handDetector.inputDevicePartBase.inputDataBase.inputKeys.InputDataAddKey(InputKeyCode.Enter, InputKeyState.UP);
  110. } else if(touchableObj.EventsToReceive == TouchableEventType.Touch) {
  111. HandDispatcher.OnPokeUp(touchableObj.gameObject, this, scPointEventData);
  112. }
  113. touchableObj = null;
  114. _target = null;
  115. }
  116. private void PokeUpdated(GameObject _target, BaseNearInteractionTouchable touchableObj) {
  117. if(touchableObj.EventsToReceive == TouchableEventType.Pointer) {
  118. } else if(touchableObj.EventsToReceive == TouchableEventType.Touch) {
  119. HandDispatcher.OnPokeUpdated(touchableObj.gameObject, this, scPointEventData);
  120. }
  121. }
  122. private static bool IsObjectPartOfTouchable(GameObject targetObject, BaseNearInteractionTouchable touchable) {
  123. return targetObject != null && touchable != null &&
  124. (targetObject == touchable.gameObject ||
  125. // Descendant game objects are touchable as well. In particular, this is needed to be able to send
  126. // touch events to Unity UI control elements.
  127. (targetObject.transform != null && touchable.gameObject.transform != null &&
  128. targetObject.transform.IsChildOf(touchable.gameObject.transform)));
  129. }
  130. public bool FindClosestTouchableForLayerMask() {
  131. newClosestTouchable = null;
  132. closestDistance = float.PositiveInfinity;
  133. closestNormal = Vector3.zero;
  134. int numColliders = Physics.OverlapSphereNonAlloc(TouchPosition, TouchRadius, queryBuffer, LayerMask);
  135. if(numColliders == queryBuffer.Length) {
  136. Debug.LogWarning($"Maximum number of {numColliders} colliders found in PokePointer overlap query. Consider increasing the query buffer size in the input system settings.");
  137. }
  138. for(int i = 0; i < numColliders; i++) {
  139. var collider = queryBuffer[i];
  140. var touchable = collider.GetComponent<BaseNearInteractionTouchable>();
  141. if(touchable) {
  142. float distance = touchable.DistanceToTouchable(TouchPosition, out Vector3 normal);
  143. if(distance < closestDistance) {
  144. newClosestTouchable = touchable;
  145. closestDistance = distance;
  146. closestNormal = normal;
  147. }
  148. }
  149. }
  150. // Unity UI does not provide an equivalent broad-phase test to Physics.OverlapSphere,
  151. // so we have to use a static instances list to test all NearInteractionTouchableUnityUI
  152. for(int i = 0; i < NearInteractionTouchableUnityUI.Instances.Count; i++) {
  153. NearInteractionTouchableUnityUI touchable = NearInteractionTouchableUnityUI.Instances[i];
  154. float distance = touchable.DistanceToTouchable(TouchPosition, out Vector3 normal);
  155. if(distance <= TouchRadius && distance < closestDistance) {
  156. newClosestTouchable = touchable;
  157. closestDistance = distance;
  158. closestNormal = normal;
  159. }
  160. }
  161. //if(newClosestTouchable != null) {
  162. // Debug.Log("newClosestTouchable:" + newClosestTouchable.name);
  163. //}
  164. return newClosestTouchable != null;
  165. }
  166. public bool TryGetNearGraspPoint(out Vector3 position) {
  167. position = Vector3.zero;
  168. return false;
  169. }
  170. public bool TryGetNearGraspAxis(out Vector3 axis) {
  171. axis = transform.forward;
  172. return true;
  173. }
  174. public bool TryGetDistanceToNearestSurface(out float distance) {
  175. distance = closestDistance;
  176. return true;
  177. }
  178. public bool TryGetNormalToNearestSurface(out Vector3 normal) {
  179. normal = closestNormal;
  180. return true;
  181. }
  182. void OnDrawGizmos() {
  183. if(Application.isPlaying) {
  184. Gizmos.color = Color.black*0.2f;
  185. Gizmos.DrawSphere(transform.position, 0.01f);
  186. Gizmos.color = Color.black * 0.1f;
  187. Gizmos.DrawSphere(TouchPosition, TouchRadius);
  188. Gizmos.color = Color.blue * 0.3f;
  189. Gizmos.DrawSphere(start, 0.02f);
  190. Gizmos.color = Color.blue * 0.2f;
  191. Gizmos.DrawSphere(end, 0.01f);
  192. }
  193. }
  194. }
  195. }