A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections.Generic;
3using UnityEngine.InputSystem.Controls;
4using UnityEngine.InputSystem.Layouts;
5using UnityEngine.InputSystem.LowLevel;
6using UnityEngine.InputSystem.Processors;
7using UnityEngine.InputSystem.Utilities;
8
9////TODO: make sure that alterations made to InputSystem.settings in play mode do not leak out into edit mode or the asset
10
11////TODO: handle case of supportFixedUpdates and supportDynamicUpdates both being set to false; should it be an enum?
12
13////TODO: figure out how this gets into a build
14
15////TODO: allow setting up single- and multi-user configs for the project
16
17////TODO: allow enabling/disabling plugins
18
19////REVIEW: should the project settings include a list of action assets to use? (or to force into a build)
20
21////REVIEW: add extra option to enable late-updates?
22
23////REVIEW: put default sensor sampling frequency here?
24
25////REVIEW: put default gamepad polling frequency here?
26
27////REVIEW: Have an InputActionAsset field in here that allows having a single default set of actions that are enabled with no further setup?
28
29namespace UnityEngine.InputSystem
30{
31 /// <summary>
32 /// Project-wide input settings.
33 /// </summary>
34 /// <remarks>
35 /// Several aspects of the input system can be customized to tailor how the system functions to the
36 /// specific needs of a project. These settings are collected in this class. There is one global
37 /// settings object active at any one time. It can be accessed and set through <see cref="InputSystem.settings"/>.
38 ///
39 /// Changing a setting on the object takes effect immediately. It also triggers the
40 /// <see cref="InputSystem.onSettingsChange"/> callback.
41 /// </remarks>
42 /// <seealso cref="InputSystem.settings"/>
43 /// <seealso cref="InputSystem.onSettingsChange"/>
44 public partial class InputSettings : ScriptableObject
45 {
46 /// <summary>
47 /// Allows you to control how the input system handles updates. In other words, how and when pending input events are processed.
48 /// </summary>
49 /// <value>When to run input updates.</value>
50 /// <remarks>
51 /// By default, input updates will automatically be triggered as part of the player loop.
52 /// If <c>updateMode</c> is set to <see cref="UpdateMode.ProcessEventsInDynamicUpdate"/>
53 /// (the default), then right at the beginning of a dynamic update (i.e. before all
54 /// <c>MonoBehaviour.Update</c> methods are called), input is processed. And if <c>updateMode</c>
55 /// is set to <see cref="UpdateMode.ProcessEventsInFixedUpdate"/>, then right at the beginning
56 /// of each fixed update (i.e. before all <c>MonoBehaviour.FixedUpdate</c> methods are
57 /// called), input is processed.
58 ///
59 /// Additionally, if there are devices that need updates right before rendering (see <see
60 /// cref="InputDevice.updateBeforeRender"/>), an extra update will be run right before
61 /// rendering. This special update will only consume input on devices that have
62 /// <see cref="InputDevice.updateBeforeRender"/> set to <c>true</c>.
63 ///
64 /// You can run updates manually using <see cref="InputSystem.Update"/>. Doing so
65 /// outside of tests is only recommended, however, if <c>updateMode</c> is set to
66 /// <see cref="UpdateMode.ProcessEventsManually"/> (in which case it is actually required
67 /// for input to be processed at all).
68 ///
69 /// Note that in the editor, input updates will also run before each editor update
70 /// (i.e. as part of <c>EditorApplication.update</c>). Player and editor input state
71 /// are kept separate, though, so any input consumed in editor updates will not be visible
72 /// in player updates and vice versa.
73 /// </remarks>
74 /// <seealso cref="InputSystem.Update"/>
75 public UpdateMode updateMode
76 {
77 get => m_UpdateMode;
78 set
79 {
80 if (m_UpdateMode == value)
81 return;
82 m_UpdateMode = value;
83 OnChange();
84 }
85 }
86
87 /// <summary>
88 /// Controls how platform-specific input should be converted when returning delta values for scroll wheel input actions.
89 /// </summary>
90 /// <value>The conversion behavior.</value>
91 /// <remarks>
92 /// By default, the range used for the delta is normalized to a range of -1 to 1, to be uniform across all platforms.
93 /// The alternative is that the native platform's scroll wheel range is returned, which is -120 to 120 for windows, and
94 /// -1 to 1 for most other platforms. You should leave this value as the default uniform range unless you need to support
95 /// legacy code that relies on the native platform-specific values.
96 /// </remarks>
97 public ScrollDeltaBehavior scrollDeltaBehavior
98 {
99 get => m_ScrollDeltaBehavior;
100 set
101 {
102 if (m_ScrollDeltaBehavior == value)
103 return;
104 m_ScrollDeltaBehavior = value;
105 OnChange();
106 }
107 }
108
109 /// <summary>
110 /// If true, sensors that deliver rotation values on handheld devices will automatically adjust
111 /// rotations when the screen orientation changes.
112 /// </summary>
113 /// <remarks>
114 /// This is enabled by default.
115 ///
116 /// If enabled, rotation values will be rotated around Z. In <see cref="ScreenOrientation.Portrait"/>, values
117 /// remain unchanged. In <see cref="ScreenOrientation.PortraitUpsideDown"/>, they will be rotated by 180 degrees.
118 /// In <see cref="ScreenOrientation.LandscapeLeft"/> by 90 degrees, and in <see cref="ScreenOrientation.LandscapeRight"/>
119 /// by 270 degrees.
120 ///
121 /// Sensors affected by this setting are <see cref="Accelerometer"/>, <see cref="Compass"/>, and <see cref="Gyroscope"/>.
122 /// </remarks>
123 /// <seealso cref="CompensateDirectionProcessor"/>
124 public bool compensateForScreenOrientation
125 {
126 get => m_CompensateForScreenOrientation;
127 set
128 {
129 if (m_CompensateForScreenOrientation == value)
130 return;
131 m_CompensateForScreenOrientation = value;
132 OnChange();
133 }
134 }
135
136 /// <summary>
137 /// Currently: Option is deprecated and has no influence on the system. Filtering on noise is always enabled.
138 /// Previously: Whether to not make a device <c>.current</c> (see <see cref="InputDevice.MakeCurrent"/>)
139 /// when there is only noise in the input.
140 /// </summary>
141 /// <remarks>
142 /// We add extra processing every time input is
143 /// received on a device that is considered noisy. These devices are those that
144 /// have at least one control that is marked as <see cref="InputControl.noisy"/>.
145 /// A good example is the PS4 controller which has a gyroscope sensor built into
146 /// the device. Whereas sticks and buttons on the device require user interaction
147 /// to produce non-default values, the gyro will produce varying values even if
148 /// the device just sits there without user interaction.
149 ///
150 /// Without noise filtering, a PS4 controller will thus continually make itself
151 /// current as it will send a continuous stream of input even when not actively
152 /// used by the player. By toggling this property on, each input event will be
153 /// run through a noise mask. Only if state has changed outside of memory areas
154 /// marked as noise will the input be considered valid user interaction and the
155 /// device will be made current. Note that in this process, the system does
156 /// <em>not</em> determine whether non-noisy controls on the device have actually
157 /// changed value. All the system establishes is whether such controls have changed
158 /// <em>state</em>. However, processing such as for deadzones may cause values
159 /// to not effectively change even though the non-noisy state of the device has
160 /// changed.
161 /// </remarks>
162 /// <seealso cref="InputDevice.MakeCurrent"/>
163 /// <seealso cref="InputControl.noisy"/>
164 [Obsolete("filterNoiseOnCurrent is deprecated, filtering of noise is always enabled now.", false)]
165 public bool filterNoiseOnCurrent
166 {
167 get => false;
168 set
169 {
170 /* no op */
171 }
172 }
173
174 /// <summary>
175 /// Default value used when nothing is set explicitly on <see cref="StickDeadzoneProcessor.min"/>
176 /// or <see cref="AxisDeadzoneProcessor.min"/>.
177 /// </summary>
178 /// <value>Default lower limit for deadzones.</value>
179 /// <remarks>
180 /// "Deadzones" refer to limits established for the range of values accepted as input
181 /// on a control. If the value for the control falls outside the range, i.e. below the
182 /// given minimum or above the given maximum, the value is clamped to the respective
183 /// limit.
184 ///
185 /// This property configures the default lower bound of the value range.
186 ///
187 /// Note that deadzones will by default re-normalize values after clamping. This means that
188 /// inputs at the lower and upper end are dropped and that the range in-between is re-normalized
189 /// to [0..1].
190 ///
191 /// Note that deadzones preserve the sign of inputs. This means that both the upper and
192 /// the lower deadzone bound extend to both the positive and the negative range. For example,
193 /// a deadzone min of 0.1 will clamp values between -0.1 and +0.1.
194 ///
195 /// The most common example of where deadzones are used are the sticks on gamepads, i.e.
196 /// <see cref="Gamepad.leftStick"/> and <see cref="Gamepad.rightStick"/>. Sticks will
197 /// usually be wobbly to some extent (just how wobbly varies greatly between different
198 /// types of controllers -- which means that often deadzones need to be configured on a
199 /// per-device type basis). Using deadzones, stick motion at the extreme ends of the spectrum
200 /// can be filtered out and noise in these areas can effectively be eliminated this way.
201 ///
202 /// The default value for this property is 0.125.
203 /// </remarks>
204 /// <seealso cref="StickDeadzoneProcessor"/>
205 /// <seealso cref="AxisDeadzoneProcessor"/>
206 public float defaultDeadzoneMin
207 {
208 get => m_DefaultDeadzoneMin;
209 set
210 {
211 // ReSharper disable once CompareOfFloatsByEqualityOperator
212 if (m_DefaultDeadzoneMin == value)
213 return;
214 m_DefaultDeadzoneMin = value;
215 OnChange();
216 }
217 }
218
219 /// <summary>
220 /// Default value used when nothing is set explicitly on <see cref="StickDeadzoneProcessor.max"/>
221 /// or <see cref="AxisDeadzoneProcessor.max"/>.
222 /// </summary>
223 /// <value>Default upper limit for deadzones.</value>
224 /// <remarks>
225 /// "Deadzones" refer to limits established for the range of values accepted as input
226 /// on a control. If the value for the control falls outside the range, i.e. below the
227 /// given minimum or above the given maximum, the value is clamped to the respective
228 /// limit.
229 ///
230 /// This property configures the default upper bound of the value range.
231 ///
232 /// Note that deadzones will by default re-normalize values after clamping. This means that
233 /// inputs at the lower and upper end are dropped and that the range in-between is re-normalized
234 /// to [0..1].
235 ///
236 /// Note that deadzones preserve the sign of inputs. This means that both the upper and
237 /// the lower deadzone bound extend to both the positive and the negative range. For example,
238 /// a deadzone max of 0.95 will clamp values of >0.95 and <-0.95.
239 ///
240 /// The most common example of where deadzones are used are the sticks on gamepads, i.e.
241 /// <see cref="Gamepad.leftStick"/> and <see cref="Gamepad.rightStick"/>. Sticks will
242 /// usually be wobbly to some extent (just how wobbly varies greatly between different
243 /// types of controllers -- which means that often deadzones need to be configured on a
244 /// per-device type basis). Using deadzones, stick motion at the extreme ends of the spectrum
245 /// can be filtered out and noise in these areas can effectively be eliminated this way.
246 ///
247 /// The default value for this property is 0.925.
248 /// </remarks>
249 /// <seealso cref="StickDeadzoneProcessor"/>
250 /// <seealso cref="AxisDeadzoneProcessor"/>
251 public float defaultDeadzoneMax
252 {
253 get => m_DefaultDeadzoneMax;
254 set
255 {
256 // ReSharper disable once CompareOfFloatsByEqualityOperator
257 if (m_DefaultDeadzoneMax == value)
258 return;
259 m_DefaultDeadzoneMax = value;
260 OnChange();
261 }
262 }
263
264 /// <summary>
265 /// The default value threshold for when a button is considered pressed. Used if
266 /// no explicit thresholds are set on parameters such as <see cref="Controls.ButtonControl.pressPoint"/>
267 /// or <see cref="Interactions.PressInteraction.pressPoint"/>.
268 /// </summary>
269 /// <value>Default button press threshold.</value>
270 /// <remarks>
271 /// In the input system, each button constitutes a full floating-point value. Pure
272 /// toggle buttons, such as <see cref="Gamepad.buttonSouth"/> for example, will simply
273 /// alternate between 0 (not pressed) and 1 (pressed). However, buttons may also have
274 /// ranges, such as <see cref="Gamepad.leftTrigger"/> for example. When used in a context
275 /// where a clear distinction between pressed and not pressed is required, we need a value
276 /// beyond which we consider the button pressed.
277 ///
278 /// By setting this property, the default value for this can be configured. If a button
279 /// has a value equal to or greater than the button press point, it is considered pressed.
280 ///
281 /// The default value is 0.5.
282 ///
283 /// Any value will implicitly be clamped to <c>0.0001f</c> as allowing a value of 0 would
284 /// cause all buttons in their default state to already be pressed.
285 ///
286 /// Lowering the button press point will make triggers feel more like hair-triggers (akin
287 /// to using the hair-trigger feature on Xbox Elite controllers). However, it may make using
288 /// the directional buttons (i.e. <see cref="Controls.StickControl.up"/> etc) be fickle as
289 /// solely moving in only one direction with sticks isn't easy. To counteract that, the button
290 /// press points on the stick buttons can be raised.
291 ///
292 /// Another solution is to simply lower the press points on the triggers specifically.
293 ///
294 /// <example>
295 /// <code>
296 /// InputSystem.RegisterLayoutOverride(@"
297 /// {
298 /// ""name"" : ""HairTriggers"",
299 /// ""extend"" : ""Gamepad"",
300 /// ""controls"" [
301 /// { ""name"" : ""leftTrigger"", ""parameters"" : ""pressPoint=0.1"" },
302 /// { ""name"" : ""rightTrigger"", ""parameters"" : ""pressPoint=0.1"" }
303 /// ]
304 /// }
305 /// ");
306 /// </code>
307 /// </example>
308 /// </remarks>
309 /// <seealso cref="buttonReleaseThreshold"/>
310 /// <seealso cref="Controls.ButtonControl.pressPoint"/>
311 /// <seealso cref="Controls.ButtonControl.isPressed"/>
312 /// <seealso cref="Interactions.PressInteraction.pressPoint"/>
313 /// <seealso cref="Interactions.TapInteraction.pressPoint"/>
314 /// <seealso cref="Interactions.SlowTapInteraction.pressPoint"/>
315 /// <seealso cref="InputBindingCompositeContext.ReadValueAsButton"/>
316 public float defaultButtonPressPoint
317 {
318 get => m_DefaultButtonPressPoint;
319 set
320 {
321 // ReSharper disable once CompareOfFloatsByEqualityOperator
322 if (m_DefaultButtonPressPoint == value)
323 return;
324 m_DefaultButtonPressPoint = Mathf.Clamp(value, ButtonControl.kMinButtonPressPoint, float.MaxValue);
325 OnChange();
326 }
327 }
328
329 /// <summary>
330 /// The percentage of <see cref="defaultButtonPressPoint"/> at which a button that was pressed
331 /// is considered released again.
332 /// </summary>
333 /// <remarks>
334 /// This setting helps avoid flickering around the button press point by introducing something akin to a
335 /// "dead zone" below <see cref="defaultButtonPressPoint"/>. Once a button has been pressed to a magnitude
336 /// of at least <see cref="defaultButtonPressPoint"/>, it is considered pressed and keeps being considered pressed
337 /// until its magnitude falls back to a value of or below <see cref="buttonReleaseThreshold"/> percent of
338 /// <see cref="defaultButtonPressPoint"/>.
339 ///
340 /// This is a percentage rather than a fixed value so it allows computing release
341 /// points even when the press point has been customized. If, for example, a <see cref="Interactions.PressInteraction"/>
342 /// sets a custom <see cref="Interactions.PressInteraction.pressPoint"/>, the respective release point
343 /// can still be computed from the percentage set here.
344 /// </remarks>
345 public float buttonReleaseThreshold
346 {
347 get => m_ButtonReleaseThreshold;
348 set
349 {
350 // ReSharper disable once CompareOfFloatsByEqualityOperator
351 if (m_ButtonReleaseThreshold == value)
352 return;
353 m_ButtonReleaseThreshold = value;
354 OnChange();
355 }
356 }
357
358 /// <summary>
359 /// Default time (in seconds) within which a press and release has to occur for it
360 /// to be registered as a "tap".
361 /// </summary>
362 /// <value>Default upper limit on press durations for them to register as taps.</value>
363 /// <remarks>
364 /// A tap is considered as a quick press-and-release on a button-like input control.
365 /// This property determines just how quick the press-and-release has to be, i.e. what
366 /// the maximum time is that can elapse between the button being pressed and released
367 /// again. If the delay between press and release is greater than this time, the
368 /// input does not qualify as a tap.
369 ///
370 /// The default tap time is 0.2 seconds.
371 /// </remarks>
372 /// <seealso cref="Interactions.TapInteraction"/>
373 public float defaultTapTime
374 {
375 get => m_DefaultTapTime;
376 set
377 {
378 // ReSharper disable once CompareOfFloatsByEqualityOperator
379 if (m_DefaultTapTime == value)
380 return;
381 m_DefaultTapTime = value;
382 OnChange();
383 }
384 }
385
386 /// <summary>
387 /// Allows you to specify the default minimum duration required of a press-and-release interaction to evaluate to a slow-tap-interaction.
388 /// </summary>
389 /// <value>The default minimum duration that the button-like input control must remain in pressed state for the interaction to evaluate to a slow-tap-interaction.</value>
390 /// <remarks>
391 /// A slow-tap-interaction is considered as a press-and-release sequence on a button-like input control.
392 /// This property determines the lower bound of the duration that must elapse between the button being pressed and released again.
393 /// If the delay between press and release is less than this duration, the input does not qualify as a slow-tap-interaction.
394 ///
395 /// The default slow-tap time is 0.5 seconds.
396 /// </remarks>
397 /// <seealso cref="Interactions.SlowTapInteraction"/>
398 public float defaultSlowTapTime
399 {
400 get => m_DefaultSlowTapTime;
401 set
402 {
403 // ReSharper disable once CompareOfFloatsByEqualityOperator
404 if (m_DefaultSlowTapTime == value)
405 return;
406 m_DefaultSlowTapTime = value;
407 OnChange();
408 }
409 }
410
411 /// <summary>
412 /// Allows you to specify the default minimum duration required of a press-and-release interaction to evaluate to a hold-interaction.
413 /// </summary>
414 /// <value>The default minimum duration that the button-like input control must remain in pressed state for the interaction to evaluate to a hold-interaction.</value>
415 /// <remarks>
416 /// A hold-interaction is considered as a press-and-release sequence on a button-like input control.
417 /// This property determines the lower bound of the duration that must elapse between the button being pressed and released again.
418 /// If the delay between press and release is less than this duration, the input does not qualify as a hold-interaction.
419 ///
420 /// The default hold time is 0.4 seconds.
421 /// </remarks>
422 /// <seealso cref="Interactions.HoldInteraction"/>
423 public float defaultHoldTime
424 {
425 get => m_DefaultHoldTime;
426 set
427 {
428 // ReSharper disable once CompareOfFloatsByEqualityOperator
429 if (m_DefaultHoldTime == value)
430 return;
431 m_DefaultHoldTime = value;
432 OnChange();
433 }
434 }
435
436 /// <summary>
437 /// Allows you to specify the default maximum radius that a touch contact may be moved from its origin to evaluate to a tap-interaction.
438 /// </summary>
439 /// <value>The default maximum radius (in pixels) that a touch contact may be moved from its origin to evaluate to a tap-interaction.</value>
440 /// <remarks>
441 /// A tap-interaction or slow-tap-interaction is considered as a press-and-release sequence.
442 /// If the associated touch contact is moved a distance equal or greater to the value of this setting,
443 /// the input sequence do not qualify as a tap-interaction.
444 ///
445 /// The default tap-radius is 5 pixels.
446 /// </remarks>
447 /// <seealso cref="Interactions.TapInteraction"/>
448 /// <seealso cref="Interactions.SlowTapInteraction"/>
449 /// <seealso cref="Interactions.MultiTapInteraction"/>
450 public float tapRadius
451 {
452 get => m_TapRadius;
453 set
454 {
455 // ReSharper disable once CompareOfFloatsByEqualityOperator
456 if (m_TapRadius == value)
457 return;
458 m_TapRadius = value;
459 OnChange();
460 }
461 }
462
463 /// <summary>
464 /// Allows you to specify the maximum duration that may pass between taps in order to evaluate to a multi-tap-interaction.
465 /// </summary>
466 /// <value>The default maximum duration (in seconds) that may pass between taps in order to evaluate to a multi-tap-interaction.</value>
467 /// <remarks>
468 /// A multi-tap interaction is considered as multiple press-and-release sequences.
469 /// This property defines the maximum duration that may pass between these press-and-release sequences.
470 /// If consecutive taps (press-and-release sequences) occur with a inter-sequence duration exceeding
471 /// this property, the interaction do not qualify as a multi-tap-interaction.
472 ///
473 /// The default multi-tap delay time is 0.75 seconds.
474 /// </remarks>
475 /// <seealso cref="defaultTapTime"/>
476 public float multiTapDelayTime
477 {
478 get => m_MultiTapDelayTime;
479 set
480 {
481 // ReSharper disable once CompareOfFloatsByEqualityOperator
482 if (m_MultiTapDelayTime == value)
483 return;
484 m_MultiTapDelayTime = value;
485 OnChange();
486 }
487 }
488
489 /// <summary>
490 /// When <c>Application.runInBackground</c> is true, this property determines what happens when application focus changes
491 /// (see <a href="https://docs.unity3d.com/ScriptReference/Application-isFocused.html">Application.isFocused</a>) changes and how we handle
492 /// input while running the background.
493 /// </summary>
494 /// <value>What to do with input while not having focus. Set to <see cref="BackgroundBehavior.ResetAndDisableNonBackgroundDevices"/> by default.</value>
495 /// <remarks>
496 /// If <c>Application.runInBackground</c> is false, the value of this property is ignored. In that case, nothing happens when
497 /// focus is lost. However, when focus is regained, <see cref="InputSystem.TrySyncDevice"/> is called on all devices.
498 ///
499 /// Note that in the editor as well as in development standalone players, <c>Application.runInBackground</c> will effectively always be
500 /// turned on. The editor keeps the player loop running regardless of Game View focus for as long as the editor is active and in play mode
501 /// and development players will implicitly turn on the setting during the build process.
502 /// </remarks>
503 /// <seealso cref="InputSystem.ResetDevice"/>
504 /// <seealso cref="InputSystem.EnableDevice"/>
505 /// <seealso cref="InputDevice.canRunInBackground"/>
506 /// <seealso cref="editorInputBehaviorInPlayMode"/>
507 public BackgroundBehavior backgroundBehavior
508 {
509 get => m_BackgroundBehavior;
510 set
511 {
512 if (m_BackgroundBehavior == value)
513 return;
514 m_BackgroundBehavior = value;
515 OnChange();
516 }
517 }
518
519 /// <summary>
520 /// Determines how player focus is handled in the editor with respect to input.
521 /// </summary>
522 /// <remarks>
523 /// This setting only has an effect while in play mode (see <a href="https://docs.unity3d.com/ScriptReference/Application-isPlaying.html">Application.isPlaying</a>).
524 /// While not in play mode, all input is invariably routed to the editor.
525 ///
526 /// The editor generally treats Game View focus as equivalent to application focus (see <a href="https://docs.unity3d.com/ScriptReference/Application-isFocused.html">Application.isFocused</a>).
527 /// In other words, as long as any Game View has focus, the player is considered to have input focus. As soon as focus is transferred to a non-Game View
528 /// <c>EditorWindow</c> or the editor as a whole loses focus, the player is considered to have lost input focus.
529 ///
530 /// However, unlike in built players, the editor will keep running the player loop while in play mode regardless of whether a Game View is focused
531 /// or not. This essentially equates to <a href="https://docs.unity3d.com/ScriptReference/Application-runInBackground.html">Application.runInBackground</a> always
532 /// being true in the editor.
533 ///
534 /// To accommodate this behavior, this setting determines where input is routed while the player loop is running with no Game View being focused. As such,
535 /// it also dictates which input reaches the editor (if any) while the game is playing.
536 /// </remarks>
537 /// <seealso cref="backgroundBehavior"/>
538 public EditorInputBehaviorInPlayMode editorInputBehaviorInPlayMode
539 {
540 get => m_EditorInputBehaviorInPlayMode;
541 set
542 {
543 if (m_EditorInputBehaviorInPlayMode == value)
544 return;
545 m_EditorInputBehaviorInPlayMode = value;
546 OnChange();
547 }
548 }
549
550 /// <summary>
551 /// Determines how the Inspector window displays <see cref="InputActionProperty"/> fields.
552 /// </summary>
553 /// <seealso cref="InputActionPropertyDrawerMode"/>
554 public InputActionPropertyDrawerMode inputActionPropertyDrawerMode
555 {
556 get => m_InputActionPropertyDrawerMode;
557 set
558 {
559 if (m_InputActionPropertyDrawerMode == value)
560 return;
561 m_InputActionPropertyDrawerMode = value;
562 OnChange();
563 }
564 }
565
566 /// <summary>
567 /// Upper limit on the amount of bytes worth of <see cref="InputEvent"/>s processed in a single
568 /// <see cref="InputSystem.Update"/>.
569 /// </summary>
570 /// <remarks>
571 /// This setting establishes a bound on the amount of input event data processed in a single
572 /// update and thus limits throughput allowed for input. This prevents long stalls from
573 /// leading to long delays in input processing.
574 ///
575 /// When the limit is exceeded, all events remaining in the buffer are thrown away (the
576 /// <see cref="InputEventBuffer"/> is reset) and an error is logged. After that, the current
577 /// update will abort and early out.
578 ///
579 /// Setting this property to 0 or a negative value will disable the limit.
580 ///
581 /// The default value is 5MB.
582 /// </remarks>
583 /// <seealso cref="InputSystem.Update"/>
584 /// <see cref="InputEvent.sizeInBytes"/>
585 public int maxEventBytesPerUpdate
586 {
587 get => m_MaxEventBytesPerUpdate;
588 set
589 {
590 if (m_MaxEventBytesPerUpdate == value)
591 return;
592 m_MaxEventBytesPerUpdate = value;
593 OnChange();
594 }
595 }
596
597 /// <summary>
598 /// Upper limit on the number of <see cref="InputEvent"/>s that can be queued within one
599 /// <see cref="InputSystem.Update"/>.
600 /// <remarks>
601 /// This settings establishes an upper limit on the number of events that can be queued
602 /// using <see cref="InputSystem.QueueEvent"/> during a single update. This prevents infinite
603 /// loops where an action callback queues an event that causes the action callback to
604 /// be called again which queues an event...
605 ///
606 /// Note that this limit only applies while the input system is updating. There is no limit
607 /// on the number of events that can be queued outside of this time, but those will be queued
608 /// into the next frame where the <see cref="maxEventBytesPerUpdate"/> setting will apply.
609 ///
610 /// The default value is 1000.
611 /// </remarks>
612 /// </summary>
613 public int maxQueuedEventsPerUpdate
614 {
615 get => m_MaxQueuedEventsPerUpdate;
616 set
617 {
618 if (m_MaxQueuedEventsPerUpdate == value)
619 return;
620
621 m_MaxQueuedEventsPerUpdate = value;
622 OnChange();
623 }
624 }
625
626 /// <summary>
627 /// List of device layouts used by the project.
628 /// </summary>
629 /// <remarks>
630 /// This would usually be one of the high-level abstract device layouts. For example, for
631 /// a game that supports touch, gamepad, and keyboard&mouse, the list would be
632 /// <c>{ "Touchscreen", "Gamepad", "Mouse", "Keyboard" }</c>. However, nothing prevents the
633 /// the user from adding something a lot more specific. A game that can only be played
634 /// with a DualShock controller could make this list just be <c>{ "DualShockGamepad" }</c>,
635 /// for example.
636 ///
637 /// In the editor, we use the information to filter what we display to the user by automatically
638 /// filtering out irrelevant controls in the control picker and such.
639 ///
640 /// The information is also used when a new device is discovered. If the device is not listed
641 /// as supported by the project, it is ignored.
642 ///
643 /// The list is empty by default. An empty list indicates that no restrictions are placed on what
644 /// devices are supported. In this editor, this means that all possible devices and controls are
645 /// shown.
646 /// </remarks>
647 /// <seealso cref="InputControlLayout"/>
648 public ReadOnlyArray<string> supportedDevices
649 {
650 get => new ReadOnlyArray<string>(m_SupportedDevices);
651 set
652 {
653 // Detect if there was a change.
654 if (supportedDevices.Count == value.Count)
655 {
656 var hasChanged = false;
657 for (var i = 0; i < supportedDevices.Count; ++i)
658 if (m_SupportedDevices[i] != value[i])
659 {
660 hasChanged = true;
661 break;
662 }
663
664 if (!hasChanged)
665 return;
666 }
667
668 m_SupportedDevices = value.ToArray();
669 OnChange();
670 }
671 }
672
673 /// <summary>
674 /// Disables merging of redundant input events (at the moment, only mouse events).
675 /// Disable it if you want to get all events.
676 /// </summary>
677 /// <remarks>
678 /// When using a high frequency mouse, the number of mouse move events in each frame can be
679 /// very large, which can have a negative effect on performance. To help with this,
680 /// merging events can be used which coalesces consecutive mouse move events into a single
681 /// input action update.
682 ///
683 /// For example, if there are one hundred mouse events, but they are all position updates
684 /// with no clicks, and there is an input action callback handler for the mouse position, that
685 /// callback handler will only be called one time in the current frame. Delta and scroll
686 /// values for the mouse will still be accumulated across all mouse events.
687 /// </remarks>
688 public bool disableRedundantEventsMerging
689 {
690 get => m_DisableRedundantEventsMerging;
691 set
692 {
693 if (m_DisableRedundantEventsMerging == value)
694 return;
695
696 m_DisableRedundantEventsMerging = value;
697 OnChange();
698 }
699 }
700
701 /// <summary>
702 /// Improves shortcut key support by making composite controls consume control input
703 /// </summary>
704 /// <remarks>
705 /// Actions are exclusively triggered and will consume/block other actions sharing the same input.
706 /// E.g. when pressing the 'Shift+B' keys, the associated action would trigger but any action bound to just the 'B' key would be prevented from triggering at the same time.
707 /// Please note that enabling this will cause actions with composite bindings to consume input and block any other actions which are enabled and sharing the same controls.
708 /// Input consumption is performed in priority order, with the action containing the greatest number of bindings checked first.
709 /// Therefore actions requiring fewer keypresses will not be triggered if an action using more keypresses is triggered and has overlapping controls.
710 /// This works for shortcut keys, however in other cases this might not give the desired result, especially where there are actions with the exact same number of composite controls, in which case it is non-deterministic which action will be triggered.
711 /// These conflicts may occur even between actions which belong to different Action Maps e.g. if using an UIInputModule with the Arrow Keys bound to the Navigate Action in the UI Action Map, this would interfere with other Action Maps using those keys.
712 /// However conflicts would not occur between actions which belong to different Action Assets.
713 /// </remarks>
714 public bool shortcutKeysConsumeInput
715 {
716 get => m_ShortcutKeysConsumeInputs;
717 set
718 {
719 if (m_ShortcutKeysConsumeInputs == value)
720 return;
721
722 m_ShortcutKeysConsumeInputs = value;
723 OnChange();
724 }
725 }
726
727 /// <summary>
728 /// Enable or disable an internal feature by its name.
729 /// </summary>
730 /// <param name="featureName">Name of the feature.</param>
731 /// <param name="enabled">Whether to enable or disable the feature.</param>
732 /// <exception cref="ArgumentNullException"><paramref name="featureName"/> is <c>null</c> or empty.</exception>
733 /// <remarks>
734 /// This method is intended for experimental features. These must be enabled/disabled from code.
735 /// Setting or unsetting a feature flag will not be persisted in an <c>.inputsettings</c> file.
736 /// </remarks>
737 public void SetInternalFeatureFlag(string featureName, bool enabled)
738 {
739 if (string.IsNullOrEmpty(featureName))
740 throw new ArgumentNullException(nameof(featureName));
741
742 if (m_FeatureFlags == null)
743 m_FeatureFlags = new HashSet<string>();
744
745 if (enabled)
746 m_FeatureFlags.Add(featureName.ToUpperInvariant());
747 else
748 m_FeatureFlags.Remove(featureName.ToUpperInvariant());
749
750 OnChange();
751 }
752
753 [Tooltip("Determine which type of devices are used by the application. By default, this is empty meaning that all devices recognized "
754 + "by Unity will be used. Restricting the set of supported devices will make only those devices appear in the input system.")]
755 [SerializeField] private string[] m_SupportedDevices;
756 [Tooltip("Determine when Unity processes events. By default, accumulated input events are flushed out before each fixed update and "
757 + "before each dynamic update. This setting can be used to restrict event processing to only where the application needs it.")]
758 [SerializeField] private UpdateMode m_UpdateMode = UpdateMode.ProcessEventsInDynamicUpdate;
759 [SerializeField] private ScrollDeltaBehavior m_ScrollDeltaBehavior = ScrollDeltaBehavior.UniformAcrossAllPlatforms;
760 [SerializeField] private int m_MaxEventBytesPerUpdate = 5 * 1024 * 1024;
761 [SerializeField] private int m_MaxQueuedEventsPerUpdate = 1000;
762
763 [SerializeField] private bool m_CompensateForScreenOrientation = true;
764 [SerializeField] private BackgroundBehavior m_BackgroundBehavior = BackgroundBehavior.ResetAndDisableNonBackgroundDevices;
765 [SerializeField] private EditorInputBehaviorInPlayMode m_EditorInputBehaviorInPlayMode;
766 [SerializeField] private InputActionPropertyDrawerMode m_InputActionPropertyDrawerMode = InputActionPropertyDrawerMode.Compact;
767 [SerializeField] private float m_DefaultDeadzoneMin = 0.125f;
768 [SerializeField] private float m_DefaultDeadzoneMax = 0.925f;
769 // A setting of 0.5 seems to roughly be what games generally use on the gamepad triggers.
770 // Having a higher value here also obsoletes the need for custom press points on stick buttons
771 // (the up/down/left/right ones).
772 [Min(ButtonControl.kMinButtonPressPoint)]
773 [SerializeField] private float m_DefaultButtonPressPoint = 0.5f;
774 [SerializeField] private float m_ButtonReleaseThreshold = 0.75f;
775 [SerializeField] private float m_DefaultTapTime = 0.2f;
776 [SerializeField] private float m_DefaultSlowTapTime = 0.5f;
777 [SerializeField] private float m_DefaultHoldTime = 0.4f;
778 [SerializeField] private float m_TapRadius = 5;
779 [SerializeField] private float m_MultiTapDelayTime = 0.75f;
780 [SerializeField] private bool m_DisableRedundantEventsMerging = false;
781 [SerializeField] private bool m_ShortcutKeysConsumeInputs = false; // This is the shortcut support from v1.4. Temporarily moved here as an opt-in feature, while it's issues are investigated.
782
783 [NonSerialized] internal HashSet<string> m_FeatureFlags;
784
785 internal bool IsFeatureEnabled(string featureName)
786 {
787 return m_FeatureFlags != null && m_FeatureFlags.Contains(featureName.ToUpperInvariant());
788 }
789
790 internal void OnChange()
791 {
792 if (InputSystem.settings == this)
793 InputSystem.s_Manager.ApplySettings();
794 }
795
796 internal const int s_OldUnsupportedFixedAndDynamicUpdateSetting = 0;
797
798 /// <summary>
799 /// How the input system should update.
800 /// </summary>
801 /// <remarks>
802 /// By default, the input system will run event processing as part of the player loop. In the default configuration,
803 /// the processing will happens once before every every dynamic update (<a href="https://docs.unity3d.com/ScriptReference/MonoBehaviour.Update.html">Update</a>),
804 /// i.e. <see cref="ProcessEventsInDynamicUpdate"/> is the default behavior.
805 ///
806 /// There are two types of updates not governed by UpdateMode. One is <see cref="InputUpdateType.Editor"/> which
807 /// will always be enabled in the editor and govern input updates for <see cref="UnityEditor.EditorWindow"/>s in
808 /// sync to <see cref="UnityEditor.EditorApplication.update"/>.
809 ///
810 /// The other update type is <see cref="InputUpdateType.BeforeRender"/>. This type of update is enabled and disabled
811 /// automatically in response to whether devices are present requiring this type of update (<see
812 /// cref="InputDevice.updateBeforeRender"/>). This update does not consume extra state.
813 /// </remarks>
814 /// <seealso cref="InputSystem.Update"/>
815 /// <seealso cref="InputUpdateType"/>
816 /// <seealso href="https://docs.unity3d.com/ScriptReference/MonoBehaviour.FixedUpdate.html"/>
817 /// <seealso href="https://docs.unity3d.com/ScriptReference/MonoBehaviour.Update.html"/>
818 public enum UpdateMode
819 {
820 // Removed: ProcessEventsInBothFixedAndDynamicUpdate=0
821
822 /// <summary>
823 /// Automatically run input updates right before every <a href="https://docs.unity3d.com/ScriptReference/MonoBehaviour.Update.html">Update</a>.
824 ///
825 /// In this mode, no processing happens specifically for fixed updates. Querying input state in
826 /// <a href="https://docs.unity3d.com/ScriptReference/MonoBehaviour.FixedUpdate.html">FixedUpdate</a> will result in errors being logged in the editor and in
827 /// development builds. In release player builds, the value of the dynamic update state is returned.
828 /// </summary>
829 ProcessEventsInDynamicUpdate = 1,
830
831 /// <summary>
832 /// Automatically input run updates right before every <a href="https://docs.unity3d.com/ScriptReference/MonoBehaviour.FixedUpdate.html">FixedUpdate</a>.
833 ///
834 /// In this mode, no processing happens specifically for dynamic updates. Querying input state in
835 /// <a href="https://docs.unity3d.com/ScriptReference/MonoBehaviour.Update.html">Update</a> will result in errors being logged in the editor and in
836 /// development builds. In release player builds, the value of the fixed update state is returned.
837 /// </summary>
838 ProcessEventsInFixedUpdate,
839
840 /// <summary>
841 /// Do not run updates automatically. In this mode, <see cref="InputSystem.Update"/> must be called
842 /// manually to update input.
843 ///
844 /// This mode is most useful for placing input updates in the frame explicitly at an exact location.
845 ///
846 /// Note that failing to call <see cref="InputSystem.Update"/> may result in a lot of events
847 /// accumulating or some input getting lost.
848 /// </summary>
849 ProcessEventsManually,
850 }
851
852 /// <summary>
853 /// How platform-specific input should be converted when returning delta values for scroll wheel input actions.
854 /// </summary>
855 public enum ScrollDeltaBehavior
856 {
857 /// <summary>
858 /// The range used for the delta is converted to be uniform across all platforms.
859 /// </summary>
860 /// <remarks>
861 /// The resulting range will be [-1, 1] regardless of the platform used.
862 /// </remarks>
863 UniformAcrossAllPlatforms = 0,
864
865 /// <summary>
866 /// The range used for the delta is the same as returned by the platform input.
867 /// </summary>
868 /// <remarks>
869 /// The range will typically be [-120, 120] on Windows and [-1, 1] on MacOS and Linux.
870 /// Other platforms may have different ranges.
871 /// </remarks>
872 KeepPlatformSpecificInputRange = 1
873 }
874
875 /// <summary>
876 /// Determines how the applications behaves when running in the background. See <see cref="backgroundBehavior"/>.
877 /// </summary>
878 /// <seealso href="https://docs.unity3d.com/ScriptReference/Application-isFocused.html"/>
879 /// <seealso href="https://docs.unity3d.com/ScriptReference/Application-runInBackground.html"/>
880 /// <seealso cref="backgroundBehavior"/>
881 /// <seealso cref="InputSettings.editorInputBehaviorInPlayMode"/>
882 public enum BackgroundBehavior
883 {
884 /// <summary>
885 /// When the application loses focus, issue a <see cref="InputSystem.ResetDevice"/> call on every <see cref="InputDevice"/> that is
886 /// not marked as <see cref="InputDevice.canRunInBackground"/> and then disable the device (see <see cref="InputSystem.DisableDevice"/>
887 /// and <see cref="InputDevice.enabled"/>). Devices that <see cref="InputDevice.canRunInBackground"/> will not be touched and will
888 /// keep running as is.
889 ///
890 /// In effect, this setting will "soft-reset" all devices that cannot receive input while the application does
891 /// not have focus. That is, it will reset all controls that are not marked as <see cref="InputControlLayout.ControlItem.dontReset"/>
892 /// to their default state.
893 ///
894 /// When the application comes back into focus, all devices that have been reset and disabled will be re-enabled and a synchronization
895 /// request (see <see cref="RequestSyncCommand"/>) will be sent to each device.
896 ///
897 /// Devices that are added while the application is running in the background are treated like devices that were already present
898 /// when losing focus. That is, if they cannot run in the background, they will be disabled until focus comes back.
899 ///
900 /// Note that the resets will cancel <see cref="InputAction"/>s that are in progress from controls on devices that are being reset.
901 /// </summary>
902 ResetAndDisableNonBackgroundDevices = 0,
903
904 /// <summary>
905 /// Like <see cref="ResetAndDisableNonBackgroundDevices"/> but instead treat all devices as having <see cref="InputDevice.canRunInBackground"/>
906 /// return false. This effectively means that all input is silenced while the application is running in the background.
907 /// </summary>
908 ResetAndDisableAllDevices = 1,
909
910 /// <summary>
911 /// Ignore all changes in focus and leave devices untouched. This also disables focus checks in <see cref="UI.InputSystemUIInputModule"/>.
912 /// </summary>
913 IgnoreFocus = 2,
914 }
915
916 /// <summary>
917 /// Determines how player focus is handled with respect to input when we are in play mode in the editor.
918 /// See <see cref="InputSettings.editorInputBehaviorInPlayMode"/>. The setting does not have an effect
919 /// when the editor is not in play mode.
920 /// </summary>
921 public enum EditorInputBehaviorInPlayMode
922 {
923 /// <summary>
924 /// When the game view does not have focus, input from <see cref="Pointer"/> devices (such as <see cref="Mouse"/> and <see cref="Touchscreen"/>)
925 /// is routed to the editor and not visible in player code. Input from devices such as <see cref="Gamepad"/>s will continue to
926 /// go to the game regardless of which <c>EditorWindow</c> is focused.
927 ///
928 /// This is the default. It makes sure that the devices that are used with the editor UI respect <c>EditorWindow</c> focus and thus
929 /// do not lead to accidental inputs affecting the game. While at the same time letting all other input get through to the game.
930 /// It does, however, mean that no other <c>EditorWindow</c> can tap input from these devices (such as <see cref="Gamepad"/>s and <see cref="HID"/>s).
931 /// </summary>
932 PointersAndKeyboardsRespectGameViewFocus,
933
934 /// <summary>
935 /// When the game view does not have focus, all input is routed to the editor (and thus <c>EditorWindow</c>s). No input
936 /// is received in the game regardless of the type of device generating it.
937 /// </summary>
938 AllDevicesRespectGameViewFocus,
939
940 /// <summary>
941 /// All input is going to the game at all times. This most closely aligns input behavior in the editor with that in players. <see cref="backgroundBehavior"/>
942 /// will be respected as in the player and devices may thus be disabled in the runtime based on Game View focus.
943 /// </summary>
944 AllDeviceInputAlwaysGoesToGameView,
945 }
946
947 /// <summary>
948 /// Determines how the Inspector window displays <see cref="InputActionProperty"/> fields.
949 /// </summary>
950 /// <seealso cref="inputActionPropertyDrawerMode"/>
951 public enum InputActionPropertyDrawerMode
952 {
953 /// <summary>
954 /// Display the property in a compact format, using a minimal number of lines.
955 /// Toggling between a reference to an input action in an asset and a directly serialized input action
956 /// is done using a dropdown menu.
957 /// </summary>
958 Compact,
959
960 /// <summary>
961 /// Display the effective action underlying the property, using multiple lines.
962 /// Toggling between a reference to an input action in an asset and a directly serialized input action
963 /// is done using a property that is always visible.
964 /// </summary>
965 /// <remarks>
966 /// This mode could be useful if you want to see or revert prefab overrides and hide the field that is ignored.
967 /// </remarks>
968 MultilineEffective,
969
970 /// <summary>
971 /// Display both the input action and external reference underlying the property.
972 /// Toggling between a reference to an input action in an asset and a directly serialized input action
973 /// is done using a property that is always visible.
974 /// </summary>
975 /// <remarks>
976 /// This mode could be useful if you want to see both values of the property without needing to toggle Use Reference.
977 /// </remarks>
978 MultilineBoth,
979 }
980
981 private static bool CompareFloats(float a, float b)
982 {
983 return (a - b) <= float.Epsilon;
984 }
985
986 private static bool CompareSets<T>(ReadOnlyArray<T> a, ReadOnlyArray<T> b)
987 {
988 if (ReferenceEquals(null, a))
989 return ReferenceEquals(null, b);
990 if (ReferenceEquals(null, b))
991 return false;
992 for (var i = 0; i < a.Count; ++i)
993 {
994 bool existsInB = false;
995 for (var j = 0; j < b.Count; ++j)
996 {
997 if (a[i].Equals(b[j]))
998 {
999 existsInB = true;
1000 break;
1001 }
1002 }
1003
1004 if (!existsInB)
1005 return false;
1006 }
1007
1008 return true;
1009 }
1010
1011 private static bool CompareFeatureFlag(InputSettings a, InputSettings b, string featureName)
1012 {
1013 return a.IsFeatureEnabled(featureName) == b.IsFeatureEnabled(featureName);
1014 }
1015
1016 internal static bool AreEqual(InputSettings a, InputSettings b)
1017 {
1018 if (ReferenceEquals(null, a))
1019 return ReferenceEquals(null, b);
1020 if (ReferenceEquals(null, b))
1021 return false;
1022 if (ReferenceEquals(a, b))
1023 return true;
1024
1025 return (a.updateMode == b.updateMode) &&
1026 (a.compensateForScreenOrientation == b.compensateForScreenOrientation) &&
1027 // Ignoring filterNoiseOnCurrent since deprecated
1028 CompareFloats(a.defaultDeadzoneMin, b.defaultDeadzoneMin) &&
1029 CompareFloats(a.defaultDeadzoneMax, b.defaultDeadzoneMax) &&
1030 CompareFloats(a.defaultButtonPressPoint, b.defaultButtonPressPoint) &&
1031 CompareFloats(a.buttonReleaseThreshold, b.buttonReleaseThreshold) &&
1032 CompareFloats(a.defaultTapTime, b.defaultTapTime) &&
1033 CompareFloats(a.defaultSlowTapTime, b.defaultSlowTapTime) &&
1034 CompareFloats(a.defaultHoldTime, b.defaultHoldTime) &&
1035 CompareFloats(a.tapRadius, b.tapRadius) &&
1036 CompareFloats(a.multiTapDelayTime, b.multiTapDelayTime) &&
1037 a.backgroundBehavior == b.backgroundBehavior &&
1038 a.editorInputBehaviorInPlayMode == b.editorInputBehaviorInPlayMode &&
1039 a.inputActionPropertyDrawerMode == b.inputActionPropertyDrawerMode &&
1040 a.maxEventBytesPerUpdate == b.maxEventBytesPerUpdate &&
1041 a.maxQueuedEventsPerUpdate == b.maxQueuedEventsPerUpdate &&
1042 CompareSets(a.supportedDevices, b.supportedDevices) &&
1043 a.disableRedundantEventsMerging == b.disableRedundantEventsMerging &&
1044 a.shortcutKeysConsumeInput == b.shortcutKeysConsumeInput &&
1045
1046 CompareFeatureFlag(a, b, InputFeatureNames.kUseOptimizedControls) &&
1047 CompareFeatureFlag(a, b, InputFeatureNames.kUseReadValueCaching) &&
1048 CompareFeatureFlag(a, b, InputFeatureNames.kParanoidReadValueCachingChecks) &&
1049 CompareFeatureFlag(a, b, InputFeatureNames.kDisableUnityRemoteSupport) &&
1050 CompareFeatureFlag(a, b, InputFeatureNames.kRunPlayerUpdatesInEditMode) &&
1051#if UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
1052 CompareFeatureFlag(a, b, InputFeatureNames.kUseIMGUIEditorForAssets);
1053#else
1054 true; // Improves formatting
1055#endif
1056 }
1057 }
1058}