No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

StandaloneInputModule.cs 24KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  1. using System;
  2. using UnityEngine;
  3. using UnityEngine.Serialization;
  4. namespace UnityEngine.EventSystems
  5. {
  6. [AddComponentMenu("Event/Standalone Input Module")]
  7. /// <summary>
  8. /// A BaseInputModule designed for mouse / keyboard / controller input.
  9. /// </summary>
  10. /// <remarks>
  11. /// Input module for working with, mouse, keyboard, or controller.
  12. /// </remarks>
  13. public class StandaloneInputModule : PointerInputModule
  14. {
  15. private float m_PrevActionTime;
  16. private Vector2 m_LastMoveVector;
  17. private int m_ConsecutiveMoveCount = 0;
  18. private Vector2 m_LastMousePosition;
  19. private Vector2 m_MousePosition;
  20. private GameObject m_CurrentFocusedGameObject;
  21. private PointerEventData m_InputPointerEvent;
  22. protected StandaloneInputModule()
  23. {
  24. }
  25. [Obsolete("Mode is no longer needed on input module as it handles both mouse and keyboard simultaneously.", false)]
  26. public enum InputMode
  27. {
  28. Mouse,
  29. Buttons
  30. }
  31. [Obsolete("Mode is no longer needed on input module as it handles both mouse and keyboard simultaneously.", false)]
  32. public InputMode inputMode
  33. {
  34. get { return InputMode.Mouse; }
  35. }
  36. [SerializeField]
  37. private string m_HorizontalAxis = "Horizontal";
  38. /// <summary>
  39. /// Name of the vertical axis for movement (if axis events are used).
  40. /// </summary>
  41. [SerializeField]
  42. private string m_VerticalAxis = "Vertical";
  43. /// <summary>
  44. /// Name of the submit button.
  45. /// </summary>
  46. [SerializeField]
  47. private string m_SubmitButton = "Submit";
  48. /// <summary>
  49. /// Name of the submit button.
  50. /// </summary>
  51. [SerializeField]
  52. private string m_CancelButton = "Cancel";
  53. [SerializeField]
  54. private float m_InputActionsPerSecond = 10;
  55. [SerializeField]
  56. private float m_RepeatDelay = 0.5f;
  57. [SerializeField]
  58. [FormerlySerializedAs("m_AllowActivationOnMobileDevice")]
  59. [HideInInspector]
  60. private bool m_ForceModuleActive;
  61. [Obsolete("allowActivationOnMobileDevice has been deprecated. Use forceModuleActive instead (UnityUpgradable) -> forceModuleActive")]
  62. public bool allowActivationOnMobileDevice
  63. {
  64. get { return m_ForceModuleActive; }
  65. set { m_ForceModuleActive = value; }
  66. }
  67. /// <summary>
  68. /// Force this module to be active.
  69. /// </summary>
  70. /// <remarks>
  71. /// If there is no module active with higher priority (ordered in the inspector) this module will be forced active even if valid enabling conditions are not met.
  72. /// </remarks>
  73. [Obsolete("forceModuleActive has been deprecated. There is no need to force the module awake as StandaloneInputModule works for all platforms")]
  74. public bool forceModuleActive
  75. {
  76. get { return m_ForceModuleActive; }
  77. set { m_ForceModuleActive = value; }
  78. }
  79. /// <summary>
  80. /// Number of keyboard / controller inputs allowed per second.
  81. /// </summary>
  82. public float inputActionsPerSecond
  83. {
  84. get { return m_InputActionsPerSecond; }
  85. set { m_InputActionsPerSecond = value; }
  86. }
  87. /// <summary>
  88. /// Delay in seconds before the input actions per second repeat rate takes effect.
  89. /// </summary>
  90. /// <remarks>
  91. /// If the same direction is sustained, the inputActionsPerSecond property can be used to control the rate at which events are fired. However, it can be desirable that the first repetition is delayed, so the user doesn't get repeated actions by accident.
  92. /// </remarks>
  93. public float repeatDelay
  94. {
  95. get { return m_RepeatDelay; }
  96. set { m_RepeatDelay = value; }
  97. }
  98. /// <summary>
  99. /// Name of the horizontal axis for movement (if axis events are used).
  100. /// </summary>
  101. public string horizontalAxis
  102. {
  103. get { return m_HorizontalAxis; }
  104. set { m_HorizontalAxis = value; }
  105. }
  106. /// <summary>
  107. /// Name of the vertical axis for movement (if axis events are used).
  108. /// </summary>
  109. public string verticalAxis
  110. {
  111. get { return m_VerticalAxis; }
  112. set { m_VerticalAxis = value; }
  113. }
  114. /// <summary>
  115. /// Maximum number of input events handled per second.
  116. /// </summary>
  117. public string submitButton
  118. {
  119. get { return m_SubmitButton; }
  120. set { m_SubmitButton = value; }
  121. }
  122. /// <summary>
  123. /// Input manager name for the 'cancel' button.
  124. /// </summary>
  125. public string cancelButton
  126. {
  127. get { return m_CancelButton; }
  128. set { m_CancelButton = value; }
  129. }
  130. private bool ShouldIgnoreEventsOnNoFocus()
  131. {
  132. #if UNITY_EDITOR
  133. return !UnityEditor.EditorApplication.isRemoteConnected;
  134. #else
  135. return true;
  136. #endif
  137. }
  138. public override void UpdateModule()
  139. {
  140. if (!eventSystem.isFocused && ShouldIgnoreEventsOnNoFocus())
  141. {
  142. if (m_InputPointerEvent != null && m_InputPointerEvent.pointerDrag != null && m_InputPointerEvent.dragging)
  143. {
  144. ReleaseMouse(m_InputPointerEvent, m_InputPointerEvent.pointerCurrentRaycast.gameObject);
  145. }
  146. m_InputPointerEvent = null;
  147. return;
  148. }
  149. m_LastMousePosition = m_MousePosition;
  150. m_MousePosition = input.mousePosition;
  151. }
  152. private void ReleaseMouse(PointerEventData pointerEvent, GameObject currentOverGo)
  153. {
  154. ExecuteEvents.Execute(pointerEvent.pointerPress, pointerEvent, ExecuteEvents.pointerUpHandler);
  155. var pointerClickHandler = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
  156. // PointerClick and Drop events
  157. if (pointerEvent.pointerClick == pointerClickHandler && pointerEvent.eligibleForClick)
  158. {
  159. ExecuteEvents.Execute(pointerEvent.pointerClick, pointerEvent, ExecuteEvents.pointerClickHandler);
  160. }
  161. if (pointerEvent.pointerDrag != null && pointerEvent.dragging)
  162. {
  163. ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.dropHandler);
  164. }
  165. pointerEvent.eligibleForClick = false;
  166. pointerEvent.pointerPress = null;
  167. pointerEvent.rawPointerPress = null;
  168. pointerEvent.pointerClick = null;
  169. if (pointerEvent.pointerDrag != null && pointerEvent.dragging)
  170. ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.endDragHandler);
  171. pointerEvent.dragging = false;
  172. pointerEvent.pointerDrag = null;
  173. // redo pointer enter / exit to refresh state
  174. // so that if we moused over something that ignored it before
  175. // due to having pressed on something else
  176. // it now gets it.
  177. if (currentOverGo != pointerEvent.pointerEnter)
  178. {
  179. HandlePointerExitAndEnter(pointerEvent, null);
  180. HandlePointerExitAndEnter(pointerEvent, currentOverGo);
  181. }
  182. m_InputPointerEvent = pointerEvent;
  183. }
  184. public override bool ShouldActivateModule()
  185. {
  186. if (!base.ShouldActivateModule())
  187. return false;
  188. var shouldActivate = m_ForceModuleActive;
  189. shouldActivate |= input.GetButtonDown(m_SubmitButton);
  190. shouldActivate |= input.GetButtonDown(m_CancelButton);
  191. shouldActivate |= !Mathf.Approximately(input.GetAxisRaw(m_HorizontalAxis), 0.0f);
  192. shouldActivate |= !Mathf.Approximately(input.GetAxisRaw(m_VerticalAxis), 0.0f);
  193. shouldActivate |= (m_MousePosition - m_LastMousePosition).sqrMagnitude > 0.0f;
  194. shouldActivate |= input.GetMouseButtonDown(0);
  195. if (input.touchCount > 0)
  196. shouldActivate = true;
  197. return shouldActivate;
  198. }
  199. /// <summary>
  200. /// See BaseInputModule.
  201. /// </summary>
  202. public override void ActivateModule()
  203. {
  204. if (!eventSystem.isFocused && ShouldIgnoreEventsOnNoFocus())
  205. return;
  206. base.ActivateModule();
  207. m_MousePosition = input.mousePosition;
  208. m_LastMousePosition = input.mousePosition;
  209. var toSelect = eventSystem.currentSelectedGameObject;
  210. if (toSelect == null)
  211. toSelect = eventSystem.firstSelectedGameObject;
  212. eventSystem.SetSelectedGameObject(toSelect, GetBaseEventData());
  213. }
  214. /// <summary>
  215. /// See BaseInputModule.
  216. /// </summary>
  217. public override void DeactivateModule()
  218. {
  219. base.DeactivateModule();
  220. ClearSelection();
  221. }
  222. public override void Process()
  223. {
  224. if (!eventSystem.isFocused && ShouldIgnoreEventsOnNoFocus())
  225. return;
  226. bool usedEvent = SendUpdateEventToSelectedObject();
  227. // case 1004066 - touch / mouse events should be processed before navigation events in case
  228. // they change the current selected gameobject and the submit button is a touch / mouse button.
  229. // touch needs to take precedence because of the mouse emulation layer
  230. if (!ProcessTouchEvents() && input.mousePresent)
  231. ProcessMouseEvent();
  232. if (eventSystem.sendNavigationEvents)
  233. {
  234. if (!usedEvent)
  235. usedEvent |= SendMoveEventToSelectedObject();
  236. if (!usedEvent)
  237. SendSubmitEventToSelectedObject();
  238. }
  239. }
  240. private bool ProcessTouchEvents()
  241. {
  242. for (int i = 0; i < input.touchCount; ++i)
  243. {
  244. Touch touch = input.GetTouch(i);
  245. if (touch.type == TouchType.Indirect)
  246. continue;
  247. bool released;
  248. bool pressed;
  249. var pointer = GetTouchPointerEventData(touch, out pressed, out released);
  250. ProcessTouchPress(pointer, pressed, released);
  251. if (!released)
  252. {
  253. ProcessMove(pointer);
  254. ProcessDrag(pointer);
  255. }
  256. else
  257. RemovePointerData(pointer);
  258. }
  259. return input.touchCount > 0;
  260. }
  261. /// <summary>
  262. /// This method is called by Unity whenever a touch event is processed. Override this method with a custom implementation to process touch events yourself.
  263. /// </summary>
  264. /// <param name="pointerEvent">Event data relating to the touch event, such as position and ID to be passed to the touch event destination object.</param>
  265. /// <param name="pressed">This is true for the first frame of a touch event, and false thereafter. This can therefore be used to determine the instant a touch event occurred.</param>
  266. /// <param name="released">This is true only for the last frame of a touch event.</param>
  267. /// <remarks>
  268. /// This method can be overridden in derived classes to change how touch press events are handled.
  269. /// </remarks>
  270. protected void ProcessTouchPress(PointerEventData pointerEvent, bool pressed, bool released)
  271. {
  272. var currentOverGo = pointerEvent.pointerCurrentRaycast.gameObject;
  273. // PointerDown notification
  274. if (pressed)
  275. {
  276. pointerEvent.eligibleForClick = true;
  277. pointerEvent.delta = Vector2.zero;
  278. pointerEvent.dragging = false;
  279. pointerEvent.useDragThreshold = true;
  280. pointerEvent.pressPosition = pointerEvent.position;
  281. pointerEvent.pointerPressRaycast = pointerEvent.pointerCurrentRaycast;
  282. DeselectIfSelectionChanged(currentOverGo, pointerEvent);
  283. if (pointerEvent.pointerEnter != currentOverGo)
  284. {
  285. // send a pointer enter to the touched element if it isn't the one to select...
  286. HandlePointerExitAndEnter(pointerEvent, currentOverGo);
  287. pointerEvent.pointerEnter = currentOverGo;
  288. }
  289. // search for the control that will receive the press
  290. // if we can't find a press handler set the press
  291. // handler to be what would receive a click.
  292. var newPressed = ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.pointerDownHandler);
  293. var newClick = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
  294. // didnt find a press handler... search for a click handler
  295. if (newPressed == null)
  296. newPressed = newClick;
  297. // Debug.Log("Pressed: " + newPressed);
  298. float time = Time.unscaledTime;
  299. if (newPressed == pointerEvent.lastPress)
  300. {
  301. var diffTime = time - pointerEvent.clickTime;
  302. if (diffTime < 0.3f)
  303. ++pointerEvent.clickCount;
  304. else
  305. pointerEvent.clickCount = 1;
  306. pointerEvent.clickTime = time;
  307. }
  308. else
  309. {
  310. pointerEvent.clickCount = 1;
  311. }
  312. pointerEvent.pointerPress = newPressed;
  313. pointerEvent.rawPointerPress = currentOverGo;
  314. pointerEvent.pointerClick = newClick;
  315. pointerEvent.clickTime = time;
  316. // Save the drag handler as well
  317. pointerEvent.pointerDrag = ExecuteEvents.GetEventHandler<IDragHandler>(currentOverGo);
  318. if (pointerEvent.pointerDrag != null)
  319. ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.initializePotentialDrag);
  320. }
  321. // PointerUp notification
  322. if (released)
  323. {
  324. // Debug.Log("Executing pressup on: " + pointer.pointerPress);
  325. ExecuteEvents.Execute(pointerEvent.pointerPress, pointerEvent, ExecuteEvents.pointerUpHandler);
  326. // Debug.Log("KeyCode: " + pointer.eventData.keyCode);
  327. // see if we mouse up on the same element that we clicked on...
  328. var pointerClickHandler = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
  329. // PointerClick and Drop events
  330. if (pointerEvent.pointerClick == pointerClickHandler && pointerEvent.eligibleForClick)
  331. {
  332. ExecuteEvents.Execute(pointerEvent.pointerClick, pointerEvent, ExecuteEvents.pointerClickHandler);
  333. }
  334. if (pointerEvent.pointerDrag != null && pointerEvent.dragging)
  335. {
  336. ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.dropHandler);
  337. }
  338. pointerEvent.eligibleForClick = false;
  339. pointerEvent.pointerPress = null;
  340. pointerEvent.rawPointerPress = null;
  341. pointerEvent.pointerClick = null;
  342. if (pointerEvent.pointerDrag != null && pointerEvent.dragging)
  343. ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.endDragHandler);
  344. pointerEvent.dragging = false;
  345. pointerEvent.pointerDrag = null;
  346. // send exit events as we need to simulate this on touch up on touch device
  347. ExecuteEvents.ExecuteHierarchy(pointerEvent.pointerEnter, pointerEvent, ExecuteEvents.pointerExitHandler);
  348. pointerEvent.pointerEnter = null;
  349. }
  350. m_InputPointerEvent = pointerEvent;
  351. }
  352. /// <summary>
  353. /// Calculate and send a submit event to the current selected object.
  354. /// </summary>
  355. /// <returns>If the submit event was used by the selected object.</returns>
  356. protected bool SendSubmitEventToSelectedObject()
  357. {
  358. if (eventSystem.currentSelectedGameObject == null)
  359. return false;
  360. var data = GetBaseEventData();
  361. if (input.GetButtonDown(m_SubmitButton))
  362. ExecuteEvents.Execute(eventSystem.currentSelectedGameObject, data, ExecuteEvents.submitHandler);
  363. if (input.GetButtonDown(m_CancelButton))
  364. ExecuteEvents.Execute(eventSystem.currentSelectedGameObject, data, ExecuteEvents.cancelHandler);
  365. return data.used;
  366. }
  367. private Vector2 GetRawMoveVector()
  368. {
  369. Vector2 move = Vector2.zero;
  370. move.x = input.GetAxisRaw(m_HorizontalAxis);
  371. move.y = input.GetAxisRaw(m_VerticalAxis);
  372. if (input.GetButtonDown(m_HorizontalAxis))
  373. {
  374. if (move.x < 0)
  375. move.x = -1f;
  376. if (move.x > 0)
  377. move.x = 1f;
  378. }
  379. if (input.GetButtonDown(m_VerticalAxis))
  380. {
  381. if (move.y < 0)
  382. move.y = -1f;
  383. if (move.y > 0)
  384. move.y = 1f;
  385. }
  386. return move;
  387. }
  388. /// <summary>
  389. /// Calculate and send a move event to the current selected object.
  390. /// </summary>
  391. /// <returns>If the move event was used by the selected object.</returns>
  392. protected bool SendMoveEventToSelectedObject()
  393. {
  394. float time = Time.unscaledTime;
  395. Vector2 movement = GetRawMoveVector();
  396. if (Mathf.Approximately(movement.x, 0f) && Mathf.Approximately(movement.y, 0f))
  397. {
  398. m_ConsecutiveMoveCount = 0;
  399. return false;
  400. }
  401. bool similarDir = (Vector2.Dot(movement, m_LastMoveVector) > 0);
  402. // If direction didn't change at least 90 degrees, wait for delay before allowing consequtive event.
  403. if (similarDir && m_ConsecutiveMoveCount == 1)
  404. {
  405. if (time <= m_PrevActionTime + m_RepeatDelay)
  406. return false;
  407. }
  408. // If direction changed at least 90 degree, or we already had the delay, repeat at repeat rate.
  409. else
  410. {
  411. if (time <= m_PrevActionTime + 1f / m_InputActionsPerSecond)
  412. return false;
  413. }
  414. var axisEventData = GetAxisEventData(movement.x, movement.y, 0.6f);
  415. if (axisEventData.moveDir != MoveDirection.None)
  416. {
  417. ExecuteEvents.Execute(eventSystem.currentSelectedGameObject, axisEventData, ExecuteEvents.moveHandler);
  418. if (!similarDir)
  419. m_ConsecutiveMoveCount = 0;
  420. m_ConsecutiveMoveCount++;
  421. m_PrevActionTime = time;
  422. m_LastMoveVector = movement;
  423. }
  424. else
  425. {
  426. m_ConsecutiveMoveCount = 0;
  427. }
  428. return axisEventData.used;
  429. }
  430. protected void ProcessMouseEvent()
  431. {
  432. ProcessMouseEvent(0);
  433. }
  434. [Obsolete("This method is no longer checked, overriding it with return true does nothing!")]
  435. protected virtual bool ForceAutoSelect()
  436. {
  437. return false;
  438. }
  439. /// <summary>
  440. /// Process all mouse events.
  441. /// </summary>
  442. protected void ProcessMouseEvent(int id)
  443. {
  444. var mouseData = GetMousePointerEventData(id);
  445. var leftButtonData = mouseData.GetButtonState(PointerEventData.InputButton.Left).eventData;
  446. m_CurrentFocusedGameObject = leftButtonData.buttonData.pointerCurrentRaycast.gameObject;
  447. // Process the first mouse button fully
  448. ProcessMousePress(leftButtonData);
  449. ProcessMove(leftButtonData.buttonData);
  450. ProcessDrag(leftButtonData.buttonData);
  451. // Now process right / middle clicks
  452. ProcessMousePress(mouseData.GetButtonState(PointerEventData.InputButton.Right).eventData);
  453. ProcessDrag(mouseData.GetButtonState(PointerEventData.InputButton.Right).eventData.buttonData);
  454. ProcessMousePress(mouseData.GetButtonState(PointerEventData.InputButton.Middle).eventData);
  455. ProcessDrag(mouseData.GetButtonState(PointerEventData.InputButton.Middle).eventData.buttonData);
  456. if (!Mathf.Approximately(leftButtonData.buttonData.scrollDelta.sqrMagnitude, 0.0f))
  457. {
  458. var scrollHandler = ExecuteEvents.GetEventHandler<IScrollHandler>(leftButtonData.buttonData.pointerCurrentRaycast.gameObject);
  459. ExecuteEvents.ExecuteHierarchy(scrollHandler, leftButtonData.buttonData, ExecuteEvents.scrollHandler);
  460. }
  461. }
  462. protected bool SendUpdateEventToSelectedObject()
  463. {
  464. if (eventSystem.currentSelectedGameObject == null)
  465. return false;
  466. var data = GetBaseEventData();
  467. ExecuteEvents.Execute(eventSystem.currentSelectedGameObject, data, ExecuteEvents.updateSelectedHandler);
  468. return data.used;
  469. }
  470. /// <summary>
  471. /// Calculate and process any mouse button state changes.
  472. /// </summary>
  473. protected void ProcessMousePress(MouseButtonEventData data)
  474. {
  475. var pointerEvent = data.buttonData;
  476. var currentOverGo = pointerEvent.pointerCurrentRaycast.gameObject;
  477. // PointerDown notification
  478. if (data.PressedThisFrame())
  479. {
  480. pointerEvent.eligibleForClick = true;
  481. pointerEvent.delta = Vector2.zero;
  482. pointerEvent.dragging = false;
  483. pointerEvent.useDragThreshold = true;
  484. pointerEvent.pressPosition = pointerEvent.position;
  485. pointerEvent.pointerPressRaycast = pointerEvent.pointerCurrentRaycast;
  486. DeselectIfSelectionChanged(currentOverGo, pointerEvent);
  487. // search for the control that will receive the press
  488. // if we can't find a press handler set the press
  489. // handler to be what would receive a click.
  490. var newPressed = ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.pointerDownHandler);
  491. var newClick = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
  492. // didnt find a press handler... search for a click handler
  493. if (newPressed == null)
  494. newPressed = newClick;
  495. // Debug.Log("Pressed: " + newPressed);
  496. float time = Time.unscaledTime;
  497. if (newPressed == pointerEvent.lastPress)
  498. {
  499. var diffTime = time - pointerEvent.clickTime;
  500. if (diffTime < 0.3f)
  501. ++pointerEvent.clickCount;
  502. else
  503. pointerEvent.clickCount = 1;
  504. pointerEvent.clickTime = time;
  505. }
  506. else
  507. {
  508. pointerEvent.clickCount = 1;
  509. }
  510. pointerEvent.pointerPress = newPressed;
  511. pointerEvent.rawPointerPress = currentOverGo;
  512. pointerEvent.pointerClick = newClick;
  513. pointerEvent.clickTime = time;
  514. // Save the drag handler as well
  515. pointerEvent.pointerDrag = ExecuteEvents.GetEventHandler<IDragHandler>(currentOverGo);
  516. if (pointerEvent.pointerDrag != null)
  517. ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.initializePotentialDrag);
  518. m_InputPointerEvent = pointerEvent;
  519. }
  520. // PointerUp notification
  521. if (data.ReleasedThisFrame())
  522. {
  523. ReleaseMouse(pointerEvent, currentOverGo);
  524. }
  525. }
  526. protected GameObject GetCurrentFocusedGameObject()
  527. {
  528. return m_CurrentFocusedGameObject;
  529. }
  530. }
  531. }