A game about forced loneliness, made by TACStudios
1using UnityEngine.InputSystem.Layouts;
2using UnityEngine.InputSystem.LowLevel;
3using UnityEngine.InputSystem.Utilities;
4
5////REVIEW: expose euler angle subcontrols?
6
7namespace UnityEngine.InputSystem.Controls
8{
9 /// <summary>
10 /// A generic input control reading quaternion (rotation) values.
11 /// </summary>
12 public class QuaternionControl : InputControl<Quaternion>
13 {
14 // Accessing these components as individual controls usually doesn't make too much sense,
15 // but having these controls allows changing the state format on the quaternion without
16 // requiring the control to explicitly support the various different storage formats.
17 // Also, it allows putting processors on the individual components which may be necessary
18 // to properly convert the source data.
19
20 /// <summary>
21 /// The X component of the quaternion.
22 /// </summary>
23 /// <value>Control representing the X component.</value>
24 [InputControl(displayName = "X")]
25 public AxisControl x { get; set; }
26
27 /// <summary>
28 /// The Y component of the quaternion.
29 /// </summary>
30 /// <value>Control representing the Y component.</value>
31 [InputControl(displayName = "Y")]
32 public AxisControl y { get; set; }
33
34 /// <summary>
35 /// The Z component of the quaternion.
36 /// </summary>
37 /// <value>Control representing the Z component.</value>
38 [InputControl(displayName = "Z")]
39 public AxisControl z { get; set; }
40
41 /// <summary>
42 /// The W component of the quaternion.
43 /// </summary>
44 /// <value>Control representing the W component.</value>
45 [InputControl(displayName = "W")]
46 public AxisControl w { get; set; }
47
48 /// <summary>
49 /// Default-initialize the control.
50 /// </summary>
51 public QuaternionControl()
52 {
53 m_StateBlock.sizeInBits = sizeof(float) * 4 * 8;
54 m_StateBlock.format = InputStateBlock.FormatQuaternion;
55 }
56
57 /// <inheritdoc/>
58 protected override void FinishSetup()
59 {
60 x = GetChildControl<AxisControl>("x");
61 y = GetChildControl<AxisControl>("y");
62 z = GetChildControl<AxisControl>("z");
63 w = GetChildControl<AxisControl>("w");
64 base.FinishSetup();
65 }
66
67 /// <inheritdoc/>
68 public override unsafe Quaternion ReadUnprocessedValueFromState(void* statePtr)
69 {
70 switch (m_OptimizedControlDataType)
71 {
72 case InputStateBlock.kFormatQuaternion:
73 return *(Quaternion*)((byte*)statePtr + (int)m_StateBlock.byteOffset);
74 default:
75 return new Quaternion(
76 x.ReadValueFromStateWithCaching(statePtr),
77 y.ReadValueFromStateWithCaching(statePtr),
78 z.ReadValueFromStateWithCaching(statePtr),
79 w.ReadUnprocessedValueFromStateWithCaching(statePtr));
80 }
81 }
82
83 /// <inheritdoc/>
84 public override unsafe void WriteValueIntoState(Quaternion value, void* statePtr)
85 {
86 switch (m_OptimizedControlDataType)
87 {
88 case InputStateBlock.kFormatQuaternion:
89 *(Quaternion*)((byte*)statePtr + (int)m_StateBlock.byteOffset) = value;
90 break;
91 default:
92 x.WriteValueIntoState(value.x, statePtr);
93 y.WriteValueIntoState(value.y, statePtr);
94 z.WriteValueIntoState(value.z, statePtr);
95 w.WriteValueIntoState(value.w, statePtr);
96 break;
97 }
98 }
99
100 protected override FourCC CalculateOptimizedControlDataType()
101 {
102 if (
103 m_StateBlock.sizeInBits == sizeof(float) * 4 * 8 &&
104 m_StateBlock.bitOffset == 0 &&
105 x.optimizedControlDataType == InputStateBlock.FormatFloat &&
106 y.optimizedControlDataType == InputStateBlock.FormatFloat &&
107 z.optimizedControlDataType == InputStateBlock.FormatFloat &&
108 w.optimizedControlDataType == InputStateBlock.FormatFloat &&
109 y.m_StateBlock.byteOffset == x.m_StateBlock.byteOffset + 4 &&
110 z.m_StateBlock.byteOffset == x.m_StateBlock.byteOffset + 8 &&
111 w.m_StateBlock.byteOffset == x.m_StateBlock.byteOffset + 12 &&
112 // For some unknown reason ReadUnprocessedValueFromState here uses ReadValueFromState on x/y/z (but not w)
113 // which means we can't optimize if there any processors on x/y/z
114 x.m_ProcessorStack.length == 0 &&
115 y.m_ProcessorStack.length == 0 &&
116 z.m_ProcessorStack.length == 0
117 )
118 return InputStateBlock.FormatQuaternion;
119
120 return InputStateBlock.FormatInvalid;
121 }
122 }
123}