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.

PointerModel.cs 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  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 float pressure
  67. {
  68. get => m_Pressure;
  69. set
  70. {
  71. if (m_Pressure != value)
  72. {
  73. changedThisFrame = true;
  74. m_Pressure = value;
  75. }
  76. }
  77. }
  78. public float azimuthAngle
  79. {
  80. get => m_AzimuthAngle;
  81. set
  82. {
  83. if (m_AzimuthAngle != value)
  84. {
  85. changedThisFrame = true;
  86. m_AzimuthAngle = value;
  87. }
  88. }
  89. }
  90. public float altitudeAngle
  91. {
  92. get => m_AltitudeAngle;
  93. set
  94. {
  95. if (m_AltitudeAngle != value)
  96. {
  97. changedThisFrame = true;
  98. m_AltitudeAngle = value;
  99. }
  100. }
  101. }
  102. public float twist
  103. {
  104. get => m_Twist;
  105. set
  106. {
  107. if (m_Twist != value)
  108. {
  109. changedThisFrame = true;
  110. m_Twist = value;
  111. }
  112. }
  113. }
  114. public Vector2 radius
  115. {
  116. get => m_Radius;
  117. set
  118. {
  119. if (m_Radius != value)
  120. {
  121. changedThisFrame = true;
  122. m_Radius = value;
  123. }
  124. }
  125. }
  126. public ButtonState leftButton;
  127. public ButtonState rightButton;
  128. public ButtonState middleButton;
  129. public ExtendedPointerEventData eventData;
  130. public PointerModel(ExtendedPointerEventData eventData)
  131. {
  132. this.eventData = eventData;
  133. changedThisFrame = false;
  134. leftButton = default; leftButton.OnEndFrame();
  135. rightButton = default; rightButton.OnEndFrame();
  136. middleButton = default; middleButton.OnEndFrame();
  137. m_ScreenPosition = default;
  138. m_ScrollDelta = default;
  139. m_WorldOrientation = default;
  140. m_WorldPosition = default;
  141. m_Pressure = default;
  142. m_AzimuthAngle = default;
  143. m_AltitudeAngle = default;
  144. m_Twist = default;
  145. m_Radius = default;
  146. }
  147. public void OnFrameFinished()
  148. {
  149. changedThisFrame = false;
  150. scrollDelta = default;
  151. leftButton.OnEndFrame();
  152. rightButton.OnEndFrame();
  153. middleButton.OnEndFrame();
  154. }
  155. private Vector2 m_ScreenPosition;
  156. private Vector2 m_ScrollDelta;
  157. private Vector3 m_WorldPosition;
  158. private Quaternion m_WorldOrientation;
  159. private float m_Pressure;
  160. private float m_AzimuthAngle;
  161. private float m_AltitudeAngle;
  162. private float m_Twist;
  163. private Vector2 m_Radius;
  164. public void CopyTouchOrPenStateFrom(PointerEventData eventData)
  165. {
  166. #if UNITY_2021_1_OR_NEWER
  167. pressure = eventData.pressure;
  168. azimuthAngle = eventData.azimuthAngle;
  169. altitudeAngle = eventData.altitudeAngle;
  170. twist = eventData.twist;
  171. radius = eventData.radius;
  172. #endif
  173. }
  174. // State related to pressing and releasing individual bodies. Retains those parts of
  175. // PointerInputEvent that are specific to presses and releases.
  176. public struct ButtonState
  177. {
  178. private bool m_IsPressed;
  179. private PointerEventData.FramePressState m_FramePressState;
  180. private float m_PressTime;
  181. public bool isPressed
  182. {
  183. get => m_IsPressed;
  184. set
  185. {
  186. if (m_IsPressed != value)
  187. {
  188. m_IsPressed = value;
  189. if (m_FramePressState == PointerEventData.FramePressState.NotChanged && value)
  190. m_FramePressState = PointerEventData.FramePressState.Pressed;
  191. else if (m_FramePressState == PointerEventData.FramePressState.NotChanged && !value)
  192. m_FramePressState = PointerEventData.FramePressState.Released;
  193. else if (m_FramePressState == PointerEventData.FramePressState.Pressed && !value)
  194. m_FramePressState = PointerEventData.FramePressState.PressedAndReleased;
  195. }
  196. }
  197. }
  198. /// <summary>
  199. /// When we "release" a button other than through user interaction (e.g. through focus switching),
  200. /// we don't want this to count as an actual release that ends up clicking. This flag will cause
  201. /// generated events to have <c>eligibleForClick</c> to be false.
  202. /// </summary>
  203. public bool ignoreNextClick
  204. {
  205. get => m_IgnoreNextClick;
  206. set => m_IgnoreNextClick = value;
  207. }
  208. public float pressTime
  209. {
  210. get => m_PressTime;
  211. set => m_PressTime = value;
  212. }
  213. public bool clickedOnSameGameObject
  214. {
  215. get => m_ClickedOnSameGameObject;
  216. set => m_ClickedOnSameGameObject = value;
  217. }
  218. public bool wasPressedThisFrame => m_FramePressState == PointerEventData.FramePressState.Pressed ||
  219. m_FramePressState == PointerEventData.FramePressState.PressedAndReleased;
  220. public bool wasReleasedThisFrame => m_FramePressState == PointerEventData.FramePressState.Released ||
  221. m_FramePressState == PointerEventData.FramePressState.PressedAndReleased;
  222. private RaycastResult m_PressRaycast;
  223. private GameObject m_PressObject;
  224. private GameObject m_RawPressObject;
  225. private GameObject m_LastPressObject;
  226. private GameObject m_DragObject;
  227. private Vector2 m_PressPosition;
  228. private float m_ClickTime; // On Time.unscaledTime timeline, NOT input event time.
  229. private int m_ClickCount;
  230. private bool m_Dragging;
  231. private bool m_ClickedOnSameGameObject;
  232. private bool m_IgnoreNextClick;
  233. public void CopyPressStateTo(PointerEventData eventData)
  234. {
  235. eventData.pointerPressRaycast = m_PressRaycast;
  236. eventData.pressPosition = m_PressPosition;
  237. eventData.clickCount = m_ClickCount;
  238. eventData.clickTime = m_ClickTime;
  239. // We can't set lastPress directly. Old input module uses three different event instances, one for each
  240. // button. We share one instance and just switch press states. Set pointerPress twice to get the lastPress
  241. // we need.
  242. //
  243. // NOTE: This does *NOT* quite work as stated in the docs. pointerPress is nulled out on button release which
  244. // will set lastPress as a side-effect. This means that lastPress will only be non-null while no press is
  245. // going on and will *NOT* refer to the last pressed object when a new object has been pressed on.
  246. eventData.pointerPress = m_LastPressObject;
  247. eventData.pointerPress = m_PressObject;
  248. eventData.rawPointerPress = m_RawPressObject;
  249. eventData.pointerDrag = m_DragObject;
  250. eventData.dragging = m_Dragging;
  251. if (ignoreNextClick)
  252. eventData.eligibleForClick = false;
  253. }
  254. public void CopyPressStateFrom(PointerEventData eventData)
  255. {
  256. m_PressRaycast = eventData.pointerPressRaycast;
  257. m_PressObject = eventData.pointerPress;
  258. m_RawPressObject = eventData.rawPointerPress;
  259. m_LastPressObject = eventData.lastPress;
  260. m_PressPosition = eventData.pressPosition;
  261. m_ClickTime = eventData.clickTime;
  262. m_ClickCount = eventData.clickCount;
  263. m_DragObject = eventData.pointerDrag;
  264. m_Dragging = eventData.dragging;
  265. }
  266. public void OnEndFrame()
  267. {
  268. m_FramePressState = PointerEventData.FramePressState.NotChanged;
  269. }
  270. }
  271. }
  272. }
  273. #endif