PointerModel.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #if UNITY_INPUT_SYSTEM_ENABLE_UI
  2. using UnityEngine.EventSystems;
  3. namespace UnityEngine.InputSystem.UI
  4. {
  5. // A pointer is identified by a single unique integer ID. It has an associated position and the ability to press
  6. // on up to three buttons. It can also scroll.
  7. //
  8. // There's a single ExtendedPointerEventData instance allocated for the pointer which is used to retain the pointer's
  9. // event state. As part of that state is specific to button presses, each button retains a partial copy of press-specific
  10. // event information.
  11. //
  12. // A pointer can operate in 2D (mouse, pen, touch) or 3D (tracked). For 3D, screen-space 2D positions are derived
  13. // via raycasts based on world-space position and orientation.
  14. internal struct PointerModel
  15. {
  16. public bool changedThisFrame;
  17. public UIPointerType pointerType => eventData.pointerType;
  18. public Vector2 screenPosition
  19. {
  20. get => m_ScreenPosition;
  21. set
  22. {
  23. if (m_ScreenPosition != value)
  24. {
  25. m_ScreenPosition = value;
  26. changedThisFrame = true;
  27. }
  28. }
  29. }
  30. public Vector3 worldPosition
  31. {
  32. get => m_WorldPosition;
  33. set
  34. {
  35. if (m_WorldPosition != value)
  36. {
  37. m_WorldPosition = value;
  38. changedThisFrame = true;
  39. }
  40. }
  41. }
  42. public Quaternion worldOrientation
  43. {
  44. get => m_WorldOrientation;
  45. set
  46. {
  47. if (m_WorldOrientation != value)
  48. {
  49. m_WorldOrientation = value;
  50. changedThisFrame = true;
  51. }
  52. }
  53. }
  54. public Vector2 scrollDelta
  55. {
  56. get => m_ScrollDelta;
  57. set
  58. {
  59. if (m_ScrollDelta != value)
  60. {
  61. changedThisFrame = true;
  62. m_ScrollDelta = value;
  63. }
  64. }
  65. }
  66. public ButtonState leftButton;
  67. public ButtonState rightButton;
  68. public ButtonState middleButton;
  69. public ExtendedPointerEventData eventData;
  70. public PointerModel(int pointerId, int touchId, UIPointerType pointerType, InputDevice device, ExtendedPointerEventData eventData)
  71. {
  72. this.eventData = eventData;
  73. eventData.pointerId = pointerId;
  74. eventData.touchId = touchId;
  75. eventData.pointerType = pointerType;
  76. eventData.device = device;
  77. changedThisFrame = false;
  78. leftButton = default; leftButton.OnEndFrame();
  79. rightButton = default; rightButton.OnEndFrame();
  80. middleButton = default; middleButton.OnEndFrame();
  81. m_ScreenPosition = default;
  82. m_ScrollDelta = default;
  83. m_WorldOrientation = default;
  84. m_WorldPosition = default;
  85. }
  86. public void OnFrameFinished()
  87. {
  88. changedThisFrame = false;
  89. scrollDelta = default;
  90. leftButton.OnEndFrame();
  91. rightButton.OnEndFrame();
  92. middleButton.OnEndFrame();
  93. }
  94. private Vector2 m_ScreenPosition;
  95. private Vector2 m_ScrollDelta;
  96. private Vector3 m_WorldPosition;
  97. private Quaternion m_WorldOrientation;
  98. // State related to pressing and releasing individual bodies. Retains those parts of
  99. // PointerInputEvent that are specific to presses and releases.
  100. public struct ButtonState
  101. {
  102. private bool m_IsPressed;
  103. private PointerEventData.FramePressState m_FramePressState;
  104. public bool isPressed
  105. {
  106. get => m_IsPressed;
  107. set
  108. {
  109. if (m_IsPressed != value)
  110. {
  111. m_IsPressed = value;
  112. if (m_FramePressState == PointerEventData.FramePressState.NotChanged && value)
  113. m_FramePressState = PointerEventData.FramePressState.Pressed;
  114. else if (m_FramePressState == PointerEventData.FramePressState.NotChanged && !value)
  115. m_FramePressState = PointerEventData.FramePressState.Released;
  116. else if (m_FramePressState == PointerEventData.FramePressState.Pressed && !value)
  117. m_FramePressState = PointerEventData.FramePressState.PressedAndReleased;
  118. }
  119. }
  120. }
  121. public bool wasPressedThisFrame => m_FramePressState == PointerEventData.FramePressState.Pressed ||
  122. m_FramePressState == PointerEventData.FramePressState.PressedAndReleased;
  123. public bool wasReleasedThisFrame => m_FramePressState == PointerEventData.FramePressState.Released ||
  124. m_FramePressState == PointerEventData.FramePressState.PressedAndReleased;
  125. private RaycastResult pressRaycast;
  126. private GameObject pressObject;
  127. private GameObject rawPressObject;
  128. private GameObject lastPressObject;
  129. private GameObject dragObject;
  130. private Vector2 pressPosition;
  131. private float clickTime; // On Time.unscaledTime timeline, NOT input event time.
  132. private int clickCount;
  133. private bool dragging;
  134. public void CopyPressStateTo(PointerEventData eventData)
  135. {
  136. eventData.pointerPressRaycast = pressRaycast;
  137. eventData.pressPosition = pressPosition;
  138. eventData.clickCount = clickCount;
  139. eventData.clickTime = clickTime;
  140. // We can't set lastPress directly. Old input module uses three different event instances, one for each
  141. // button. We share one instance and just switch press states. Set pointerPress twice to get the lastPress
  142. // we need.
  143. //
  144. // NOTE: This does *NOT* quite work as stated in the docs. pointerPress is nulled out on button release which
  145. // will set lastPress as a side-effect. This means that lastPress will only be non-null while no press is
  146. // going on and will *NOT* refer to the last pressed object when a new object has been pressed on.
  147. eventData.pointerPress = lastPressObject;
  148. eventData.pointerPress = pressObject;
  149. eventData.rawPointerPress = rawPressObject;
  150. eventData.pointerDrag = dragObject;
  151. eventData.dragging = dragging;
  152. }
  153. public void CopyPressStateFrom(PointerEventData eventData)
  154. {
  155. pressRaycast = eventData.pointerPressRaycast;
  156. pressObject = eventData.pointerPress;
  157. rawPressObject = eventData.rawPointerPress;
  158. lastPressObject = eventData.lastPress;
  159. pressPosition = eventData.pressPosition;
  160. clickTime = eventData.clickTime;
  161. clickCount = eventData.clickCount;
  162. dragObject = eventData.pointerDrag;
  163. dragging = eventData.dragging;
  164. }
  165. public void OnEndFrame()
  166. {
  167. m_FramePressState = PointerEventData.FramePressState.NotChanged;
  168. }
  169. }
  170. }
  171. }
  172. #endif