A game about forced loneliness, made by TACStudios
1using System;
2using UnityEngine.InputSystem.Controls;
3using UnityEngine.InputSystem.Layouts;
4using UnityEngine.InputSystem.LowLevel;
5using UnityEngine.InputSystem.Utilities;
6
7////TODO: make the sensors return values through their device
8//// (e.g. GravitySensor should itself be an InputControl returning a Vector3 value which is the gravity value)
9
10////REVIEW: Is there a better way than having all the sensor classes?
11
12namespace UnityEngine.InputSystem.LowLevel
13{
14 internal struct AccelerometerState : IInputStateTypeInfo
15 {
16 public static FourCC kFormat => new FourCC('A', 'C', 'C', 'L');
17
18 [InputControl(displayName = "Acceleration", processors = "CompensateDirection", noisy = true)]
19 public Vector3 acceleration;
20
21 public FourCC format => kFormat;
22 }
23
24 internal struct GyroscopeState : IInputStateTypeInfo
25 {
26 public static FourCC kFormat => new FourCC('G', 'Y', 'R', 'O');
27
28 [InputControl(displayName = "Angular Velocity", processors = "CompensateDirection", noisy = true)]
29 public Vector3 angularVelocity;
30
31 public FourCC format => kFormat;
32 }
33
34 internal struct GravityState : IInputStateTypeInfo
35 {
36 public static FourCC kFormat => new FourCC('G', 'R', 'V', ' ');
37
38 [InputControl(displayName = "Gravity", processors = "CompensateDirection", noisy = true)]
39 public Vector3 gravity;
40
41 public FourCC format => kFormat;
42 }
43
44 internal struct AttitudeState : IInputStateTypeInfo
45 {
46 public static FourCC kFormat => new FourCC('A', 'T', 'T', 'D');
47
48 [InputControl(displayName = "Attitude", processors = "CompensateRotation", noisy = true)]
49 public Quaternion attitude;
50
51 public FourCC format => kFormat;
52 }
53
54 internal struct LinearAccelerationState : IInputStateTypeInfo
55 {
56 public static FourCC kFormat => new FourCC('L', 'A', 'A', 'C');
57
58 [InputControl(displayName = "Acceleration", processors = "CompensateDirection", noisy = true)]
59 public Vector3 acceleration;
60
61 public FourCC format => kFormat;
62 }
63}
64
65namespace UnityEngine.InputSystem
66{
67 /// <summary>
68 /// Base class representing any sensor kind of input device.
69 /// </summary>
70 /// <remarks>
71 /// Sensors represent device environmental sensors, such as <see cref="Accelerometer"/>s, <see cref="Gyroscope"/>s,
72 /// <see cref="GravitySensor"/>s and others.
73 ///
74 /// Unlike other devices, sensor devices usually start out in a disabled state in order to reduce energy
75 /// consumption (i.e. preserve battery life) when the sensors are not in fact used. To enable a specific sensor,
76 /// call <see cref="InputSystem.EnableDevice"/> on the device instance.
77 ///
78 /// <example>
79 /// <code>
80 /// // Enable the gyroscope.
81 /// InputSystem.EnableDevice(Gyroscope.current);
82 /// </code>
83 /// </example>
84 ///
85 /// Sensors are usually sampled automatically by the platform at regular intervals. For example, if a sensor
86 /// is sampled at 50Hz, the platform will queue an event with an update at a rate of roughly 50 events per
87 /// second. The default sampling rate for a sensor is usually platform-specific. A custom sampling frequency
88 /// can be set through <see cref="samplingFrequency"/> but be aware that there may be limitations for how fast
89 /// a given sensor can be sampled.
90 /// </remarks>
91 [InputControlLayout(isGenericTypeOfDevice = true)]
92 public class Sensor : InputDevice
93 {
94 /// <summary>
95 /// The frequency (in Hertz) at which the underlying sensor will be refreshed and at which update
96 /// events for it will be queued.
97 /// </summary>
98 /// <value>Times per second at which the sensor is refreshed.</value>
99 /// <remarks>
100 /// Note that when setting sampling frequencies, there may be limits on the range of frequencies
101 /// supported by the underlying hardware/platform.
102 ///
103 /// To support querying sampling frequencies, a sensor device must implement <see cref="QuerySamplingFrequencyCommand"/>.
104 /// To support setting frequencies, it must implemenet <see cref="SetSamplingFrequencyCommand"/>.
105 /// </remarks>
106 /// <exception cref="NotSupportedException">Thrown when reading the property and the underlying
107 /// sensor does not support querying of sampling frequencies.</exception>
108 public float samplingFrequency
109 {
110 get
111 {
112 var command = QuerySamplingFrequencyCommand.Create();
113 if (ExecuteCommand(ref command) >= 0)
114 return command.frequency;
115 throw new NotSupportedException($"Device '{this}' does not support querying sampling frequency");
116 }
117 set
118 {
119 ////REVIEW: should this throw NotSupportedException, too?
120 var command = SetSamplingFrequencyCommand.Create(value);
121 ExecuteCommand(ref command);
122 }
123 }
124 }
125
126 /// <summary>
127 /// Input device representing an accelerometer sensor.
128 /// </summary>
129 /// <remarks>
130 /// An accelerometer let's you measure the acceleration of a device, and can be useful to control content by moving a device around.
131 /// Note that the accelerometer will report the acceleration measured on a device both due to moving the device around, and due gravity
132 /// pulling the device down. You can use <see cref="GravitySensor"/> and <see cref="LinearAccelerationSensor"/> to get decoupled values
133 /// for these.
134 ///
135 /// <example>
136 /// <code>
137 /// class MyBehavior : MonoBehaviour
138 /// {
139 /// protected void OnEnable()
140 /// {
141 /// // All sensors start out disabled so they have to manually be enabled first.
142 /// InputSystem.EnableDevice(Accelerometer.current);
143 /// }
144 ///
145 /// protected void OnDisable()
146 /// {
147 /// InputSystem.DisableDevice(Accelerometer.current);
148 /// }
149 ///
150 /// protected void Update()
151 /// {
152 /// var acceleration = Accelerometer.current.acceleration.ReadValue();
153 /// //...
154 /// }
155 /// }
156 /// </code>
157 /// </example>
158 /// </remarks>
159 [InputControlLayout(stateType = typeof(AccelerometerState))]
160 public class Accelerometer : Sensor
161 {
162 public Vector3Control acceleration { get; protected set; }
163
164 /// <summary>
165 /// The accelerometer that was last added or had activity last.
166 /// </summary>
167 /// <value>Current accelerometer or <c>null</c>.</value>
168 public static Accelerometer current { get; private set; }
169
170 /// <inheritdoc />
171 public override void MakeCurrent()
172 {
173 base.MakeCurrent();
174 current = this;
175 }
176
177 /// <inheritdoc />
178 protected override void OnRemoved()
179 {
180 base.OnRemoved();
181 if (current == this)
182 current = null;
183 }
184
185 /// <inheritdoc />
186 protected override void FinishSetup()
187 {
188 acceleration = GetChildControl<Vector3Control>("acceleration");
189 base.FinishSetup();
190 }
191 }
192
193 /// <summary>
194 /// Input device representing a gyroscope sensor.
195 /// </summary>
196 /// <remarks>
197 /// A gyroscope lets you measure the angular velocity of a device, and can be useful to control content by rotating a device.
198 /// </remarks>
199 [InputControlLayout(stateType = typeof(GyroscopeState))]
200 public class Gyroscope : Sensor
201 {
202 public Vector3Control angularVelocity { get; protected set; }
203
204 /// <summary>
205 /// The gyroscope that was last added or had activity last.
206 /// </summary>
207 /// <value>Current gyroscope or <c>null</c>.</value>
208 public static Gyroscope current { get; private set; }
209
210 /// <inheritdoc />
211 public override void MakeCurrent()
212 {
213 base.MakeCurrent();
214 current = this;
215 }
216
217 /// <inheritdoc />
218 protected override void OnRemoved()
219 {
220 base.OnRemoved();
221 if (current == this)
222 current = null;
223 }
224
225 /// <inheritdoc />
226 protected override void FinishSetup()
227 {
228 angularVelocity = GetChildControl<Vector3Control>("angularVelocity");
229 base.FinishSetup();
230 }
231 }
232
233 /// <summary>
234 /// Input device representing a gravity sensor.
235 /// </summary>
236 /// <remarks>
237 /// A gravity sensor let's you determine the direction of the gravity vector relative to a device, and can be useful to control content by device orientation.
238 /// This is usually derived from a hardware <see cref="Accelerometer"/>, by subtracting the effect of linear acceleration (see <see cref="LinearAccelerationSensor"/>).
239 /// </remarks>
240 [InputControlLayout(stateType = typeof(GravityState), displayName = "Gravity")]
241 public class GravitySensor : Sensor
242 {
243 public Vector3Control gravity { get; protected set; }
244
245 /// <summary>
246 /// The gravity sensor that was last added or had activity last.
247 /// </summary>
248 /// <value>Current gravity sensor or <c>null</c>.</value>
249 public static GravitySensor current { get; private set; }
250
251 /// <inheritdoc />
252 protected override void FinishSetup()
253 {
254 gravity = GetChildControl<Vector3Control>("gravity");
255 base.FinishSetup();
256 }
257
258 /// <inheritdoc />
259 public override void MakeCurrent()
260 {
261 base.MakeCurrent();
262 current = this;
263 }
264
265 /// <inheritdoc />
266 protected override void OnRemoved()
267 {
268 base.OnRemoved();
269 if (current == this)
270 current = null;
271 }
272 }
273
274 //// REVIEW: Is this name good enough, possible other name RotationVector, here's how Android docs describe it. "A rotation vector sensor reports the orientation of the device relative to the East-North-Up coordinates frame."
275 //// This is the same as https://docs.unity3d.com/ScriptReference/Gyroscope-attitude.html
276 /// <summary>
277 /// Input device representing an attitude sensor.
278 /// </summary>
279 /// <remarks>
280 /// An attitude sensor let's you determine the orientation of a device, and can be useful to control content by rotating a device.
281 /// </remarks>
282 [InputControlLayout(stateType = typeof(AttitudeState), displayName = "Attitude")]
283 public class AttitudeSensor : Sensor
284 {
285 public QuaternionControl attitude { get; protected set; }
286
287 /// <summary>
288 /// The attitude sensor that was last added or had activity last.
289 /// </summary>
290 /// <value>Current attitude sensor or <c>null</c>.</value>
291 public static AttitudeSensor current { get; private set; }
292
293 /// <inheritdoc />
294 public override void MakeCurrent()
295 {
296 base.MakeCurrent();
297 current = this;
298 }
299
300 /// <inheritdoc />
301 protected override void OnRemoved()
302 {
303 base.OnRemoved();
304 if (current == this)
305 current = null;
306 }
307
308 /// <inheritdoc />
309 protected override void FinishSetup()
310 {
311 attitude = GetChildControl<QuaternionControl>("attitude");
312 base.FinishSetup();
313 }
314 }
315
316 /// <summary>
317 /// Input device representing linear acceleration affecting the device playing the content.
318 /// </summary>
319 /// <remarks>
320 /// An accelerometer let's you measure the acceleration of a device, and can be useful to control content by moving a device around.
321 /// Linear acceleration is the acceleration of a device unaffected by gravity forces.
322 /// This is usually derived from a hardware <see cref="Accelerometer"/>, by subtracting the effect of gravity (see <see cref="GravitySensor"/>).
323 /// </remarks>
324 [InputControlLayout(stateType = typeof(LinearAccelerationState), displayName = "Linear Acceleration")]
325 public class LinearAccelerationSensor : Sensor
326 {
327 public Vector3Control acceleration { get; protected set; }
328
329 /// <summary>
330 /// The linear acceleration sensor that was last added or had activity last.
331 /// </summary>
332 /// <value>Current linear acceleration sensor or <c>null</c>.</value>
333 public static LinearAccelerationSensor current { get; private set; }
334
335 /// <inheritdoc />
336 public override void MakeCurrent()
337 {
338 base.MakeCurrent();
339 current = this;
340 }
341
342 /// <inheritdoc />
343 protected override void OnRemoved()
344 {
345 base.OnRemoved();
346 if (current == this)
347 current = null;
348 }
349
350 /// <inheritdoc />
351 protected override void FinishSetup()
352 {
353 acceleration = GetChildControl<Vector3Control>("acceleration");
354 base.FinishSetup();
355 }
356 }
357
358 /// <summary>
359 /// Input device representing the magnetic field affecting the device playing the content.
360 /// </summary>
361 [InputControlLayout(displayName = "Magnetic Field")]
362 public class MagneticFieldSensor : Sensor
363 {
364 /// <summary>
365 /// Strength of the magnetic field reported by the sensor.
366 /// </summary>
367 /// <value>Control representing the strength of the magnetic field.</value>
368 /// <remarks>
369 /// Values are in micro-Tesla (uT) and measure the ambient magnetic field in the X, Y and Z axis.
370 /// </remarks>
371 [InputControl(displayName = "Magnetic Field", noisy = true)]
372 public Vector3Control magneticField { get; protected set; }
373
374 /// <summary>
375 /// The linear acceleration sensor that was last added or had activity last.
376 /// </summary>
377 /// <value>Current linear acceleration sensor or <c>null</c>.</value>
378 public static MagneticFieldSensor current { get; private set; }
379
380 /// <inheritdoc />
381 public override void MakeCurrent()
382 {
383 base.MakeCurrent();
384 current = this;
385 }
386
387 /// <inheritdoc />
388 protected override void OnRemoved()
389 {
390 base.OnRemoved();
391 if (current == this)
392 current = null;
393 }
394
395 /// <inheritdoc />
396 protected override void FinishSetup()
397 {
398 magneticField = GetChildControl<Vector3Control>("magneticField");
399 base.FinishSetup();
400 }
401 }
402
403 /// <summary>
404 /// Input device representing the ambient light measured by the device playing the content.
405 /// </summary>
406 [InputControlLayout(displayName = "Light")]
407 public class LightSensor : Sensor
408 {
409 /// <summary>
410 /// Light level in SI lux units.
411 /// </summary>
412 [InputControl(displayName = "Light Level", noisy = true)]
413 public AxisControl lightLevel { get; protected set; }
414
415 /// <summary>
416 /// The light sensor that was last added or had activity last.
417 /// </summary>
418 /// <value>Current light sensor or <c>null</c>.</value>
419 public static LightSensor current { get; private set; }
420
421 /// <inheritdoc />
422 public override void MakeCurrent()
423 {
424 base.MakeCurrent();
425 current = this;
426 }
427
428 /// <inheritdoc />
429 protected override void OnRemoved()
430 {
431 base.OnRemoved();
432 if (current == this)
433 current = null;
434 }
435
436 /// <inheritdoc />
437 protected override void FinishSetup()
438 {
439 lightLevel = GetChildControl<AxisControl>("lightLevel");
440 base.FinishSetup();
441 }
442 }
443
444 /// <summary>
445 /// Input device representing the atmospheric pressure measured by the device playing the content.
446 /// </summary>
447 [InputControlLayout(displayName = "Pressure")]
448 public class PressureSensor : Sensor
449 {
450 /// <summary>
451 /// Atmospheric pressure in hPa (millibar).
452 /// </summary>
453 [InputControl(displayName = "Atmospheric Pressure", noisy = true)]
454 public AxisControl atmosphericPressure { get; protected set; }
455
456 /// <summary>
457 /// The pressure sensor that was last added or had activity last.
458 /// </summary>
459 /// <value>Current pressure sensor or <c>null</c>.</value>
460 public static PressureSensor current { get; private set; }
461
462 /// <inheritdoc />
463 public override void MakeCurrent()
464 {
465 base.MakeCurrent();
466 current = this;
467 }
468
469 /// <inheritdoc />
470 protected override void OnRemoved()
471 {
472 base.OnRemoved();
473 if (current == this)
474 current = null;
475 }
476
477 /// <inheritdoc />
478 protected override void FinishSetup()
479 {
480 atmosphericPressure = GetChildControl<AxisControl>("atmosphericPressure");
481 base.FinishSetup();
482 }
483 }
484
485 /// <summary>
486 /// Input device representing the proximity of the device playing the content to the user.
487 /// </summary>
488 /// <remarks>
489 /// The proximity sensor is usually used by phones to determine if the user is holding the phone to their ear or not.
490 /// </remarks>
491 [InputControlLayout(displayName = "Proximity")]
492 public class ProximitySensor : Sensor
493 {
494 /// <summary>
495 /// Proximity sensor distance measured in centimeters.
496 /// </summary>
497 [InputControl(displayName = "Distance", noisy = true)]
498 public AxisControl distance { get; protected set; }
499
500 /// <summary>
501 /// The proximity sensor that was last added or had activity last.
502 /// </summary>
503 /// <value>Current proximity sensor or <c>null</c>.</value>
504 public static ProximitySensor current { get; private set; }
505
506 /// <inheritdoc />
507 public override void MakeCurrent()
508 {
509 base.MakeCurrent();
510 current = this;
511 }
512
513 /// <inheritdoc />
514 protected override void OnRemoved()
515 {
516 base.OnRemoved();
517 if (current == this)
518 current = null;
519 }
520
521 /// <inheritdoc />
522 protected override void FinishSetup()
523 {
524 distance = GetChildControl<AxisControl>("distance");
525 base.FinishSetup();
526 }
527 }
528
529 /// <summary>
530 /// Input device representing the ambient air humidity measured by the device playing the content.
531 /// </summary>
532 [InputControlLayout(displayName = "Humidity")]
533 public class HumiditySensor : Sensor
534 {
535 /// <summary>
536 /// Relative ambient air humidity in percent.
537 /// </summary>
538 [InputControl(displayName = "Relative Humidity", noisy = true)]
539 public AxisControl relativeHumidity { get; protected set; }
540
541 /// <summary>
542 /// The humidity sensor that was last added or had activity last.
543 /// </summary>
544 /// <value>Current humidity sensor or <c>null</c>.</value>
545 public static HumiditySensor current { get; private set; }
546
547 /// <inheritdoc />
548 public override void MakeCurrent()
549 {
550 base.MakeCurrent();
551 current = this;
552 }
553
554 /// <inheritdoc />
555 protected override void OnRemoved()
556 {
557 base.OnRemoved();
558 if (current == this)
559 current = null;
560 }
561
562 /// <inheritdoc />
563 protected override void FinishSetup()
564 {
565 relativeHumidity = GetChildControl<AxisControl>("relativeHumidity");
566 base.FinishSetup();
567 }
568 }
569
570 /// <summary>
571 /// Input device representing the ambient air temperature measured by the device playing the content.
572 /// </summary>
573 [InputControlLayout(displayName = "Ambient Temperature")]
574 public class AmbientTemperatureSensor : Sensor
575 {
576 /// <summary>
577 /// Temperature in degree Celsius.
578 /// </summary>
579 [InputControl(displayName = "Ambient Temperature", noisy = true)]
580 public AxisControl ambientTemperature { get; protected set; }
581
582 /// <summary>
583 /// The ambient temperature sensor that was last added or had activity last.
584 /// </summary>
585 /// <value>Current ambient temperature sensor or <c>null</c>.</value>
586 public static AmbientTemperatureSensor current { get; private set; }
587
588 /// <inheritdoc />
589 public override void MakeCurrent()
590 {
591 base.MakeCurrent();
592 current = this;
593 }
594
595 /// <inheritdoc />
596 protected override void OnRemoved()
597 {
598 base.OnRemoved();
599 if (current == this)
600 current = null;
601 }
602
603 /// <inheritdoc />
604 protected override void FinishSetup()
605 {
606 ambientTemperature = GetChildControl<AxisControl>("ambientTemperature");
607 base.FinishSetup();
608 }
609 }
610
611 /// <summary>
612 /// Input device representing the foot steps taken by the user as measured by the device playing the content.
613 /// </summary>
614 /// <remarks>
615 /// On iOS, access to the step counter must be enabled via <see cref="InputSettings.iOSSettings.motionUsage"/>.
616 /// </remarks>
617 [InputControlLayout(displayName = "Step Counter")]
618 public class StepCounter : Sensor
619 {
620 /// <summary>
621 /// The number of steps taken by the user since the last reboot while activated.
622 /// </summary>
623 [InputControl(displayName = "Step Counter", noisy = true)]
624 public IntegerControl stepCounter { get; protected set; }
625
626 /// <summary>
627 /// The step counter that was last added or had activity last.
628 /// </summary>
629 /// <value>Current step counter or <c>null</c>.</value>
630 public static StepCounter current { get; private set; }
631
632 /// <inheritdoc />
633 public override void MakeCurrent()
634 {
635 base.MakeCurrent();
636 current = this;
637 }
638
639 /// <inheritdoc />
640 protected override void OnRemoved()
641 {
642 base.OnRemoved();
643 if (current == this)
644 current = null;
645 }
646
647 /// <inheritdoc />
648 protected override void FinishSetup()
649 {
650 stepCounter = GetChildControl<IntegerControl>("stepCounter");
651 base.FinishSetup();
652 }
653 }
654
655 /// <summary>
656 /// Hinge angle sensor.
657 /// This sensor is usually available on foldable devices.
658 /// Note: The step resolution for angle is device dependentent, on Android you can query the sensor resolution by querying device capabilities.
659 /// </summary>
660 [InputControlLayout(displayName = "Hinge Angle")]
661 public class HingeAngle : Sensor
662 {
663 /// <summary>
664 /// The angle in degrees on how much the device is unfolded.
665 /// </summary>
666 /// <value>0 means fully folded, 180 means fully unfolded.</value>
667 public AxisControl angle { get; protected set; }
668
669 /// <summary>
670 /// The hinge angle sensor that was last added or had activity last.
671 /// </summary>
672 /// <value>Current hinge angle sensor or <c>null</c>.</value>
673 public static HingeAngle current { get; private set; }
674
675 /// <inheritdoc />
676 public override void MakeCurrent()
677 {
678 base.MakeCurrent();
679 current = this;
680 }
681
682 /// <inheritdoc />
683 protected override void OnRemoved()
684 {
685 base.OnRemoved();
686 if (current == this)
687 current = null;
688 }
689
690 /// <inheritdoc />
691 protected override void FinishSetup()
692 {
693 angle = GetChildControl<AxisControl>("angle");
694 base.FinishSetup();
695 }
696 }
697}