A game about forced loneliness, made by TACStudios
1// ENABLE_VR is not defined on Game Core but the assembly is available with limited features when the XR module is enabled.
2#if UNITY_INPUT_SYSTEM_ENABLE_XR && (ENABLE_VR || UNITY_GAMECORE) && !UNITY_FORCE_INPUTSYSTEM_XR_OFF || PACKAGE_DOCS_GENERATION
3using System.Runtime.InteropServices;
4using Unity.Collections.LowLevel.Unsafe;
5using UnityEngine.InputSystem.Controls;
6using UnityEngine.InputSystem.Layouts;
7using UnityEngine.InputSystem.LowLevel;
8using UnityEngine.InputSystem.Utilities;
9using UnityEngine.Scripting;
10using TrackingState = UnityEngine.XR.InputTrackingState;
11
12namespace UnityEngine.InputSystem.XR
13{
14 /// <summary>
15 /// State layout for a single pose.
16 /// </summary>
17 /// <remarks>
18 /// This is the low-level memory representation of a single pose, i.e the
19 /// way poses are internally transmitted and stored in the system. PoseStates are used on devices containing <see cref="PoseControl"/>s.
20 /// </remarks>
21 /// <seealso cref="PoseControl"/>
22 [StructLayout(LayoutKind.Explicit, Size = kSizeInBytes)]
23 public struct PoseState : IInputStateTypeInfo
24 {
25 internal const int kSizeInBytes = 60;
26
27 internal static readonly FourCC s_Format = new FourCC('P', 'o', 's', 'e');
28
29 /// <summary>
30 /// Memory format tag for PoseState.
31 /// </summary>
32 /// <value>Returns "Pose".</value>
33 /// <seealso cref="InputStateBlock.format"/>
34 public FourCC format => s_Format;
35
36 /// <summary>
37 /// Constructor for PoseStates.
38 ///
39 /// Useful for creating PoseStates locally (not from <see cref="PoseControl"/>).
40 /// </summary>
41 /// <param name="isTracked">Value to use for <see cref="isTracked"/></param>
42 /// <param name="trackingState">Value to use for <see cref="trackingState"/></param>
43 /// <param name="position">Value to use for <see cref="position"/></param>
44 /// <param name="rotation">Value to use for <see cref="rotation"/></param>
45 /// <param name="velocity">Value to use for <see cref="velocity"/></param>
46 /// <param name="angularVelocity">Value to use for <see cref="angularVelocity"/></param>
47 public PoseState(bool isTracked, TrackingState trackingState, Vector3 position, Quaternion rotation, Vector3 velocity, Vector3 angularVelocity)
48 {
49 this.isTracked = isTracked;
50 this.trackingState = trackingState;
51 this.position = position;
52 this.rotation = rotation;
53 this.velocity = velocity;
54 this.angularVelocity = angularVelocity;
55 }
56
57 /// <summary>
58 /// Whether the pose is currently being fully tracked. Otherwise, the tracking is either unavailable, or simulated.
59 /// </summary>
60 /// <remarks>
61 /// Fully tracked means that the pose is accurate and not using any simulated or extrapolated positions, and the system tracking this pose is able to confidently track this object.
62 /// </remarks>
63 [FieldOffset(0), InputControl(displayName = "Is Tracked", layout = "Button", sizeInBits = 8 /* needed to ensure optimization kicks-in */)]
64 public bool isTracked;
65
66 /// <summary>
67 /// A Flags Enumeration specifying which other fields in the pose state are valid.
68 /// </summary>
69 [FieldOffset(4), InputControl(displayName = "Tracking State", layout = "Integer")]
70 public TrackingState trackingState;
71
72 /// <summary>
73 /// The position in 3D space, relative to the tracking origin where this pose represents.
74 /// </summary>
75 /// <remarks>
76 /// Positions are represented in meters.
77 /// This field is only valid if <see cref="trackingState"/> contains the <see cref="UnityEngine.XR.InputTrackingState.Position"/> value.
78 /// See <seealso cref="UnityEngine.XR.TrackingOriginModeFlags"/> for information on tracking origins.
79 /// </remarks>
80 [FieldOffset(8), InputControl(displayName = "Position", noisy = true)]
81 public Vector3 position;
82
83 /// <summary>
84 /// The rotation in 3D space, relative to the tracking origin where this pose represents.
85 /// </summary>
86 /// <remarks>
87 /// This field is only valid if <see cref="trackingState"/> contains the <see cref="UnityEngine.XR.InputTrackingState.Rotation"/> value.
88 /// See <seealso cref="UnityEngine.XR.TrackingOriginModeFlags"/> for information on tracking origins.
89 /// </remarks>
90 [FieldOffset(20), InputControl(displayName = "Rotation", noisy = true)]
91 public Quaternion rotation;
92
93 /// <summary>
94 /// The velocity in 3D space, relative to the tracking origin where this pose represents.
95 /// </summary>
96 /// <remarks>
97 /// Velocities are represented in meters per second.
98 /// This field is only valid if <see cref="trackingState"/> contains the <see cref="UnityEngine.XR.InputTrackingState.Velocity"/> value.
99 /// See <seealso cref="UnityEngine.XR.TrackingOriginModeFlags"/> for information on tracking origins.
100 /// </remarks>
101 [FieldOffset(36), InputControl(displayName = "Velocity", noisy = true)]
102 public Vector3 velocity;
103
104 /// <summary>
105 /// The angular velocity in 3D space, relative to the tracking origin where this pose represents.
106 /// </summary>
107 /// <remarks>
108 /// This field is only valid if <see cref="trackingState"/> contains the <see cref="UnityEngine.XR.InputTrackingState.AngularVelocity"/> value.
109 /// See <seealso cref="UnityEngine.XR.TrackingOriginModeFlags"/> for information on tracking origins.
110 /// </remarks>
111 [FieldOffset(48), InputControl(displayName = "Angular Velocity", noisy = true)]
112 public Vector3 angularVelocity;
113 }
114
115 /// <summary>
116 /// A control representing a Pose in 3D space, relative to an XR tracking origin
117 /// </summary>
118 /// <remarks>
119 /// Note that unlike most other control types, <c>PoseControls</c> do not have
120 /// a flexible memory layout. They are hardwired to <see cref="PoseState"/> and
121 /// will not work correctly with a different memory layouts. Additional fields may
122 /// be appended to the struct but what's there in the struct has to be located
123 /// at exactly those memory addresses.
124 ///
125 /// For more information on tracking origins see <see cref="UnityEngine.XR.TrackingOriginModeFlags"/>.
126 /// </remarks>
127 [Preserve, InputControlLayout(stateType = typeof(PoseState))]
128 public class PoseControl : InputControl<PoseState>
129 {
130 /// <summary>
131 /// Represents whether this pose is fully tracked or unavailable/simulated.
132 /// </summary>
133 /// <value>Control representing whether the pose is being fully tracked. Maps to the <see cref="PoseState.isTracked"/> value.</value>
134 /// <seealso cref="PoseState.isTracked"/>
135 public ButtonControl isTracked { get; set; }
136
137 /// <summary>
138 /// The other controls on this <see cref="PoseControl"/> that are currently reporting data.
139 /// </summary>
140 /// <remarks>
141 /// This can be missing values when the device tracking this pose is restricted or not tracking properly.
142 /// </remarks>
143 /// <value>Control representing whether the pose is being fully tracked. Maps to the <see cref="PoseState.trackingState"/> value of the pose retrieved from this control.</value>
144 /// <seealso cref="PoseState.trackingState"/>
145 public IntegerControl trackingState { get; set; }
146
147 /// <summary>
148 /// The position, in meters, of this tracked pose relative to the tracking origin.
149 /// </summary>
150 /// <remarks>
151 /// The data for this control is only valid if the value returned from <see cref="trackingState"/> contains <see cref="UnityEngine.XR.InputTrackingState.Position"/> value.
152 /// </remarks>
153 /// <value>Control representing whether the pose is being fully tracked. Maps to the <see cref="PoseState.position"/> value of the pose retrieved from this control.</value>
154 /// <seealso cref="PoseState.position"/>
155 public Vector3Control position { get; set; }
156
157 /// <summary>
158 /// The rotation of this tracked pose relative to the tracking origin.
159 /// </summary>
160 /// <remarks>
161 /// The data for this control is only valid if the value returned from <see cref="trackingState"/> contains <see cref="UnityEngine.XR.InputTrackingState.Rotation"/> value.
162 /// </remarks>
163 /// <value>Control representing whether the pose is being fully tracked. Maps to the <see cref="PoseState.rotation"/> value of the pose retrieved from this control.</value>
164 /// <seealso cref="PoseState.rotation"/>
165 public QuaternionControl rotation { get; set; }
166
167 /// <summary>
168 /// The velocity, in meters per second, of this tracked pose relative to the tracking origin.
169 /// </summary>
170 /// <remarks>
171 /// The data for this control is only valid if the value returned from <see cref="trackingState"/> contains <see cref="UnityEngine.XR.InputTrackingState.Velocity"/> value.
172 /// </remarks>
173 /// <value>Control representing whether the pose is being fully tracked. Maps to the <see cref="PoseState.velocity"/> value of the pose retrieved from this control.</value>
174 /// <seealso cref="PoseState.velocity"/>
175 public Vector3Control velocity { get; set; }
176
177 /// <summary>
178 /// The angular velocity of this tracked pose relative to the tracking origin.
179 /// </summary>
180 /// <remarks>
181 /// The data for this control is only valid if the value returned from <see cref="trackingState"/> contains <see cref="UnityEngine.XR.InputTrackingState.AngularVelocity"/> value.
182 /// </remarks>
183 /// <value>Control representing whether the pose is being fully tracked. Maps to the <see cref="PoseState.angularVelocity"/> value of the pose retrieved from this control.</value>
184 /// <seealso cref="PoseState.angularVelocity"/>
185 public Vector3Control angularVelocity { get; set; }
186
187 /// <summary>
188 /// Default-initialize the pose control.
189 /// </summary>
190 /// <remarks>
191 /// Sets the <see cref="InputStateBlock.format"/> to <c>"Pose"</c>.
192 /// </remarks>
193 public PoseControl()
194 {
195 m_StateBlock.format = PoseState.s_Format;
196 }
197
198 /// <inheritdoc />
199 protected override void FinishSetup()
200 {
201 isTracked = GetChildControl<ButtonControl>("isTracked");
202 trackingState = GetChildControl<IntegerControl>("trackingState");
203 position = GetChildControl<Vector3Control>("position");
204 rotation = GetChildControl<QuaternionControl>("rotation");
205 velocity = GetChildControl<Vector3Control>("velocity");
206 angularVelocity = GetChildControl<Vector3Control>("angularVelocity");
207
208 base.FinishSetup();
209 }
210
211 /// <inheritdoc />
212 public override unsafe PoseState ReadUnprocessedValueFromState(void* statePtr)
213 {
214 switch (m_OptimizedControlDataType)
215 {
216 case InputStateBlock.kFormatPose:
217 return *(PoseState*)((byte*)statePtr + (int)m_StateBlock.byteOffset);
218 default:
219 return new PoseState()
220 {
221 isTracked = isTracked.ReadUnprocessedValueFromStateWithCaching(statePtr) > 0.5f,
222 trackingState = (TrackingState)trackingState.ReadUnprocessedValueFromStateWithCaching(statePtr),
223 position = position.ReadUnprocessedValueFromStateWithCaching(statePtr),
224 rotation = rotation.ReadUnprocessedValueFromStateWithCaching(statePtr),
225 velocity = velocity.ReadUnprocessedValueFromStateWithCaching(statePtr),
226 angularVelocity = angularVelocity.ReadUnprocessedValueFromStateWithCaching(statePtr),
227 };
228 }
229 }
230
231 /// <inheritdoc />
232 public override unsafe void WriteValueIntoState(PoseState value, void* statePtr)
233 {
234 switch (m_OptimizedControlDataType)
235 {
236 case InputStateBlock.kFormatPose:
237 *(PoseState*)((byte*)statePtr + (int)m_StateBlock.byteOffset) = value;
238 break;
239 default:
240 isTracked.WriteValueIntoState(value.isTracked, statePtr);
241 trackingState.WriteValueIntoState((uint)value.trackingState, statePtr);
242 position.WriteValueIntoState(value.position, statePtr);
243 rotation.WriteValueIntoState(value.rotation, statePtr);
244 velocity.WriteValueIntoState(value.velocity, statePtr);
245 angularVelocity.WriteValueIntoState(value.angularVelocity, statePtr);
246 break;
247 }
248 }
249
250 protected override FourCC CalculateOptimizedControlDataType()
251 {
252 if (
253 m_StateBlock.sizeInBits == PoseState.kSizeInBytes * 8 &&
254 m_StateBlock.bitOffset == 0 &&
255 isTracked.optimizedControlDataType == InputStateBlock.kFormatByte &&
256 trackingState.optimizedControlDataType == InputStateBlock.kFormatInt &&
257 position.optimizedControlDataType == InputStateBlock.kFormatVector3 &&
258 rotation.optimizedControlDataType == InputStateBlock.kFormatQuaternion &&
259 velocity.optimizedControlDataType == InputStateBlock.kFormatVector3 &&
260 angularVelocity.optimizedControlDataType == InputStateBlock.kFormatVector3 &&
261 trackingState.m_StateBlock.byteOffset == isTracked.m_StateBlock.byteOffset + 4 &&
262 position.m_StateBlock.byteOffset == isTracked.m_StateBlock.byteOffset + 8 &&
263 rotation.m_StateBlock.byteOffset == isTracked.m_StateBlock.byteOffset + 20 &&
264 velocity.m_StateBlock.byteOffset == isTracked.m_StateBlock.byteOffset + 36 &&
265 angularVelocity.m_StateBlock.byteOffset == isTracked.m_StateBlock.byteOffset + 48
266 )
267 return InputStateBlock.kFormatPose;
268
269 return InputStateBlock.kFormatInvalid;
270 }
271 }
272}
273#endif