123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- #if PACKAGE_DOCS_GENERATION || UNITY_INPUT_SYSTEM_ENABLE_UI
- using System.Text;
- using UnityEngine.EventSystems;
- using UnityEngine.InputSystem.Controls;
- using UnityEngine.InputSystem.Utilities;
-
- namespace UnityEngine.InputSystem.UI
- {
- /// <summary>
- /// An extension to <c>PointerEventData</c> which makes additional data about the input event available.
- /// </summary>
- /// <remarks>
- /// Instances of this class are sent instead of <see cref="PointerEventData"/> by <see cref="InputSystemUIInputModule"/>
- /// for all pointer-type input.
- ///
- /// The <see cref="PointerEventData.pointerId"/> property will generally correspond to the <see cref="InputDevice.deviceId"/>
- /// of <see cref="device"/>. An exception to this are touches as each <see cref="Touchscreen"/> may generate several pointers
- /// (one for each active finger).
- /// </remarks>
- public class ExtendedPointerEventData : PointerEventData
- {
- public ExtendedPointerEventData(EventSystem eventSystem)
- : base(eventSystem)
- {
- }
-
- /// <summary>
- /// The <see cref="InputControl"/> that generated the pointer input.
- /// The device associated with this control should be the same as this event's device.
- /// </summary>
- /// <seealso cref="device"/>
- public InputControl control { get; set; }
-
- /// <summary>
- /// The <see cref="InputDevice"/> that generated the pointer input.
- /// </summary>
- /// <seealso cref="Pointer"/>
- /// <seealso cref="Touchscreen"/>
- /// <seealso cref="Mouse"/>
- /// <seealso cref="Pen"/>
- public InputDevice device { get; set; }
-
- /// <summary>
- /// For <see cref="UIPointerType.Touch"/> type pointer input, this is the touch ID as reported by the
- /// <see cref="Touchscreen"/> device.
- /// </summary>
- /// <remarks>
- /// For pointer input that is not coming from touch, this will be 0 (which is not considered a valid touch ID
- /// by the input system).
- ///
- /// Note that for touch input, <see cref="PointerEventData.pointerId"/> will be a combination of the
- /// device ID of <see cref="device"/> and the touch ID to generate a unique pointer ID even if there
- /// are multiple touchscreens.
- /// </remarks>
- /// <seealso cref="TouchControl.touchId"/>
- public int touchId { get; set; }
-
- /// <summary>
- /// Type of pointer that generated the input.
- /// </summary>
- public UIPointerType pointerType { get; set; }
-
- public int uiToolkitPointerId { get; set; }
-
- /// <summary>
- /// For <see cref="UIPointerType.Tracked"/> type pointer input, this is the world-space position of
- /// the <see cref="TrackedDevice"/>.
- /// </summary>
- /// <seealso cref="InputSystemUIInputModule.trackedDevicePosition"/>
- public Vector3 trackedDevicePosition { get; set; }
-
- /// <summary>
- /// For <see cref="UIPointerType.Tracked"/> type pointer input, this is the world-space orientation of
- /// the <see cref="TrackedDevice"/>.
- /// </summary>
- /// <seealso cref="InputSystemUIInputModule.trackedDeviceOrientation"/>
- public Quaternion trackedDeviceOrientation { get; set; }
-
- public override string ToString()
- {
- var stringBuilder = new StringBuilder();
- stringBuilder.Append(base.ToString());
- stringBuilder.AppendLine("button: " + button); // Defined in PointerEventData but PointerEventData.ToString() does not include it.
- stringBuilder.AppendLine("clickTime: " + clickTime); // Same here.
- stringBuilder.AppendLine("clickCount: " + clickCount); // Same here.
- stringBuilder.AppendLine("device: " + device);
- stringBuilder.AppendLine("pointerType: " + pointerType);
- stringBuilder.AppendLine("touchId: " + touchId);
- stringBuilder.AppendLine("pressPosition: " + pressPosition);
- stringBuilder.AppendLine("trackedDevicePosition: " + trackedDevicePosition);
- stringBuilder.AppendLine("trackedDeviceOrientation: " + trackedDeviceOrientation);
- #if UNITY_2021_1_OR_NEWER
- stringBuilder.AppendLine("pressure" + pressure);
- stringBuilder.AppendLine("radius: " + radius);
- stringBuilder.AppendLine("azimuthAngle: " + azimuthAngle);
- stringBuilder.AppendLine("altitudeAngle: " + altitudeAngle);
- stringBuilder.AppendLine("twist: " + twist);
- #endif
- #if UNITY_2022_3_OR_NEWER
- stringBuilder.AppendLine("displayIndex: " + displayIndex);
- #endif
- return stringBuilder.ToString();
- }
-
- internal static int MakePointerIdForTouch(int deviceId, int touchId)
- {
- unchecked
- {
- return (deviceId << 24) + touchId;
- }
- }
-
- internal static int TouchIdFromPointerId(int pointerId)
- {
- return pointerId & 0xff;
- }
-
- ////TODO: add pressure and tilt support (probably add after 1.0; probably should have separate actions)
- /*
- /// <summary>
- /// If supported by the input device, this is the pressure level of the pointer contact. This is generally
- /// only supported by <see cref="Pen"/> devices as well as by <see cref="Touchscreen"/>s on phones. If not
- /// supported, this will be 1.
- /// </summary>
- /// <seealso cref="Pointer.pressure"/>
- public float pressure { get; set; }
-
- /// <summary>
- /// If the pointer input is coming from a <see cref="Pen"/>, this is pen's <see cref="Pen.tilt"/>.
- /// </summary>
- public Vector2 tilt { get; set; }
- */
-
- internal void ReadDeviceState()
- {
- if (control.parent is Pen pen)
- {
- uiToolkitPointerId = GetPenPointerId(pen);
- #if UNITY_2021_1_OR_NEWER
- pressure = pen.pressure.magnitude;
- azimuthAngle = (pen.tilt.value.x + 1) * Mathf.PI / 2;
- altitudeAngle = (pen.tilt.value.y + 1) * Mathf.PI / 2;
- twist = pen.twist.value * Mathf.PI * 2;
- #endif
- #if UNITY_2022_3_OR_NEWER
- displayIndex = pen.displayIndex.ReadValue();
- #endif
- }
- else if (control.parent is TouchControl touchControl)
- {
- uiToolkitPointerId = GetTouchPointerId(touchControl);
- #if UNITY_2021_1_OR_NEWER
- pressure = touchControl.pressure.magnitude;
- radius = touchControl.radius.value;
- #endif
- #if UNITY_2022_3_OR_NEWER
- displayIndex = touchControl.displayIndex.ReadValue();
- #endif
- }
- else if (control.parent is Touchscreen touchscreen)
- {
- uiToolkitPointerId = GetTouchPointerId(touchscreen.primaryTouch);
- #if UNITY_2021_1_OR_NEWER
- pressure = touchscreen.pressure.magnitude;
- radius = touchscreen.radius.value;
- #endif
- #if UNITY_2022_3_OR_NEWER
- displayIndex = touchscreen.displayIndex.ReadValue();
- #endif
- }
- else
- {
- uiToolkitPointerId = UIElements.PointerId.mousePointerId;
- }
- }
-
- private static int GetPenPointerId(Pen pen)
- {
- var n = 0;
- foreach (var otherDevice in InputSystem.devices)
- if (otherDevice is Pen otherPen)
- {
- if (pen == otherPen)
- {
- return UIElements.PointerId.penPointerIdBase +
- Mathf.Min(n, UIElements.PointerId.penPointerCount - 1);
- }
- n++;
- }
- return UIElements.PointerId.penPointerIdBase;
- }
-
- private static int GetTouchPointerId(TouchControl touchControl)
- {
- var i = ((Touchscreen)touchControl.device).touches.IndexOfReference(touchControl);
- return UIElements.PointerId.touchPointerIdBase +
- Mathf.Clamp(i, 0, UIElements.PointerId.touchPointerCount - 1);
- }
- }
-
- /// <summary>
- /// General type of pointer that generated a <see cref="PointerEventData"/> pointer event.
- /// </summary>
- public enum UIPointerType
- {
- None,
-
- /// <summary>
- /// A <see cref="Mouse"/> or <see cref="Pen"/> or other general <see cref="Pointer"/>.
- /// </summary>
- MouseOrPen,
-
- /// <summary>
- /// A <see cref="Touchscreen"/>.
- /// </summary>
- Touch,
-
- /// <summary>
- /// A <see cref="TrackedDevice"/>.
- /// </summary>
- Tracked,
- }
-
- /// <summary>
- /// Determine how the UI behaves in the presence of multiple pointer devices.
- /// </summary>
- /// <remarks>
- /// While running, an application may, for example, have both a <see cref="Mouse"/> and a <see cref="Touchscreen"/> device
- /// and both may end up getting bound to the actions of <see cref="InputSystemUIInputModule"/> and thus both may route
- /// input into the UI. When this happens, the pointer behavior decides how the UI input module resolves the ambiguity.
- /// </remarks>
- public enum UIPointerBehavior
- {
- /// <summary>
- /// Any input that isn't <see cref="Touchscreen"/> or <see cref="TrackedDevice"/> input is
- /// treated as a single unified pointer.
- ///
- /// This is the default behavior based on the expectation that mice and pens will generally drive a single on-screen
- /// cursor whereas touch and tracked devices have an inherent ability to generate multiple pointers.
- ///
- /// Note that when input from touch or tracked devices is received, the combined pointer for mice and pens (if it exists)
- /// will be removed. If it was over UI objects, <c>IPointerExitHandler</c>s will be invoked.
- /// </summary>
- SingleMouseOrPenButMultiTouchAndTrack,
-
- /// <summary>
- /// All input is unified to a single pointer. This means that all input from all pointing devices (<see cref="Mouse"/>,
- /// <see cref="Pen"/>, <see cref="Touchscreen"/>, and <see cref="TrackedDevice"/>) is routed into a single pointer
- /// instance. There is only one position on screen which can be controlled from any of these devices.
- /// </summary>
- SingleUnifiedPointer,
-
- /// <summary>
- /// Any pointing device, whether it's <see cref="Mouse"/>, <see cref="Pen"/>, <see cref="Touchscreen"/>,
- /// or <see cref="TrackedDevice"/> input, is treated as its own independent pointer and arbitrary many
- /// such pointers can be active at any one time.
- /// </summary>
- AllPointersAsIs,
- }
- }
- #endif
|