A game about forced loneliness, made by TACStudios
1using System.Runtime.InteropServices; 2using UnityEngine.InputSystem.Controls; 3using UnityEngine.InputSystem.Layouts; 4using UnityEngine.InputSystem.LowLevel; 5using UnityEngine.InputSystem.Utilities; 6 7////TODO: option to allow to constrain mouse input to the screen area (i.e. no input once mouse leaves player window) 8 9namespace UnityEngine.InputSystem.LowLevel 10{ 11 /// <summary> 12 /// Combine a single pointer with buttons and a scroll wheel. 13 /// </summary> 14 // IMPORTANT: State layout must match with MouseInputState in native. 15 [StructLayout(LayoutKind.Explicit, Size = 30)] 16 public struct MouseState : IInputStateTypeInfo 17 { 18 /// <summary> 19 /// Memory format identifier for MouseState. 20 /// </summary> 21 /// <value>Returns "MOUS".</value> 22 /// <seealso cref="InputStateBlock.format"/> 23 public static FourCC Format => new FourCC('M', 'O', 'U', 'S'); 24 25 /// <summary> 26 /// Screen-space position of the mouse in pixels. 27 /// </summary> 28 /// <value>Position of mouse on screen.</value> 29 /// <seealso cref="Pointer.position"/> 30 [InputControl(usage = "Point", dontReset = true)] // Mouse should stay put when we reset devices. 31 [FieldOffset(0)] 32 public Vector2 position; 33 34 /// <summary> 35 /// Screen-space motion delta of the mouse in pixels. 36 /// </summary> 37 /// <value>Mouse movement.</value> 38 /// <seealso cref="Pointer.delta"/> 39 [InputControl(usage = "Secondary2DMotion", layout = "Delta")] 40 [FieldOffset(8)] 41 public Vector2 delta; 42 43 ////REVIEW: have half-axis buttons on the scroll axes? (up, down, left, right) 44 /// <summary> 45 /// Scroll-wheel delta of the mouse. 46 /// </summary> 47 /// <value>Scroll wheel delta.</value> 48 /// <seealso cref="Mouse.scroll"/> 49 [InputControl(displayName = "Scroll", layout = "Delta")] 50 [InputControl(name = "scroll/x", aliases = new[] { "horizontal" }, usage = "ScrollHorizontal", displayName = "Left/Right")] 51 [InputControl(name = "scroll/y", aliases = new[] { "vertical" }, usage = "ScrollVertical", displayName = "Up/Down", shortDisplayName = "Wheel")] 52 [FieldOffset(16)] 53 public Vector2 scroll; 54 55 /// <summary> 56 /// Button mask for which buttons on the mouse are currently pressed. 57 /// </summary> 58 /// <value>Button state mask.</value> 59 /// <seealso cref="MouseButton"/> 60 /// <seealso cref="Mouse.leftButton"/> 61 /// <seealso cref="Mouse.middleButton"/> 62 /// <seealso cref="Mouse.rightButton"/> 63 /// <seealso cref="Mouse.forwardButton"/> 64 /// <seealso cref="Mouse.backButton"/> 65 [InputControl(name = "press", useStateFrom = "leftButton", synthetic = true, usages = new string[0])] 66 [InputControl(name = "leftButton", layout = "Button", bit = (int)MouseButton.Left, usage = "PrimaryAction", displayName = "Left Button", shortDisplayName = "LMB")] 67 [InputControl(name = "rightButton", layout = "Button", bit = (int)MouseButton.Right, usage = "SecondaryAction", displayName = "Right Button", shortDisplayName = "RMB")] 68 [InputControl(name = "middleButton", layout = "Button", bit = (int)MouseButton.Middle, displayName = "Middle Button", shortDisplayName = "MMB")] 69 [InputControl(name = "forwardButton", layout = "Button", bit = (int)MouseButton.Forward, usage = "Forward", displayName = "Forward")] 70 [InputControl(name = "backButton", layout = "Button", bit = (int)MouseButton.Back, usage = "Back", displayName = "Back")] 71 [FieldOffset(24)] 72 // "Park" all the controls that are common to pointers but aren't use for mice such that they get 73 // appended to the end of device state where they will always have default values. 74 ////FIXME: InputDeviceBuilder will get fooled and set up an incorrect state layout if we don't force this to VEC2; InputControlLayout will 75 //// "infer" USHT as the format which will then end up with a layout where two 4 byte float controls are "packed" into a 16bit sized parent; 76 //// in other words, setting VEC2 here manually should *not* be necessary 77 [InputControl(name = "pressure", layout = "Axis", usage = "Pressure", offset = InputStateBlock.AutomaticOffset, format = "FLT", sizeInBits = 32)] 78 [InputControl(name = "radius", layout = "Vector2", usage = "Radius", offset = InputStateBlock.AutomaticOffset, format = "VEC2", sizeInBits = 64)] 79 [InputControl(name = "pointerId", layout = "Digital", format = "BIT", sizeInBits = 1, offset = InputStateBlock.AutomaticOffset)] // Will stay at 0. 80 public ushort buttons; 81 82 /// <summary> 83 /// The index of the display that was moused. 84 /// </summary> 85 [InputControl(name = "displayIndex", layout = "Integer", displayName = "Display Index")] 86 [FieldOffset(26)] 87 public ushort displayIndex; 88 89 /// <summary> 90 /// Number of clicks performed in succession. 91 /// </summary> 92 /// <value>Successive click count.</value> 93 /// <seealso cref="Mouse.clickCount"/> 94 [InputControl(name = "clickCount", layout = "Integer", displayName = "Click Count", synthetic = true)] 95 [FieldOffset(28)] 96 public ushort clickCount; 97 98 /// <summary> 99 /// Set the button mask for the given button. 100 /// </summary> 101 /// <param name="button">Button whose state to set.</param> 102 /// <param name="state">Whether to set the bit on or off.</param> 103 /// <returns>The same MouseState with the change applied.</returns> 104 /// <seealso cref="buttons"/> 105 public MouseState WithButton(MouseButton button, bool state = true) 106 { 107 Debug.Assert((int)button < 16, $"Expected button < 16, so we fit into the 16 bit wide bitmask"); 108 var bit = 1U << (int)button; 109 if (state) 110 buttons |= (ushort)bit; 111 else 112 buttons &= (ushort)~bit; 113 return this; 114 } 115 116 /// <summary> 117 /// Returns <see cref="Format"/>. 118 /// </summary> 119 /// <seealso cref="InputStateBlock.format"/> 120 public FourCC format => Format; 121 } 122 123 /// <summary> 124 /// Button indices for <see cref="MouseState.buttons"/>. 125 /// </summary> 126 public enum MouseButton 127 { 128 /// <summary> 129 /// Left mouse button. 130 /// </summary> 131 /// <seealso cref="Mouse.leftButton"/> 132 Left, 133 134 /// <summary> 135 /// Right mouse button. 136 /// </summary> 137 /// <seealso cref="Mouse.rightButton"/> 138 Right, 139 140 /// <summary> 141 /// Middle mouse button. 142 /// </summary> 143 /// <seealso cref="Mouse.middleButton"/> 144 Middle, 145 146 /// <summary> 147 /// Second side button. 148 /// </summary> 149 /// <seealso cref="Mouse.forwardButton"/> 150 Forward, 151 152 /// <summary> 153 /// First side button. 154 /// </summary> 155 /// <seealso cref="Mouse.backButton"/> 156 Back 157 } 158} 159 160namespace UnityEngine.InputSystem 161{ 162 /// <summary> 163 /// An input device representing a mouse. 164 /// </summary> 165 /// <remarks> 166 /// Adds a scroll wheel and a typical 3-button setup with a left, middle, and right 167 /// button. 168 /// 169 /// To control cursor display and behavior, use <see cref="UnityEngine.Cursor"/>. 170 /// </remarks> 171 [InputControlLayout(stateType = typeof(MouseState), isGenericTypeOfDevice = true)] 172 public class Mouse : Pointer, IInputStateCallbackReceiver 173 { 174 /// <summary> 175 /// The horizontal and vertical scroll wheels. 176 /// </summary> 177 /// <value>Control representing the mouse scroll wheels.</value> 178 /// <remarks> 179 /// The <c>x</c> component corresponds to the horizontal scroll wheel, the 180 /// <c>y</c> component to the vertical scroll wheel. Most mice do not have 181 /// horizontal scroll wheels and will thus only see activity on <c>y</c>. 182 /// </remarks> 183 public DeltaControl scroll { get; protected set; } 184 185 /// <summary> 186 /// The left mouse button. 187 /// </summary> 188 /// <value>Control representing the left mouse button.</value> 189 public ButtonControl leftButton { get; protected set; } 190 191 /// <summary> 192 /// The middle mouse button. 193 /// </summary> 194 /// <value>Control representing the middle mouse button.</value> 195 public ButtonControl middleButton { get; protected set; } 196 197 /// <summary> 198 /// The right mouse button. 199 /// </summary> 200 /// <value>Control representing the right mouse button.</value> 201 public ButtonControl rightButton { get; protected set; } 202 203 /// <summary> 204 /// The first side button, often labeled/used as "back". 205 /// </summary> 206 /// <value>Control representing the back button on the mouse.</value> 207 /// <remarks> 208 /// On Windows, this corresponds to <c>RI_MOUSE_BUTTON_4</c>. 209 /// </remarks> 210 public ButtonControl backButton { get; protected set; } 211 212 /// <summary> 213 /// The second side button, often labeled/used as "forward". 214 /// </summary> 215 /// <value>Control representing the forward button on the mouse.</value> 216 /// <remarks> 217 /// On Windows, this corresponds to <c>RI_MOUSE_BUTTON_5</c>. 218 /// </remarks> 219 public ButtonControl forwardButton { get; protected set; } 220 221 /// <summary> 222 /// Number of times any of the mouse buttons has been clicked in succession within 223 /// the system-defined click time threshold. 224 /// </summary> 225 /// <value>Control representing the mouse click count.</value> 226 public IntegerControl clickCount { get; protected set; } 227 228 /// <summary> 229 /// The mouse that was added or updated last or null if there is no mouse 230 /// connected to the system. 231 /// </summary> 232 /// <seealso cref="InputDevice.MakeCurrent"/> 233 public new static Mouse current { get; private set; } 234 235 /// <summary> 236 /// Called when the mouse becomes the current mouse. 237 /// </summary> 238 public override void MakeCurrent() 239 { 240 base.MakeCurrent(); 241 current = this; 242 } 243 244 /// <summary> 245 /// Called when the mouse is added to the system. 246 /// </summary> 247 protected override void OnAdded() 248 { 249 base.OnAdded(); 250 251 if (native && s_PlatformMouseDevice == null) 252 s_PlatformMouseDevice = this; 253 } 254 255 /// <summary> 256 /// Called when the device is removed from the system. 257 /// </summary> 258 protected override void OnRemoved() 259 { 260 base.OnRemoved(); 261 if (current == this) 262 current = null; 263 } 264 265 internal static Mouse s_PlatformMouseDevice; 266 267 ////REVIEW: how should we handle this being called from EditorWindow's? (where the editor window space processor will turn coordinates automatically into editor window space) 268 /// <summary> 269 /// Move the operating system's mouse cursor. 270 /// </summary> 271 /// <param name="position">New position in player window space.</param> 272 /// <remarks> 273 /// The <see cref="Pointer.position"/> property will not update immediately but rather will update in the 274 /// next input update. 275 /// </remarks> 276 public void WarpCursorPosition(Vector2 position) 277 { 278 var command = WarpMousePositionCommand.Create(position); 279 ExecuteCommand(ref command); 280 } 281 282 /// <inheritdoc /> 283 protected override void FinishSetup() 284 { 285 scroll = GetChildControl<DeltaControl>("scroll"); 286 leftButton = GetChildControl<ButtonControl>("leftButton"); 287 middleButton = GetChildControl<ButtonControl>("middleButton"); 288 rightButton = GetChildControl<ButtonControl>("rightButton"); 289 forwardButton = GetChildControl<ButtonControl>("forwardButton"); 290 backButton = GetChildControl<ButtonControl>("backButton"); 291 displayIndex = GetChildControl<IntegerControl>("displayIndex"); 292 clickCount = GetChildControl<IntegerControl>("clickCount"); 293 base.FinishSetup(); 294 } 295 296 /// <summary> 297 /// Implements <see cref="IInputStateCallbackReceiver.OnNextUpdate"/> for the mouse. 298 /// </summary> 299 protected new void OnNextUpdate() 300 { 301 base.OnNextUpdate(); 302 InputState.Change(scroll, Vector2.zero); 303 } 304 305 /// <summary> 306 /// Implements <see cref="IInputStateCallbackReceiver.OnStateEvent"/> for the mouse. 307 /// </summary> 308 /// <param name="eventPtr"></param> 309 protected new unsafe void OnStateEvent(InputEventPtr eventPtr) 310 { 311 scroll.AccumulateValueInEvent(currentStatePtr, eventPtr); 312 base.OnStateEvent(eventPtr); 313 } 314 315 void IInputStateCallbackReceiver.OnNextUpdate() 316 { 317 OnNextUpdate(); 318 } 319 320 void IInputStateCallbackReceiver.OnStateEvent(InputEventPtr eventPtr) 321 { 322 OnStateEvent(eventPtr); 323 } 324 } 325}