SCInputModule.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  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 {
  9. public class SCInputModule : StandaloneInputModule {
  10. public static SCInputModule Instance { get; private set; }
  11. private Camera mRayCasterCamera;
  12. public Camera RayCasterCamera {
  13. get {
  14. if(mRayCasterCamera == null) {
  15. mRayCasterCamera = EnsureUIEventCamera();
  16. }
  17. return mRayCasterCamera;
  18. }
  19. }
  20. private PhysicsRaycaster mPhysicsRaycaster;
  21. public PhysicsRaycaster PhysicsRaycaster {
  22. get {
  23. if(mPhysicsRaycaster == null) {
  24. mPhysicsRaycaster = EnsurePhysicsRaycaster();
  25. }
  26. return mPhysicsRaycaster;
  27. }
  28. }
  29. public LayerMask layerMask;
  30. public float maxDetectDistance=0;
  31. Vector3? lastMousePoint3d;
  32. Vector2 newPos, lastPosition;
  33. Vector3 viewportPos = new Vector3(0.5f, 0.5f, 1.0f);
  34. protected override void Start() {
  35. base.Start();
  36. if(Instance) {
  37. DestroyImmediate(this);
  38. return;
  39. }
  40. DontDestroyOnLoad(gameObject);
  41. Instance = this;
  42. }
  43. public override void Process() {
  44. }
  45. public virtual void ProcessCS(SCPointEventData scPointEventData, Transform posture, int layerMask = 1 << 8, float maxDetectDistance = 30,bool isSimlate=false, RaycastResult simlateResult=new RaycastResult()) {
  46. //if(!eventSystem.isFocused)
  47. // return;
  48. bool usedEvent = SendUpdateEventToSelectedObject();
  49. ProcessSCEventInit(scPointEventData, posture, layerMask, maxDetectDistance);
  50. ProcessSCEvent(scPointEventData, isSimlate, simlateResult);
  51. if(eventSystem.sendNavigationEvents) {
  52. if(!usedEvent)
  53. usedEvent |= SendMoveEventToSelectedObject();
  54. if(!usedEvent)
  55. SendSubmitEventToSelectedObject();
  56. }
  57. }
  58. void ProcessSCEventInit(SCPointEventData scPointEventData, Transform posture, int layerMask, float maxDetectDistance) {
  59. if(this.layerMask.value != 0) {
  60. layerMask = this.layerMask;
  61. }
  62. if(this.maxDetectDistance > 0) {
  63. maxDetectDistance = this.maxDetectDistance;
  64. }
  65. PhysicsRaycaster.eventMask = layerMask;
  66. RayCasterCamera.cullingMask = layerMask;
  67. RayCasterCamera.farClipPlane = maxDetectDistance;
  68. RayCasterCamera.transform.position = posture.position; // posture.position;// Vector3.Lerp(RayCasterCamera.transform.position, targetDetectBase.transform.position,0.3f); //targetDetectBase.transform.position;
  69. RayCasterCamera.transform.rotation = posture.rotation;
  70. ///Canvas分配wrold Camera
  71. foreach(var canvas in CanvasCollection.CanvasList) {
  72. canvas.worldCamera = RayCasterCamera;
  73. }
  74. newPos = SCInputModule.Instance.RayCasterCamera.ViewportToScreenPoint(viewportPos);
  75. // Populate initial data or drag data
  76. if(lastMousePoint3d == null) {
  77. // For the first event, use the same position for 'last' and 'new'.
  78. lastPosition = newPos;
  79. } else {
  80. // Otherwise, re-project the last pointer position.
  81. lastPosition = SCInputModule.Instance.RayCasterCamera.WorldToScreenPoint(lastMousePoint3d.Value);
  82. }
  83. // Save off the 3D position of the cursor.
  84. lastMousePoint3d = SCInputModule.Instance.RayCasterCamera.ViewportToWorldPoint(viewportPos);
  85. scPointEventData.delta = newPos - lastPosition;
  86. scPointEventData.position = newPos;
  87. if(RayCasterCamera != null && Application.platform != RuntimePlatform.Android) {
  88. Ray ray = new Ray();
  89. ray = RayCasterCamera.ScreenPointToRay(scPointEventData.position);
  90. Debug.DrawRay(ray.origin, ray.direction * maxDetectDistance, Color.blue);
  91. }
  92. }
  93. /// <summary>
  94. /// Process all mouse events.
  95. /// </summary>
  96. protected void ProcessSCEvent(SCPointEventData scPointEventData, bool isSimlate = false, RaycastResult simlateResult = new RaycastResult()) {
  97. scPointEventData.MouseButtonEventData.buttonData = scPointEventData;
  98. scPointEventData.MouseButtonEventData.buttonState = StateForMouseButton(scPointEventData.inputDevicePartBase);
  99. if(isSimlate) {
  100. scPointEventData.pointerCurrentRaycast = simlateResult;
  101. } else {
  102. eventSystem.RaycastAll(scPointEventData, m_RaycastResultCache);
  103. scPointEventData.pointerCurrentRaycast = FindFirstRaycast(m_RaycastResultCache);
  104. m_RaycastResultCache.Clear();
  105. }
  106. scPointEventData.Forward = RayCasterCamera.transform.forward;
  107. if(scPointEventData.MouseButtonEventData.PressedThisFrame() && scPointEventData.pointerCurrentRaycast.gameObject) {
  108. scPointEventData.HitPointerRelativeRayCasterCamera = RayCasterCamera.transform.InverseTransformPoint(scPointEventData.pointerCurrentRaycast.worldPosition);
  109. scPointEventData.Position3D = scPointEventData.PressPosition3D = RayCasterCamera.transform.TransformPoint(scPointEventData.HitPointerRelativeRayCasterCamera);
  110. scPointEventData.pressForward = RayCasterCamera.transform.forward;
  111. scPointEventData.DownPressGameObject = scPointEventData.pointerCurrentRaycast.gameObject;
  112. } else if(scPointEventData.MouseButtonEventData.ReleasedThisFrame()) {
  113. scPointEventData.HitPointerDeltaDragObjCenter = scPointEventData.HitPointerRelativeRayCasterCamera = scPointEventData.dragObjPosition = Vector3.zero;
  114. scPointEventData.Position3D = Vector3.zero;
  115. scPointEventData.PressPosition3D = Vector3.zero;
  116. scPointEventData.DownPressGameObject = null;
  117. scPointEventData.pressForward = Vector3.zero;
  118. }
  119. if(scPointEventData.DownPressGameObject) {
  120. scPointEventData.Position3D = RayCasterCamera.transform.TransformPoint(scPointEventData.HitPointerRelativeRayCasterCamera);
  121. }
  122. // Process the first mouse button fully
  123. ProcessMousePress(scPointEventData.MouseButtonEventData);
  124. ProcessMove(scPointEventData);
  125. if(scPointEventData.MouseButtonEventData.PressedThisFrame() && scPointEventData.pointerCurrentRaycast.gameObject && scPointEventData.pointerDrag) {
  126. ///碰撞点指向碰撞物体中心的向量
  127. scPointEventData.HitPointerDeltaDragObjCenter = scPointEventData.pointerDrag.transform.position - scPointEventData.pointerCurrentRaycast.worldPosition;
  128. ///第一次赋值 ,must
  129. scPointEventData.dragObjPosition = scPointEventData.HitPointerDeltaDragObjCenter + scPointEventData.Position3D;
  130. }
  131. ///必须在ProcessDrag前,否则,延迟一帧导致停顿感
  132. if(scPointEventData.dragging) {
  133. scPointEventData.dragObjPosition = scPointEventData.HitPointerDeltaDragObjCenter + scPointEventData.Position3D;
  134. }
  135. ///拖拽不启动阈值,否则不能触发IDragHandler
  136. //scPointEventData.useDragThreshold = false;
  137. ProcessDrag(scPointEventData);
  138. ///更新dragHitPinterPosition,必须在ProcessDrag后,ProcessDrag调用的DragHandler可能会更改PointerDrag对象的Transform
  139. if(scPointEventData.dragging) {
  140. scPointEventData.dragAnchorPosition3D = scPointEventData.pointerDrag.transform.position - scPointEventData.HitPointerDeltaDragObjCenter;
  141. } else {
  142. scPointEventData.dragAnchorPosition3D = Vector3.zero;
  143. }
  144. if(!Mathf.Approximately(scPointEventData.scrollDelta.sqrMagnitude, 0.0f)) {
  145. var scrollHandler = ExecuteEvents.GetEventHandler<IScrollHandler>(scPointEventData.pointerCurrentRaycast.gameObject);
  146. ExecuteEvents.ExecuteHierarchy(scrollHandler, scPointEventData, ExecuteEvents.scrollHandler);
  147. }
  148. scPointEventDataxx = scPointEventData;
  149. }
  150. private static bool ShouldStartDrag(Vector3 pressPos, Vector3 currentPos, float threshold, bool useDragThreshold) {
  151. if(!useDragThreshold)
  152. return true;
  153. return (pressPos - currentPos).magnitude >= threshold * 0.0005f;
  154. }
  155. protected override void ProcessDrag(PointerEventData pointerEvent) {
  156. if(!pointerEvent.IsPointerMoving() ||
  157. Cursor.lockState == CursorLockMode.Locked ||
  158. pointerEvent.pointerDrag == null)
  159. return;
  160. if(!pointerEvent.dragging
  161. && ShouldStartDrag((pointerEvent as SCPointEventData).PressPosition3D, (pointerEvent as SCPointEventData).Position3D, eventSystem.pixelDragThreshold, pointerEvent.useDragThreshold)) {
  162. ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.beginDragHandler);
  163. pointerEvent.dragging = true;
  164. }
  165. // Drag notification
  166. if(pointerEvent.dragging) {
  167. // Before doing drag we should cancel any pointer down state
  168. // And clear selection!
  169. if(pointerEvent.pointerPress != pointerEvent.pointerDrag) {
  170. ExecuteEvents.Execute(pointerEvent.pointerPress, pointerEvent, ExecuteEvents.pointerUpHandler);
  171. pointerEvent.eligibleForClick = false;
  172. pointerEvent.pointerPress = null;
  173. pointerEvent.rawPointerPress = null;
  174. }
  175. ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.dragHandler);
  176. }
  177. }
  178. protected PointerEventData.FramePressState StateForMouseButton(InputDevicePartBase devicePart) {
  179. var pressed = devicePart.inputDataBase.inputKeys.GetKeyDown(InputKeyCode.Enter);
  180. var released = devicePart.inputDataBase.inputKeys.GetKeyUp(InputKeyCode.Enter);
  181. if(pressed && released)
  182. return PointerEventData.FramePressState.PressedAndReleased;
  183. if(pressed)
  184. return PointerEventData.FramePressState.Pressed;
  185. if(released)
  186. return PointerEventData.FramePressState.Released;
  187. return PointerEventData.FramePressState.NotChanged;
  188. }
  189. protected PhysicsRaycaster EnsurePhysicsRaycaster() {
  190. mPhysicsRaycaster = GetComponent<PhysicsRaycaster>();
  191. if(mPhysicsRaycaster == null) {
  192. mPhysicsRaycaster = gameObject.AddComponent<PhysicsRaycaster>();
  193. }
  194. return mPhysicsRaycaster;
  195. }
  196. protected Camera EnsureUIEventCamera(float maxDetectDistance = 30) {
  197. mRayCasterCamera = GetComponent<Camera>();
  198. if(!mRayCasterCamera) {
  199. mRayCasterCamera = gameObject.AddComponent<Camera>();
  200. }
  201. mRayCasterCamera.enabled = false;
  202. mRayCasterCamera.nearClipPlane = 0;
  203. mRayCasterCamera.farClipPlane = maxDetectDistance;
  204. mRayCasterCamera.clearFlags = CameraClearFlags.Color;
  205. mRayCasterCamera.backgroundColor = Color.black;
  206. mRayCasterCamera.orthographic = true;
  207. mRayCasterCamera.allowHDR = false;
  208. mRayCasterCamera.allowMSAA = false;
  209. mRayCasterCamera.orthographicSize = 0.1f;
  210. mRayCasterCamera.aspect = 1f;
  211. return mRayCasterCamera;
  212. }
  213. SCPointEventData scPointEventDataxx;
  214. //void OnDrawGizmos() {
  215. // if(Application.isPlaying) {
  216. // // Now show the input position.
  217. // //Gizmos.color = Color.red;
  218. // //foreach(var item in cornerLocalPostion) {
  219. // // Gizmos.DrawSphere(item, 0.01f);
  220. // //}
  221. // //Gizmos.color = Color.yellow;
  222. // //foreach(var item in midPointLocalPostion) {
  223. // // Gizmos.DrawSphere(item, 0.01f);
  224. // //}
  225. // if(scPointEventDataxx != null && scPointEventDataxx.DownPressGameObject) {
  226. // Gizmos.color = Color.black;
  227. // Gizmos.DrawSphere(scPointEventDataxx.PressPosition3D, 0.01f);
  228. // //Gizmos.color = Color.red * 0.5f;
  229. // Gizmos.DrawSphere(scPointEventDataxx.Position3D, 0.01f);
  230. // //Gizmos.color = Color.yellow * 0.5f;
  231. // if(scPointEventDataxx.pointerDrag != null) {
  232. // Gizmos.DrawSphere(scPointEventDataxx.dragObjPosition, 0.04f);
  233. // //Gizmos.color = Color.blue * 0.8f;
  234. // Gizmos.DrawSphere(scPointEventDataxx.dragAnchorPosition3D, 0.02f);
  235. // }
  236. // }
  237. // //if(scPointEventDataxx.pointerDrag)
  238. // //Gizmos.DrawSphere(scPointEventDataxx.pointerDrag.transform.position, 0.01f);
  239. // }
  240. //}
  241. }
  242. }