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) || PACKAGE_DOCS_GENERATION
3using System;
4using System.Collections.Generic;
5using UnityEngine.InputSystem.Layouts;
6using UnityEngine.InputSystem.Controls;
7using UnityEngine.XR;
8
9namespace UnityEngine.InputSystem.XR
10{
11 /// <summary>
12 /// A set of static utilities for registering XR Input Devices externally.
13 /// </summary>
14 public static class XRUtilities
15 {
16 /// <summary>
17 /// A simple Regex pattern that allows InputDeviceMatchers to match to any version of the XRInput interface.
18 /// </summary>
19 public const string InterfaceMatchAnyVersion = "^(XRInput)";
20
21 /// <summary>
22 /// The initial, now deprecated interface for XRInput. This version handles button packing for Android differently from current.
23 /// </summary>
24 public const string InterfaceV1 = "XRInput";
25
26 /// <summary>
27 /// The current interface code sent with devices to identify as XRInput devices.
28 /// </summary>
29 public const string InterfaceCurrent = "XRInputV1";
30 }
31
32 // Sync to UnityXRInputFeatureType in IUnityXRInput.h
33 /// <summary>
34 /// The type of data a <see cref="XRFeatureDescriptor"/> exposes.
35 /// </summary>
36 public enum FeatureType
37 {
38 Custom = 0,
39 Binary,
40 DiscreteStates,
41 Axis1D,
42 Axis2D,
43 Axis3D,
44 Rotation,
45 Hand,
46 Bone,
47 Eyes
48 }
49
50 /// <summary>
51 /// Contextual strings that identify the contextual, cross-platform use that a feature represents. <see cref="UnityEngine.XR.CommonUsages"/> for a list of unity's built-in shared usages.
52 /// </summary>
53#pragma warning disable 0649
54 [Serializable]
55 public struct UsageHint
56 {
57 public string content;
58 }
59
60 //Sync to XRInputFeatureDefinition in XRInputDeviceDefinition.h
61 /// <summary>
62 /// Describes an individual input on a device, such as a trackpad, or button, or trigger.
63 /// </summary>
64 [Serializable]
65 public struct XRFeatureDescriptor
66 {
67 /// <summary>
68 /// The name of the feature.
69 /// </summary>
70 public string name;
71 /// <summary>
72 /// The uses that this feature should represent, such as trigger, or grip, or touchpad.
73 /// </summary>
74 public List<UsageHint> usageHints;
75 /// <summary>
76 /// The type of data this feature exposes.
77 /// </summary>
78 public FeatureType featureType;
79 /// <summary>
80 /// The overall size of the feature. This is only filled in when the <see cref="featureType"/> is <see cref="FeatureType.Custom"/>.
81 /// </summary>
82 public uint customSize;
83 }
84
85 //Sync to XRInputDeviceDefinition in XRInputDeviceDefinition.h
86 /// <summary>
87 /// Describes an input device: what it can do and how it should be used. These are reported during device connection, and help identify devices and map input data to the right controls.
88 /// </summary>
89 [Serializable]
90 public class XRDeviceDescriptor
91 {
92 /// <summary>
93 /// The name of the device.
94 /// </summary>
95 public string deviceName;
96 /// <summary>
97 /// The manufacturer of the device.
98 /// </summary>
99 public string manufacturer;
100 /// <summary>
101 /// The serial number of the device. An empty string if no serial number is available.
102 /// </summary>
103 public string serialNumber;
104 /// <summary>
105 /// The capabilities of the device, used to help filter and identify devices that server a certain purpose (e.g. controller, or headset, or hardware tracker).
106 /// </summary>
107 public InputDeviceCharacteristics characteristics;
108 /// <summary>
109 /// The underlying deviceId, this can be used with <see cref="UnityEngine.XR.InputDevices"/> to create a device.
110 /// </summary>
111 public int deviceId;
112 /// <summary>
113 /// A list of all input features. <seealso cref="XRFeatureDescriptor"/>
114 /// </summary>
115 public List<XRFeatureDescriptor> inputFeatures;
116
117 /// <summary>
118 /// Converts this structure to a JSON string.
119 /// </summary>
120 /// <returns></returns>
121 public string ToJson()
122 {
123 return JsonUtility.ToJson(this);
124 }
125
126 /// <summary>
127 /// Converts a json string to a new <see cref="XRDeviceDescriptor"/>.
128 /// </summary>
129 /// <param name="json">The JSON string containing <see cref="XRDeviceDescriptor"/> data.</param>
130 /// <returns>A new <see cref="XRDeviceDescriptor"/></returns>
131 public static XRDeviceDescriptor FromJson(string json)
132 {
133 return JsonUtility.FromJson<XRDeviceDescriptor>(json);
134 }
135 }
136
137 /// <summary>
138 /// Represents a 3 dimensional, tracked bone within a hierarchy of other bones.
139 /// </summary>
140 public struct Bone
141 {
142 /// <summary>
143 /// The index with the device's controls array where the parent bone resides.
144 /// </summary>
145 public uint m_ParentBoneIndex;
146
147 /// <summary>
148 /// The tracked position of the bone.
149 /// </summary>
150 public Vector3 m_Position;
151
152 /// <summary>
153 /// The tracked rotation of the bone.
154 /// </summary>
155 public Quaternion m_Rotation;
156
157 /// <summary>
158 /// The index with the device's controls array where the parent bone resides.
159 /// </summary>
160 public uint parentBoneIndex
161 {
162 get => m_ParentBoneIndex;
163 set => m_ParentBoneIndex = value;
164 }
165
166 /// <summary>
167 /// The tracked position of the bone.
168 /// </summary>
169 public Vector3 position
170 {
171 get => m_Position;
172 set => m_Position = value;
173 }
174
175 /// <summary>
176 /// The tracked rotation of the bone.
177 /// </summary>
178 public Quaternion rotation
179 {
180 get => m_Rotation;
181 set => m_Rotation = value;
182 }
183 }
184
185 /// <summary>
186 /// Represents a pair of tracked eyes.
187 /// </summary>
188 public struct Eyes
189 {
190 /// <summary>
191 /// The tracked position of the left eye.
192 /// </summary>
193 public Vector3 m_LeftEyePosition;
194 /// <summary>
195 /// The tracked rotation of the left eye.
196 /// </summary>
197 public Quaternion m_LeftEyeRotation;
198 /// <summary>
199 /// The tracked position of the right eye.
200 /// </summary>
201 public Vector3 m_RightEyePosition;
202 /// <summary>
203 /// The tracked rotation of the right eye.
204 /// </summary>
205 public Quaternion m_RightEyeRotation;
206 /// <summary>
207 /// The point in 3D space that the pair of eyes is looking.
208 /// </summary>
209 public Vector3 m_FixationPoint;
210 /// <summary>
211 /// The amount [0-1] the left eye is open or closed. 1.0 is fully open.
212 /// </summary>
213 public float m_LeftEyeOpenAmount;
214 /// <summary>
215 /// The amount [0-1] the right eye is open or closed. 1.0 is fully open.
216 /// </summary>
217 public float m_RightEyeOpenAmount;
218
219 /// <summary>
220 /// The tracked position of the left eye.
221 /// </summary>
222 public Vector3 leftEyePosition
223 {
224 get => m_LeftEyePosition;
225 set => m_LeftEyePosition = value;
226 }
227
228 /// <summary>
229 /// The tracked rotation of the left eye.
230 /// </summary>
231 public Quaternion leftEyeRotation
232 {
233 get => m_LeftEyeRotation;
234 set => m_LeftEyeRotation = value;
235 }
236
237 /// <summary>
238 /// The tracked position of the right eye.
239 /// </summary>
240 public Vector3 rightEyePosition
241 {
242 get => m_RightEyePosition;
243 set => m_RightEyePosition = value;
244 }
245
246 /// <summary>
247 /// The tracked rotation of the right eye.
248 /// </summary>
249 public Quaternion rightEyeRotation
250 {
251 get => m_RightEyeRotation;
252 set => m_RightEyeRotation = value;
253 }
254
255 /// <summary>
256 /// The point in 3D space that the pair of eyes is looking.
257 /// </summary>
258 public Vector3 fixationPoint
259 {
260 get => m_FixationPoint;
261 set => m_FixationPoint = value;
262 }
263
264 /// <summary>
265 /// The amount [0-1] the left eye is open or closed. 1.0 is fully open.
266 /// </summary>
267 public float leftEyeOpenAmount
268 {
269 get => m_LeftEyeOpenAmount;
270 set => m_LeftEyeOpenAmount = value;
271 }
272
273 /// <summary>
274 /// The amount [0-1] the right eye is open or closed. 1.0 is fully open.
275 /// </summary>
276 public float rightEyeOpenAmount
277 {
278 get => m_RightEyeOpenAmount;
279 set => m_RightEyeOpenAmount = value;
280 }
281 }
282
283 public class BoneControl : InputControl<Bone>
284 {
285 [InputControl(offset = 0, displayName = "parentBoneIndex")]
286 public IntegerControl parentBoneIndex { get; set; }
287 [InputControl(offset = 4, displayName = "Position")]
288 public Vector3Control position { get; set; }
289 [InputControl(offset = 16, displayName = "Rotation")]
290 public QuaternionControl rotation { get; set; }
291
292 protected override void FinishSetup()
293 {
294 parentBoneIndex = GetChildControl<IntegerControl>("parentBoneIndex");
295 position = GetChildControl<Vector3Control>("position");
296 rotation = GetChildControl<QuaternionControl>("rotation");
297
298 base.FinishSetup();
299 }
300
301 public override unsafe Bone ReadUnprocessedValueFromState(void* statePtr)
302 {
303 return new Bone()
304 {
305 parentBoneIndex = (uint)parentBoneIndex.ReadUnprocessedValueFromStateWithCaching(statePtr),
306 position = position.ReadUnprocessedValueFromStateWithCaching(statePtr),
307 rotation = rotation.ReadUnprocessedValueFromStateWithCaching(statePtr)
308 };
309 }
310
311 public override unsafe void WriteValueIntoState(Bone value, void* statePtr)
312 {
313 parentBoneIndex.WriteValueIntoState((int)value.parentBoneIndex, statePtr);
314 position.WriteValueIntoState(value.position, statePtr);
315 rotation.WriteValueIntoState(value.rotation, statePtr);
316 }
317 }
318
319 public class EyesControl : InputControl<Eyes>
320 {
321 [InputControl(offset = 0, displayName = "LeftEyePosition")]
322 public Vector3Control leftEyePosition { get; set; }
323 [InputControl(offset = 12, displayName = "LeftEyeRotation")]
324 public QuaternionControl leftEyeRotation { get; set; }
325 [InputControl(offset = 28, displayName = "RightEyePosition")]
326 public Vector3Control rightEyePosition { get; set; }
327 [InputControl(offset = 40, displayName = "RightEyeRotation")]
328 public QuaternionControl rightEyeRotation { get; set; }
329 [InputControl(offset = 56, displayName = "FixationPoint")]
330 public Vector3Control fixationPoint { get; set; }
331 [InputControl(offset = 68, displayName = "LeftEyeOpenAmount")]
332 public AxisControl leftEyeOpenAmount { get; set; }
333 [InputControl(offset = 72, displayName = "RightEyeOpenAmount")]
334 public AxisControl rightEyeOpenAmount { get; set; }
335
336 protected override void FinishSetup()
337 {
338 leftEyePosition = GetChildControl<Vector3Control>("leftEyePosition");
339 leftEyeRotation = GetChildControl<QuaternionControl>("leftEyeRotation");
340 rightEyePosition = GetChildControl<Vector3Control>("rightEyePosition");
341 rightEyeRotation = GetChildControl<QuaternionControl>("rightEyeRotation");
342 fixationPoint = GetChildControl<Vector3Control>("fixationPoint");
343 leftEyeOpenAmount = GetChildControl<AxisControl>("leftEyeOpenAmount");
344 rightEyeOpenAmount = GetChildControl<AxisControl>("rightEyeOpenAmount");
345
346 base.FinishSetup();
347 }
348
349 public override unsafe Eyes ReadUnprocessedValueFromState(void* statePtr)
350 {
351 return new Eyes()
352 {
353 leftEyePosition = leftEyePosition.ReadUnprocessedValueFromStateWithCaching(statePtr),
354 leftEyeRotation = leftEyeRotation.ReadUnprocessedValueFromStateWithCaching(statePtr),
355 rightEyePosition = rightEyePosition.ReadUnprocessedValueFromStateWithCaching(statePtr),
356 rightEyeRotation = rightEyeRotation.ReadUnprocessedValueFromStateWithCaching(statePtr),
357 fixationPoint = fixationPoint.ReadUnprocessedValueFromStateWithCaching(statePtr),
358 leftEyeOpenAmount = leftEyeOpenAmount.ReadUnprocessedValueFromStateWithCaching(statePtr),
359 rightEyeOpenAmount = rightEyeOpenAmount.ReadUnprocessedValueFromStateWithCaching(statePtr)
360 };
361 }
362
363 public override unsafe void WriteValueIntoState(Eyes value, void* statePtr)
364 {
365 leftEyePosition.WriteValueIntoState(value.leftEyePosition, statePtr);
366 leftEyeRotation.WriteValueIntoState(value.leftEyeRotation, statePtr);
367 rightEyePosition.WriteValueIntoState(value.rightEyePosition, statePtr);
368 rightEyeRotation.WriteValueIntoState(value.rightEyeRotation, statePtr);
369 fixationPoint.WriteValueIntoState(value.fixationPoint, statePtr);
370 leftEyeOpenAmount.WriteValueIntoState(value.leftEyeOpenAmount, statePtr);
371 rightEyeOpenAmount.WriteValueIntoState(value.rightEyeOpenAmount, statePtr);
372 }
373 }
374#pragma warning restore 0649
375
376 /// <summary>
377 /// A small helper class to aid in initializing and registering XR devices and layout builders.
378 /// </summary>
379#if UNITY_DISABLE_DEFAULT_INPUT_PLUGIN_INITIALIZATION
380 public
381#else
382 internal
383#endif
384 static class XRSupport
385 {
386 /// <summary>
387 /// Registers all initial templates and the generalized layout builder with the InputSystem.
388 /// </summary>
389 public static void Initialize()
390 {
391#if !UNITY_FORCE_INPUTSYSTEM_XR_OFF
392 InputSystem.RegisterLayout<PoseControl>("Pose");
393 InputSystem.RegisterLayout<BoneControl>("Bone");
394 InputSystem.RegisterLayout<EyesControl>("Eyes");
395
396 InputSystem.RegisterLayout<XRHMD>();
397 InputSystem.RegisterLayout<XRController>();
398
399 InputSystem.onFindLayoutForDevice += XRLayoutBuilder.OnFindLayoutForDevice;
400
401 // Built-in layouts replaced by the com.unity.xr.windowsmr package.
402#if !DISABLE_BUILTIN_INPUT_SYSTEM_WINDOWSMR
403 InputSystem.RegisterLayout<UnityEngine.XR.WindowsMR.Input.WMRHMD>(
404 matches: new InputDeviceMatcher()
405 .WithInterface(XRUtilities.InterfaceMatchAnyVersion)
406 .WithProduct("(Windows Mixed Reality HMD)|(Microsoft HoloLens)|(^(WindowsMR Headset))")
407 );
408 InputSystem.RegisterLayout<UnityEngine.XR.WindowsMR.Input.WMRSpatialController>(
409 matches: new InputDeviceMatcher()
410 .WithInterface(XRUtilities.InterfaceMatchAnyVersion)
411 .WithProduct(@"(^(Spatial Controller))|(^(OpenVR Controller\(WindowsMR))")
412 );
413 InputSystem.RegisterLayout<UnityEngine.XR.WindowsMR.Input.HololensHand>(
414 matches: new InputDeviceMatcher()
415 .WithInterface(XRUtilities.InterfaceMatchAnyVersion)
416 .WithProduct(@"(^(Hand -))")
417 );
418#endif
419
420 // Built-in layouts replaced by the com.unity.xr.oculus package.
421#if !DISABLE_BUILTIN_INPUT_SYSTEM_OCULUS
422 InputSystem.RegisterLayout<Unity.XR.Oculus.Input.OculusHMD>(
423 matches: new InputDeviceMatcher()
424 .WithInterface(XRUtilities.InterfaceMatchAnyVersion)
425 .WithProduct("^(Oculus Rift)|^(Oculus Quest)|^(Oculus Go)"));
426 InputSystem.RegisterLayout<Unity.XR.Oculus.Input.OculusTouchController>(
427 matches: new InputDeviceMatcher()
428 .WithInterface(XRUtilities.InterfaceMatchAnyVersion)
429 .WithProduct(@"(^(Oculus Touch Controller))|(^(Oculus Quest Controller))"));
430 InputSystem.RegisterLayout<Unity.XR.Oculus.Input.OculusRemote>(
431 matches: new InputDeviceMatcher()
432 .WithInterface(XRUtilities.InterfaceMatchAnyVersion)
433 .WithProduct(@"Oculus Remote"));
434 InputSystem.RegisterLayout<Unity.XR.Oculus.Input.OculusTrackingReference>(
435 matches: new InputDeviceMatcher()
436 .WithInterface(XRUtilities.InterfaceMatchAnyVersion)
437 .WithProduct(@"((Tracking Reference)|(^(Oculus Rift [a-zA-Z0-9]* \(Camera)))"));
438
439 InputSystem.RegisterLayout<Unity.XR.Oculus.Input.OculusHMDExtended>(
440 name: "GearVR",
441 matches: new InputDeviceMatcher()
442 .WithInterface(XRUtilities.InterfaceMatchAnyVersion)
443 .WithProduct("Oculus HMD"));
444 InputSystem.RegisterLayout<Unity.XR.Oculus.Input.GearVRTrackedController>(
445 matches: new InputDeviceMatcher()
446 .WithInterface(XRUtilities.InterfaceMatchAnyVersion)
447 .WithProduct("^(Oculus Tracked Remote)"));
448#endif
449
450 // Built-in layouts replaced by the com.unity.xr.googlevr package.
451#if !DISABLE_BUILTIN_INPUT_SYSTEM_GOOGLEVR
452 InputSystem.RegisterLayout<Unity.XR.GoogleVr.DaydreamHMD>(
453 matches: new InputDeviceMatcher()
454 .WithInterface(XRUtilities.InterfaceMatchAnyVersion)
455 .WithProduct("Daydream HMD"));
456 InputSystem.RegisterLayout<Unity.XR.GoogleVr.DaydreamController>(
457 matches: new InputDeviceMatcher()
458 .WithInterface(XRUtilities.InterfaceMatchAnyVersion)
459 .WithProduct("^(Daydream Controller)"));
460#endif
461
462 // Built-in layouts replaced by the com.unity.xr.openvr package.
463#if !DISABLE_BUILTIN_INPUT_SYSTEM_OPENVR
464 InputSystem.RegisterLayout<Unity.XR.OpenVR.OpenVRHMD>(
465 matches: new InputDeviceMatcher()
466 .WithInterface(XRUtilities.InterfaceMatchAnyVersion)
467 .WithProduct("^(OpenVR Headset)|^(Vive Pro)")
468 );
469 InputSystem.RegisterLayout<Unity.XR.OpenVR.OpenVRControllerWMR>(
470 matches: new InputDeviceMatcher()
471 .WithInterface(XRUtilities.InterfaceMatchAnyVersion)
472 .WithProduct("^(OpenVR Controller\\(WindowsMR)")
473 );
474 InputSystem.RegisterLayout<Unity.XR.OpenVR.ViveWand>(
475 matches: new InputDeviceMatcher()
476 .WithInterface(XRUtilities.InterfaceMatchAnyVersion)
477 .WithManufacturer("HTC")
478 .WithProduct(@"^(OpenVR Controller\(((Vive. Controller)|(VIVE. Controller)|(Vive Controller)))")
479 );
480 InputSystem.RegisterLayout<Unity.XR.OpenVR.OpenVROculusTouchController>(
481 matches: new InputDeviceMatcher()
482 .WithInterface(XRUtilities.InterfaceMatchAnyVersion)
483 .WithProduct(@"^(OpenVR Controller\(Oculus)")
484 );
485
486 InputSystem.RegisterLayout<Unity.XR.OpenVR.ViveTracker>(
487 matches: new InputDeviceMatcher()
488 .WithInterface(XRUtilities.InterfaceMatchAnyVersion)
489 .WithManufacturer("HTC")
490 .WithProduct(@"^(VIVE Tracker)")
491 );
492 InputSystem.RegisterLayout<Unity.XR.OpenVR.HandedViveTracker>(
493 matches: new InputDeviceMatcher()
494 .WithInterface(XRUtilities.InterfaceMatchAnyVersion)
495 .WithManufacturer("HTC")
496 .WithProduct(@"^(OpenVR Controller\(VIVE Tracker)")
497 );
498 InputSystem.RegisterLayout<Unity.XR.OpenVR.ViveLighthouse>(
499 matches: new InputDeviceMatcher()
500 .WithInterface(XRUtilities.InterfaceMatchAnyVersion)
501 .WithManufacturer("HTC")
502 .WithProduct(@"^(HTC V2-XD/XE)")
503 );
504#endif
505#endif
506 }
507 }
508}
509#endif