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}