SCInputModule.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  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. using UnityEngine.UI;
  9. namespace SC.XR.Unity.Module_InputSystem {
  10. public class SCInputModule : StandaloneInputModule {
  11. public static SCInputModule Instance { get; private set; }
  12. public static bool IsRayCastResultsSortByDistance = false;
  13. public static bool IsUseSCScrollRectMode = false;
  14. private Camera mRayCasterCamera;
  15. public Camera RayCasterCamera {
  16. get {
  17. if(mRayCasterCamera == null) {
  18. mRayCasterCamera = EnsureUIEventCamera();
  19. }
  20. mRayCasterCamera.orthographic = true;
  21. return mRayCasterCamera;
  22. }
  23. }
  24. private PhysicsRaycaster mPhysicsRaycaster;
  25. public PhysicsRaycaster PhysicsRaycaster {
  26. get {
  27. if(mPhysicsRaycaster == null) {
  28. mPhysicsRaycaster = EnsurePhysicsRaycaster();
  29. }
  30. return mPhysicsRaycaster;
  31. }
  32. }
  33. public LayerMask layerMask;
  34. public float maxDetectDistance=0;
  35. Vector3? lastMousePoint3d;
  36. Vector2 newPos, lastPosition;
  37. Vector3 viewportPos = new Vector3(0.5f, 0.5f, 1f);
  38. Rect camerarect = new Rect(0, 0, 1, 1);
  39. static Rect constCamerarect = new Rect(0, 0, 1, 1);
  40. protected override void Start() {
  41. base.Start();
  42. if(Instance) {
  43. DestroyImmediate(this);
  44. return;
  45. }
  46. DontDestroyOnLoad(gameObject);
  47. Instance = this;
  48. camerarect = new Rect(0, 0, 1, 1);
  49. }
  50. public override void Process() {
  51. }
  52. public virtual void ProcessCS(SCPointEventData scPointEventData, Transform posture, int layerMask = 1 << 8, float maxDetectDistance = 30,bool isSimlate=false, RaycastResult simlateResult=new RaycastResult()) {
  53. //if(!eventSystem.isFocused)
  54. // return;
  55. bool usedEvent = SendUpdateEventToSelectedObject();
  56. ProcessSCEventInit(scPointEventData, posture, layerMask, maxDetectDistance);
  57. ProcessSCEvent(scPointEventData, isSimlate, simlateResult);
  58. if(eventSystem.sendNavigationEvents) {
  59. /*
  60. if(!usedEvent)
  61. usedEvent |= SendMoveEventToSelectedObject();
  62. if(!usedEvent)
  63. SendSubmitEventToSelectedObject();*/
  64. }
  65. }
  66. void ProcessSCEventInit(SCPointEventData scPointEventData, Transform posture, int layerMask, float maxDetectDistance) {
  67. if(this.layerMask.value != 0) {
  68. layerMask = this.layerMask;
  69. }
  70. if(this.maxDetectDistance > 0) {
  71. maxDetectDistance = this.maxDetectDistance;
  72. }
  73. PhysicsRaycaster.eventMask = layerMask;
  74. RayCasterCamera.cullingMask = layerMask;
  75. RayCasterCamera.farClipPlane = maxDetectDistance;
  76. RayCasterCamera.transform.position = posture.position; // posture.position;// Vector3.Lerp(RayCasterCamera.transform.position, targetDetectBase.transform.position,0.3f); //targetDetectBase.transform.position;
  77. RayCasterCamera.transform.rotation = posture.rotation;
  78. ///Canvas分配wrold Camera
  79. foreach (var canvas in CanvasCollection.CanvasList) {
  80. canvas.worldCamera = RayCasterCamera;
  81. }
  82. mRayCasterCamera.orthographic = true;
  83. if (mRayCasterCamera.rect != constCamerarect) {
  84. mRayCasterCamera.rect = camerarect;
  85. }
  86. newPos = SCInputModule.Instance.RayCasterCamera.ViewportToScreenPoint(viewportPos);
  87. // Populate initial data or drag data
  88. if (lastMousePoint3d == null) {
  89. // For the first event, use the same position for 'last' and 'new'.
  90. lastPosition = newPos;
  91. } else {
  92. // Otherwise, re-project the last pointer position.
  93. lastPosition = SCInputModule.Instance.RayCasterCamera.WorldToScreenPoint(lastMousePoint3d.Value);
  94. }
  95. // Save off the 3D position of the cursor.
  96. lastMousePoint3d = SCInputModule.Instance.RayCasterCamera.ViewportToWorldPoint(viewportPos);
  97. scPointEventData.delta = newPos - lastPosition;
  98. scPointEventData.position = newPos;
  99. //if(RayCasterCamera != null && Application.platform != RuntimePlatform.Android) {
  100. // Ray ray = new Ray();
  101. // ray = RayCasterCamera.ScreenPointToRay(scPointEventData.position);
  102. // Debug.DrawRay(ray.origin, ray.direction * maxDetectDistance, Color.blue);
  103. //}
  104. }
  105. protected static RaycastResult FindFirstRaycastByDistance(List<RaycastResult> candidates) {
  106. candidates.Sort(s_RaycastComparer);
  107. return FindFirstRaycast(candidates);
  108. }
  109. private static readonly Comparison<RaycastResult> s_RaycastComparer = RaycastComparer;
  110. private static int RaycastComparer(RaycastResult lhs, RaycastResult rhs) {
  111. return lhs.distance.CompareTo(rhs.distance);
  112. }
  113. /// <summary>
  114. /// Process all mouse events.
  115. /// </summary>
  116. protected void ProcessSCEvent(SCPointEventData scPointEventData, bool isSimlate = false, RaycastResult simlateResult = new RaycastResult()) {
  117. scPointEventData.MouseButtonEventData.buttonData = scPointEventData;
  118. scPointEventData.MouseButtonEventData.buttonState = StateForMouseButton(scPointEventData.inputDevicePartBase);
  119. if(isSimlate) {
  120. scPointEventData.pointerCurrentRaycast = simlateResult;
  121. } else {
  122. try {
  123. mRayCasterCamera.orthographic = true;
  124. eventSystem.RaycastAll(scPointEventData, m_RaycastResultCache);
  125. } catch (Exception e) {
  126. Debug.Log(e);
  127. Debug.Log("============>Start:" + Time.frameCount);
  128. if (mRayCasterCamera) {
  129. //Debug.Log("============>Start:"+Time.frameCount);
  130. Debug.Log("parent:" + mRayCasterCamera.transform.name);
  131. Debug.Log("nearClipPlane:" + mRayCasterCamera.nearClipPlane);
  132. Debug.Log("farClipPlane:" + mRayCasterCamera.farClipPlane);
  133. Debug.Log("orthographic:" + mRayCasterCamera.orthographic);
  134. Debug.Log("orthographicSize:" + mRayCasterCamera.orthographicSize);
  135. Debug.Log("aspect:" + mRayCasterCamera.aspect);
  136. Debug.Log("rect:" + mRayCasterCamera.rect);
  137. Debug.Log("============>End:" + Time.frameCount);
  138. }
  139. }
  140. if (!IsRayCastResultsSortByDistance) {
  141. scPointEventData.pointerCurrentRaycast = FindFirstRaycast(m_RaycastResultCache);
  142. } else {
  143. scPointEventData.pointerCurrentRaycast = FindFirstRaycastByDistance(m_RaycastResultCache);
  144. }
  145. m_RaycastResultCache.Clear();
  146. }
  147. scPointEventData.Forward = RayCasterCamera.transform.forward;
  148. if(scPointEventData.MouseButtonEventData.PressedThisFrame() && scPointEventData.pointerCurrentRaycast.gameObject) {
  149. scPointEventData.HitPointerRelativeRayCasterCamera = RayCasterCamera.transform.InverseTransformPoint(scPointEventData.pointerCurrentRaycast.worldPosition);
  150. scPointEventData.Position3D = scPointEventData.PressPosition3D = RayCasterCamera.transform.TransformPoint(scPointEventData.HitPointerRelativeRayCasterCamera);
  151. scPointEventData.pressForward = RayCasterCamera.transform.forward;
  152. scPointEventData.DownPressGameObject = scPointEventData.pointerCurrentRaycast.gameObject;
  153. } else if(scPointEventData.MouseButtonEventData.ReleasedThisFrame()) {
  154. scPointEventData.HitPointerDeltaDragObjCenter = scPointEventData.HitPointerRelativeRayCasterCamera = scPointEventData.dragObjPosition = Vector3.zero;
  155. scPointEventData.Position3D = Vector3.zero;
  156. scPointEventData.PressPosition3D = Vector3.zero;
  157. scPointEventData.DownPressGameObject = null;
  158. scPointEventData.pressForward = Vector3.zero;
  159. scPointEventData.downtimer = 0;
  160. }
  161. if(scPointEventData.DownPressGameObject) {
  162. scPointEventData.downtimer += Time.deltaTime;
  163. scPointEventData.Position3D = RayCasterCamera.transform.TransformPoint(scPointEventData.HitPointerRelativeRayCasterCamera);
  164. }
  165. // Process the first mouse button fully
  166. ProcessMousePress(scPointEventData.MouseButtonEventData);
  167. ProcessMove(scPointEventData);
  168. if (scPointEventData.MouseButtonEventData.PressedThisFrame() && scPointEventData.pointerCurrentRaycast.gameObject) {
  169. if (scPointEventData.pointerDrag) {
  170. ///碰撞点指向碰撞物体中心的向量
  171. scPointEventData.HitPointerDeltaDragObjCenter = scPointEventData.pointerDrag.transform.position - scPointEventData.pointerCurrentRaycast.worldPosition;
  172. } else {
  173. ///碰撞点指向碰撞物体中心的向量
  174. scPointEventData.HitPointerDeltaDragObjCenter = scPointEventData.pointerCurrentRaycast.gameObject.transform.position - scPointEventData.pointerCurrentRaycast.worldPosition;
  175. }
  176. ///第一次赋值 ,must
  177. scPointEventData.dragObjPosition = scPointEventData.HitPointerDeltaDragObjCenter + scPointEventData.Position3D;
  178. }
  179. ///必须在ProcessDrag前,否则,延迟一帧导致停顿感
  180. if(scPointEventData.dragging) {
  181. scPointEventData.dragObjPosition = scPointEventData.HitPointerDeltaDragObjCenter + scPointEventData.Position3D;
  182. }
  183. ///拖拽不启动阈值,否则不能触发IDragHandler
  184. //scPointEventData.useDragThreshold = false;
  185. ProcessDrag(scPointEventData);
  186. ///更新dragHitPinterPosition,必须在ProcessDrag后,ProcessDrag调用的DragHandler可能会更改PointerDrag对象的Transform
  187. if(scPointEventData.dragging) {
  188. scPointEventData.dragAnchorPosition3D = scPointEventData.pointerDrag.transform.position - scPointEventData.HitPointerDeltaDragObjCenter;
  189. } else {
  190. scPointEventData.dragAnchorPosition3D = Vector3.zero;
  191. }
  192. if (!Mathf.Approximately(scPointEventData.scrollDelta.sqrMagnitude, 0.0f)) {
  193. if (IsUseSCScrollRectMode) {
  194. m_scrollrectRight = FindRightScrollRect(scPointEventData.pointerCurrentRaycast.gameObject, scPointEventData);
  195. if (m_scrollrectRight != null) {
  196. ExecuteEvents.ExecuteHierarchy(m_scrollrectRight.gameObject, scPointEventData, ExecuteEvents.scrollHandler);
  197. } else {
  198. /// for implementation IScrollHandler But not ScrollRect
  199. var scrollHandlerG = ExecuteEvents.GetEventHandler<IScrollHandler>(scPointEventData.pointerCurrentRaycast.gameObject);
  200. ExecuteEvents.ExecuteHierarchy(scrollHandlerG, scPointEventData, ExecuteEvents.scrollHandler);
  201. }
  202. } else {
  203. var scrollHandlerG = ExecuteEvents.GetEventHandler<IScrollHandler>(scPointEventData.pointerCurrentRaycast.gameObject);
  204. ExecuteEvents.ExecuteHierarchy(scrollHandlerG, scPointEventData, ExecuteEvents.scrollHandler);
  205. }
  206. }
  207. scPointEventDataxx = scPointEventData;
  208. }
  209. ScrollRect scrollrectRight;
  210. ScrollRect m_scrollrectRight;
  211. ScrollRect FindRightScrollRect(GameObject gameobject,PointerEventData eventdata) {
  212. if (gameobject == null)
  213. return null;
  214. scrollrectRight = gameobject.GetComponentInParent<ScrollRect>();
  215. if (scrollrectRight!= null && scrollrectRight.gameObject.activeSelf &&
  216. ((scrollrectRight.horizontal == false && eventdata.scrollDelta.x != 0) ||
  217. (scrollrectRight.vertical == false && eventdata.scrollDelta.y != 0)
  218. )
  219. ) {
  220. if (scrollrectRight.transform.parent == null)
  221. return null;
  222. scrollrectRight = FindRightScrollRect(scrollrectRight.transform.parent.gameObject, eventdata);
  223. }
  224. return scrollrectRight;
  225. }
  226. private static bool ShouldStartDrag(Vector3 pressPos, Vector3 currentPos, float threshold, bool useDragThreshold, PointerEventData pointerEventData) {
  227. if (useDragThreshold) {
  228. if (!useDragThreshold)
  229. return true;
  230. return (pressPos - currentPos).magnitude >= threshold * 0.0005f;
  231. }
  232. return true;
  233. }
  234. protected override void ProcessDrag(PointerEventData pointerEvent) {
  235. if(!pointerEvent.IsPointerMoving() ||
  236. Cursor.lockState == CursorLockMode.Locked ||
  237. pointerEvent.pointerDrag == null)
  238. return;
  239. if(!pointerEvent.dragging
  240. && ShouldStartDrag((pointerEvent as SCPointEventData).PressPosition3D, (pointerEvent as SCPointEventData).Position3D, eventSystem.pixelDragThreshold, pointerEvent.useDragThreshold, pointerEvent)) {
  241. ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.beginDragHandler);
  242. pointerEvent.dragging = true;
  243. }
  244. // Drag notification
  245. if(pointerEvent.dragging) {
  246. // Before doing drag we should cancel any pointer down state
  247. // And clear selection!
  248. //&& ((pointerEvent as SCPointEventData).downtimer >= (pointerEvent as SCPointEventData).TriggerDeltaTime) ? true : false 解决3D环境下误触发Drag导致后,松开不能正常触发click的问题
  249. if (pointerEvent.pointerPress != pointerEvent.pointerDrag && ((pointerEvent as SCPointEventData).downtimer >= (pointerEvent as SCPointEventData).TriggerDeltaTime) ? true : false) {
  250. ExecuteEvents.Execute(pointerEvent.pointerPress, pointerEvent, ExecuteEvents.pointerUpHandler);
  251. pointerEvent.eligibleForClick = false;
  252. pointerEvent.pointerPress = null;
  253. pointerEvent.rawPointerPress = null;
  254. }
  255. ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.dragHandler);
  256. }
  257. }
  258. protected PointerEventData.FramePressState StateForMouseButton(InputDevicePartBase devicePart) {
  259. var pressed = devicePart.inputDataBase.inputKeys.GetKeyDown(InputKeyCode.Enter);
  260. var released = devicePart.inputDataBase.inputKeys.GetKeyUp(InputKeyCode.Enter);
  261. if(pressed && released)
  262. return PointerEventData.FramePressState.PressedAndReleased;
  263. if(pressed)
  264. return PointerEventData.FramePressState.Pressed;
  265. if(released)
  266. return PointerEventData.FramePressState.Released;
  267. return PointerEventData.FramePressState.NotChanged;
  268. }
  269. protected PhysicsRaycaster EnsurePhysicsRaycaster() {
  270. mPhysicsRaycaster = GetComponent<PhysicsRaycaster>();
  271. if(mPhysicsRaycaster == null) {
  272. mPhysicsRaycaster = gameObject.AddComponent<PhysicsRaycaster>();
  273. }
  274. return mPhysicsRaycaster;
  275. }
  276. protected Camera EnsureUIEventCamera(float maxDetectDistance = 30) {
  277. mRayCasterCamera = GetComponent<Camera>();
  278. if(!mRayCasterCamera) {
  279. mRayCasterCamera = gameObject.AddComponent<Camera>();
  280. }
  281. mRayCasterCamera.enabled = false;
  282. mRayCasterCamera.nearClipPlane = 0;
  283. mRayCasterCamera.farClipPlane = maxDetectDistance;
  284. mRayCasterCamera.clearFlags = CameraClearFlags.Color;
  285. mRayCasterCamera.backgroundColor = Color.black;
  286. mRayCasterCamera.orthographic = true;
  287. mRayCasterCamera.allowHDR = false;
  288. mRayCasterCamera.allowMSAA = false;
  289. mRayCasterCamera.orthographicSize = 0.1f;
  290. mRayCasterCamera.aspect = 1f;
  291. return mRayCasterCamera;
  292. }
  293. SCPointEventData scPointEventDataxx;
  294. //void OnDrawGizmos() {
  295. // if(Application.isPlaying) {
  296. // // Now show the input position.
  297. // //Gizmos.color = Color.red;
  298. // //foreach(var item in cornerLocalPostion) {
  299. // // Gizmos.DrawSphere(item, 0.01f);
  300. // //}
  301. // //Gizmos.color = Color.yellow;
  302. // //foreach(var item in midPointLocalPostion) {
  303. // // Gizmos.DrawSphere(item, 0.01f);
  304. // //}
  305. // if(scPointEventDataxx != null && scPointEventDataxx.DownPressGameObject) {
  306. // Gizmos.color = Color.black;
  307. // Gizmos.DrawSphere(scPointEventDataxx.PressPosition3D, 0.01f);
  308. // //Gizmos.color = Color.red * 0.5f;
  309. // Gizmos.DrawSphere(scPointEventDataxx.Position3D, 0.01f);
  310. // //Gizmos.color = Color.yellow * 0.5f;
  311. // if(scPointEventDataxx.pointerDrag != null) {
  312. // Gizmos.DrawSphere(scPointEventDataxx.dragObjPosition, 0.04f);
  313. // //Gizmos.color = Color.blue * 0.8f;
  314. // Gizmos.DrawSphere(scPointEventDataxx.dragAnchorPosition3D, 0.02f);
  315. // }
  316. // }
  317. // //if(scPointEventDataxx.pointerDrag)
  318. // //Gizmos.DrawSphere(scPointEventDataxx.pointerDrag.transform.position, 0.01f);
  319. // }
  320. //}
  321. }
  322. }