TouchPointer.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  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 TouchDetectRadius { get => 0.1f; }
  17. public bool IsNearObject { get => newClosestTouchable!=null; }
  18. public override PointerType PointerType => PointerType.Touch;
  19. private Collider[] queryBuffer;
  20. private Collider[] smallerqueryBuffer = new Collider[60];
  21. private Collider[] bigqueryBuffer = new Collider[180];
  22. private bool isTouchableDetect = false;
  23. public Action<bool> TargetDetectModelChange;
  24. SCPointEventData scPointEventData {
  25. get {
  26. return handDetector.inputDevicePartBase.inputDataBase.SCPointEventData;
  27. }
  28. }
  29. private Vector3 mPreviousTouchPosition;
  30. public Vector3 PreviousTouchPosition {
  31. get {
  32. if(mPreviousTouchPosition == Vector3.zero) {
  33. mPreviousTouchPosition = ToucherPosition;
  34. }
  35. return mPreviousTouchPosition;
  36. }
  37. private set {
  38. mPreviousTouchPosition = value;
  39. }
  40. }
  41. private Vector3 mToucherPosition;
  42. public Vector3 ToucherPosition {
  43. get {
  44. return mToucherPosition = Vector3.Lerp(mToucherPosition, handDetector.inputDeviceHandPart.inputDeviceHandPartUI.modelHand.ActiveHandModel.GetJointTransform(FINGER.forefinger, JOINT.One).transform.position,0.5f);
  45. //return gT26DofDetector.inputDeviceGT26DofPart.inputDeviceGT26DofPartUI.modelGT26Dof.TouchCursor.transform.position;
  46. }
  47. }
  48. public Vector3 mTouchDetectCenterPosition;
  49. public Vector3 TouchDetectCenterPosition {
  50. get {
  51. return mTouchDetectCenterPosition = Vector3.Lerp(mTouchDetectCenterPosition, handDetector.inputDeviceHandPart.inputDataHand.handInfo.MainTouchDetectCenterPosition, 0.5f);
  52. }
  53. }
  54. public float DistToTouchable {
  55. get;
  56. private set;
  57. }
  58. float closestDistance;
  59. Vector3 closestNormal;
  60. BaseNearInteractionTouchable newClosestTouchable;
  61. Vector3 start, end;
  62. public override void OnSCAwake() {
  63. base.OnSCAwake();
  64. queryBuffer = smallerqueryBuffer;
  65. }
  66. public override void OnSCStart() {
  67. base.OnSCStart();
  68. queryBuffer = smallerqueryBuffer;
  69. lineBase?.ModuleStop();
  70. }
  71. public override void OnSCDisable() {
  72. base.OnSCDisable();
  73. if(currentPokeDownObject) {
  74. PokeUp(currentTouchableObject);
  75. }
  76. currentPokeDownObject = null;
  77. currentTouchableObject = null;
  78. IsFocusLocked = false;
  79. PreviousTouchPosition = Vector3.zero;
  80. }
  81. protected override void UpdateTransform() {
  82. if (newClosestTouchable) {
  83. start = ToucherPosition + TouchDetectRadius * closestNormal;
  84. end = ToucherPosition - TouchDetectRadius * closestNormal;
  85. transform.rotation = Quaternion.LookRotation(end - start);
  86. transform.position = start;
  87. } else {
  88. transform.rotation = Quaternion.identity;
  89. transform.position = Vector3.zero;
  90. }
  91. }
  92. private GameObject currentPokeDownObject = null;
  93. private BaseNearInteractionTouchable currentTouchableObject = null;
  94. protected override void DoTargetDetect() {
  95. Debug.Log("DoTargetDetect33333===");
  96. if (newClosestTouchable == null)
  97. return;
  98. SCInputModule.Instance.ProcessCS(scPointEventData, transform, LayerMask, TouchDetectRadius * 2);
  99. IsFocusLocked = currentPokeDownObject != null;
  100. //Debug.Log(scPointEventData.pointerCurrentRaycast.gameObject);
  101. if(scPointEventData.pointerCurrentRaycast.gameObject) {
  102. DistToTouchable = Vector3.Distance(transform.position, scPointEventData.pointerCurrentRaycast.worldPosition) - TouchDetectRadius;
  103. bool newIsDown = (DistToTouchable < 0.0f);
  104. bool newIsUp = (DistToTouchable > newClosestTouchable.DebounceThreshold);
  105. if(newIsDown && currentPokeDownObject == null) {
  106. if(IsObjectPartOfTouchable(scPointEventData.pointerCurrentRaycast.gameObject, newClosestTouchable)) {
  107. currentPokeDownObject = scPointEventData.pointerCurrentRaycast.gameObject;
  108. currentTouchableObject = newClosestTouchable;
  109. PokeDown(currentTouchableObject);
  110. }
  111. } else if(currentPokeDownObject) {
  112. if(newIsUp) {
  113. PokeUp(currentTouchableObject);
  114. currentPokeDownObject = null ;
  115. currentTouchableObject = null;
  116. } else {
  117. PokeUpdated(currentTouchableObject);
  118. }
  119. }
  120. } else {
  121. if(currentPokeDownObject) {
  122. PokeUp(currentTouchableObject);
  123. currentPokeDownObject = null;
  124. currentTouchableObject = null;
  125. }
  126. }
  127. PreviousTouchPosition = ToucherPosition;
  128. }
  129. private void PokeDown(BaseNearInteractionTouchable touchableObj) {
  130. if (touchableObj.EventsToReceive == TouchableEventType.Auto) {
  131. handDetector.inputDevicePartBase.inputDataBase.inputKeys.InputDataAddKey(InputKeyCode.Enter, InputKeyState.DOWN);
  132. HandDispatcher.OnPokeDown(touchableObj.gameObject, this, scPointEventData);
  133. } else if(touchableObj.EventsToReceive == TouchableEventType.Pointer) {
  134. handDetector.inputDevicePartBase.inputDataBase.inputKeys.InputDataAddKey(InputKeyCode.Enter, InputKeyState.DOWN);
  135. } else if(touchableObj.EventsToReceive == TouchableEventType.Touch) {
  136. HandDispatcher.OnPokeDown(touchableObj.gameObject, this, scPointEventData);
  137. }
  138. }
  139. private void PokeUp(BaseNearInteractionTouchable touchableObj) {
  140. if (touchableObj.EventsToReceive == TouchableEventType.Auto) {
  141. handDetector.inputDevicePartBase.inputDataBase.inputKeys.InputDataAddKey(InputKeyCode.Enter, InputKeyState.UP);
  142. HandDispatcher.OnPokeUp(touchableObj.gameObject, this, scPointEventData);
  143. } else if (touchableObj.EventsToReceive == TouchableEventType.Pointer) {
  144. handDetector.inputDevicePartBase.inputDataBase.inputKeys.InputDataAddKey(InputKeyCode.Enter, InputKeyState.UP);
  145. } else if(touchableObj.EventsToReceive == TouchableEventType.Touch) {
  146. HandDispatcher.OnPokeUp(touchableObj.gameObject, this, scPointEventData);
  147. }
  148. }
  149. private void PokeUpdated(BaseNearInteractionTouchable touchableObj) {
  150. if (touchableObj.EventsToReceive == TouchableEventType.Auto) {
  151. HandDispatcher.OnPokeUpdated(touchableObj.gameObject, this, scPointEventData);
  152. } else if (touchableObj.EventsToReceive == TouchableEventType.Pointer) {
  153. } else if(touchableObj.EventsToReceive == TouchableEventType.Touch) {
  154. HandDispatcher.OnPokeUpdated(touchableObj.gameObject, this, scPointEventData);
  155. }
  156. }
  157. private static bool IsObjectPartOfTouchable(GameObject targetObject, BaseNearInteractionTouchable touchable) {
  158. return targetObject != null && touchable != null &&
  159. (targetObject == touchable.gameObject ||
  160. // Descendant game objects are touchable as well. In particular, this is needed to be able to send
  161. // touch events to Unity UI control elements.
  162. (targetObject.transform != null && touchable.gameObject.transform != null &&
  163. targetObject.transform.IsChildOf(touchable.gameObject.transform)));
  164. }
  165. public bool FindClosestTouchableForLayerMask() {
  166. isTouchableDetect = false;
  167. newClosestTouchable = null;
  168. closestDistance = float.PositiveInfinity;
  169. closestNormal = Vector3.zero;
  170. Array.Clear(queryBuffer,0, queryBuffer.Length);
  171. int numColliders = Physics.OverlapSphereNonAlloc(TouchDetectCenterPosition, TouchDetectRadius, queryBuffer, LayerMask);
  172. if(numColliders == queryBuffer.Length) {
  173. queryBuffer = bigqueryBuffer;
  174. Debug.LogWarning($"Maximum number of {numColliders} colliders found in TouchPointer overlap query. Consider increasing the query buffer size in the input system settings.");
  175. numColliders = Physics.OverlapSphereNonAlloc(TouchDetectCenterPosition, TouchDetectRadius, queryBuffer, LayerMask);
  176. }
  177. for(int i = 0; i < numColliders; i++) {
  178. var collider = queryBuffer[i];
  179. var touchable = collider.GetComponent<BaseNearInteractionTouchable>();
  180. if(touchable) {
  181. isTouchableDetect = true;
  182. float distance = touchable.DistanceToTouchable(ToucherPosition, out Vector3 normal);
  183. if(distance < closestDistance) {
  184. newClosestTouchable = touchable;
  185. closestDistance = distance;
  186. closestNormal = normal;
  187. }
  188. }
  189. }
  190. // Unity UI does not provide an equivalent broad-phase test to Physics.OverlapSphere,
  191. // so we have to use a static instances list to test all NearInteractionTouchableUnityUI
  192. for (int i = 0; i < NearInteractionTouchableUnityUI.Instances.Count; i++) {
  193. NearInteractionTouchableUnityUI touchable = NearInteractionTouchableUnityUI.Instances[i];
  194. float distance = touchable.DistanceToTouchable(ToucherPosition, out Vector3 normal);
  195. if (distance <= TouchDetectRadius && distance < closestDistance) {
  196. isTouchableDetect = true;
  197. newClosestTouchable = touchable;
  198. closestDistance = distance;
  199. closestNormal = normal;
  200. }
  201. }
  202. //return newClosestTouchable != null;
  203. return isTouchableDetect;
  204. }
  205. public bool TryGetNearGraspPoint(out Vector3 position) {
  206. position = Vector3.zero;
  207. return false;
  208. }
  209. public bool TryGetNearGraspAxis(out Vector3 axis) {
  210. axis = transform.forward;
  211. return true;
  212. }
  213. public bool TryGetDistanceToNearestSurface(out float distance) {
  214. distance = closestDistance;
  215. return true;
  216. }
  217. public bool TryGetNormalToNearestSurface(out Vector3 normal) {
  218. normal = closestNormal;
  219. return true;
  220. }
  221. void OnDrawGizmos() {
  222. if(Application.isPlaying) {
  223. Gizmos.color = Color.black*0.2f;
  224. Gizmos.DrawSphere(transform.position, 0.01f);
  225. Gizmos.color = Color.black * 0.1f;
  226. Gizmos.DrawSphere(TouchDetectCenterPosition, TouchDetectRadius);
  227. Gizmos.color = Color.blue * 0.3f;
  228. Gizmos.DrawSphere(start, 0.02f);
  229. Gizmos.color = Color.blue * 0.2f;
  230. Gizmos.DrawSphere(end, 0.01f);
  231. }
  232. }
  233. }
  234. }