File size: 11,133 Bytes
18a519f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 | #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_2023_1_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_2023_1_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_2023_1_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_2023_1_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
|