TouchPointer.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  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. public static bool isJinJuli;
  95. protected override void DoTargetDetect() {
  96. Debug.Log("DoTargetDetect33333===");
  97. if (newClosestTouchable == null)
  98. return;
  99. SCInputModule.Instance.ProcessCS(scPointEventData, transform, LayerMask, TouchDetectRadius * 2);
  100. IsFocusLocked = currentPokeDownObject != null;
  101. isJinJuli = IsFocusLocked;
  102. //Debug.Log(scPointEventData.pointerCurrentRaycast.gameObject);
  103. if (scPointEventData.pointerCurrentRaycast.gameObject) {
  104. DistToTouchable = Vector3.Distance(transform.position, scPointEventData.pointerCurrentRaycast.worldPosition) - TouchDetectRadius;
  105. bool newIsDown = (DistToTouchable < 0.0f);
  106. bool newIsUp = (DistToTouchable > newClosestTouchable.DebounceThreshold);
  107. if(newIsDown && currentPokeDownObject == null) {
  108. if(IsObjectPartOfTouchable(scPointEventData.pointerCurrentRaycast.gameObject, newClosestTouchable)) {
  109. currentPokeDownObject = scPointEventData.pointerCurrentRaycast.gameObject;
  110. currentTouchableObject = newClosestTouchable;
  111. PokeDown(currentTouchableObject);
  112. }
  113. } else if(currentPokeDownObject) {
  114. if(newIsUp) {
  115. PokeUp(currentTouchableObject);
  116. currentPokeDownObject = null ;
  117. currentTouchableObject = null;
  118. } else {
  119. PokeUpdated(currentTouchableObject);
  120. }
  121. }
  122. } else {
  123. if(currentPokeDownObject) {
  124. PokeUp(currentTouchableObject);
  125. currentPokeDownObject = null;
  126. currentTouchableObject = null;
  127. }
  128. }
  129. PreviousTouchPosition = ToucherPosition;
  130. }
  131. private void PokeDown(BaseNearInteractionTouchable touchableObj) {
  132. if (touchableObj.EventsToReceive == TouchableEventType.Auto) {
  133. handDetector.inputDevicePartBase.inputDataBase.inputKeys.InputDataAddKey(InputKeyCode.Enter, InputKeyState.DOWN);
  134. HandDispatcher.OnPokeDown(touchableObj.gameObject, this, scPointEventData);
  135. } else if(touchableObj.EventsToReceive == TouchableEventType.Pointer) {
  136. handDetector.inputDevicePartBase.inputDataBase.inputKeys.InputDataAddKey(InputKeyCode.Enter, InputKeyState.DOWN);
  137. } else if(touchableObj.EventsToReceive == TouchableEventType.Touch) {
  138. HandDispatcher.OnPokeDown(touchableObj.gameObject, this, scPointEventData);
  139. }
  140. }
  141. private void PokeUp(BaseNearInteractionTouchable touchableObj) {
  142. if (touchableObj.EventsToReceive == TouchableEventType.Auto) {
  143. handDetector.inputDevicePartBase.inputDataBase.inputKeys.InputDataAddKey(InputKeyCode.Enter, InputKeyState.UP);
  144. HandDispatcher.OnPokeUp(touchableObj.gameObject, this, scPointEventData);
  145. } else if (touchableObj.EventsToReceive == TouchableEventType.Pointer) {
  146. handDetector.inputDevicePartBase.inputDataBase.inputKeys.InputDataAddKey(InputKeyCode.Enter, InputKeyState.UP);
  147. } else if(touchableObj.EventsToReceive == TouchableEventType.Touch) {
  148. HandDispatcher.OnPokeUp(touchableObj.gameObject, this, scPointEventData);
  149. }
  150. }
  151. private void PokeUpdated(BaseNearInteractionTouchable touchableObj) {
  152. if (touchableObj.EventsToReceive == TouchableEventType.Auto) {
  153. HandDispatcher.OnPokeUpdated(touchableObj.gameObject, this, scPointEventData);
  154. } else if (touchableObj.EventsToReceive == TouchableEventType.Pointer) {
  155. } else if(touchableObj.EventsToReceive == TouchableEventType.Touch) {
  156. HandDispatcher.OnPokeUpdated(touchableObj.gameObject, this, scPointEventData);
  157. }
  158. }
  159. private static bool IsObjectPartOfTouchable(GameObject targetObject, BaseNearInteractionTouchable touchable) {
  160. return targetObject != null && touchable != null &&
  161. (targetObject == touchable.gameObject ||
  162. // Descendant game objects are touchable as well. In particular, this is needed to be able to send
  163. // touch events to Unity UI control elements.
  164. (targetObject.transform != null && touchable.gameObject.transform != null &&
  165. targetObject.transform.IsChildOf(touchable.gameObject.transform)));
  166. }
  167. public bool FindClosestTouchableForLayerMask() {
  168. isTouchableDetect = false;
  169. newClosestTouchable = null;
  170. closestDistance = float.PositiveInfinity;
  171. closestNormal = Vector3.zero;
  172. Array.Clear(queryBuffer,0, queryBuffer.Length);
  173. int numColliders = Physics.OverlapSphereNonAlloc(TouchDetectCenterPosition, TouchDetectRadius, queryBuffer, LayerMask);
  174. if(numColliders == queryBuffer.Length) {
  175. queryBuffer = bigqueryBuffer;
  176. Debug.LogWarning($"Maximum number of {numColliders} colliders found in TouchPointer overlap query. Consider increasing the query buffer size in the input system settings.");
  177. numColliders = Physics.OverlapSphereNonAlloc(TouchDetectCenterPosition, TouchDetectRadius, queryBuffer, LayerMask);
  178. }
  179. for(int i = 0; i < numColliders; i++) {
  180. var collider = queryBuffer[i];
  181. var touchable = collider.GetComponent<BaseNearInteractionTouchable>();
  182. if(touchable) {
  183. isTouchableDetect = true;
  184. float distance = touchable.DistanceToTouchable(ToucherPosition, out Vector3 normal);
  185. if(distance < closestDistance) {
  186. newClosestTouchable = touchable;
  187. closestDistance = distance;
  188. closestNormal = normal;
  189. }
  190. }
  191. }
  192. // Unity UI does not provide an equivalent broad-phase test to Physics.OverlapSphere,
  193. // so we have to use a static instances list to test all NearInteractionTouchableUnityUI
  194. for (int i = 0; i < NearInteractionTouchableUnityUI.Instances.Count; i++) {
  195. NearInteractionTouchableUnityUI touchable = NearInteractionTouchableUnityUI.Instances[i];
  196. float distance = touchable.DistanceToTouchable(ToucherPosition, out Vector3 normal);
  197. if (distance <= TouchDetectRadius && distance < closestDistance) {
  198. isTouchableDetect = true;
  199. newClosestTouchable = touchable;
  200. closestDistance = distance;
  201. closestNormal = normal;
  202. }
  203. }
  204. //return newClosestTouchable != null;
  205. return isTouchableDetect;
  206. }
  207. public bool TryGetNearGraspPoint(out Vector3 position) {
  208. position = Vector3.zero;
  209. return false;
  210. }
  211. public bool TryGetNearGraspAxis(out Vector3 axis) {
  212. axis = transform.forward;
  213. return true;
  214. }
  215. public bool TryGetDistanceToNearestSurface(out float distance) {
  216. distance = closestDistance;
  217. return true;
  218. }
  219. public bool TryGetNormalToNearestSurface(out Vector3 normal) {
  220. normal = closestNormal;
  221. return true;
  222. }
  223. void OnDrawGizmos() {
  224. if(Application.isPlaying) {
  225. Gizmos.color = Color.black*0.2f;
  226. Gizmos.DrawSphere(transform.position, 0.01f);
  227. Gizmos.color = Color.black * 0.1f;
  228. Gizmos.DrawSphere(TouchDetectCenterPosition, TouchDetectRadius);
  229. Gizmos.color = Color.blue * 0.3f;
  230. Gizmos.DrawSphere(start, 0.02f);
  231. Gizmos.color = Color.blue * 0.2f;
  232. Gizmos.DrawSphere(end, 0.01f);
  233. }
  234. }
  235. }
  236. }