510 lines
20 KiB
C#
510 lines
20 KiB
C#
// ENABLE_VR is not defined on Game Core but the assembly is available with limited features when the XR module is enabled.
|
|
#if UNITY_INPUT_SYSTEM_ENABLE_XR && (ENABLE_VR || UNITY_GAMECORE) || PACKAGE_DOCS_GENERATION
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine.InputSystem.Layouts;
|
|
using UnityEngine.InputSystem.Controls;
|
|
using UnityEngine.XR;
|
|
|
|
namespace UnityEngine.InputSystem.XR
|
|
{
|
|
/// <summary>
|
|
/// A set of static utilities for registering XR Input Devices externally.
|
|
/// </summary>
|
|
public static class XRUtilities
|
|
{
|
|
/// <summary>
|
|
/// A simple Regex pattern that allows InputDeviceMatchers to match to any version of the XRInput interface.
|
|
/// </summary>
|
|
public const string InterfaceMatchAnyVersion = "^(XRInput)";
|
|
|
|
/// <summary>
|
|
/// The initial, now deprecated interface for XRInput. This version handles button packing for Android differently from current.
|
|
/// </summary>
|
|
public const string InterfaceV1 = "XRInput";
|
|
|
|
/// <summary>
|
|
/// The current interface code sent with devices to identify as XRInput devices.
|
|
/// </summary>
|
|
public const string InterfaceCurrent = "XRInputV1";
|
|
}
|
|
|
|
// Sync to UnityXRInputFeatureType in IUnityXRInput.h
|
|
/// <summary>
|
|
/// The type of data a <see cref="XRFeatureDescriptor"/> exposes.
|
|
/// </summary>
|
|
public enum FeatureType
|
|
{
|
|
Custom = 0,
|
|
Binary,
|
|
DiscreteStates,
|
|
Axis1D,
|
|
Axis2D,
|
|
Axis3D,
|
|
Rotation,
|
|
Hand,
|
|
Bone,
|
|
Eyes
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
#pragma warning disable 0649
|
|
[Serializable]
|
|
public struct UsageHint
|
|
{
|
|
public string content;
|
|
}
|
|
|
|
//Sync to XRInputFeatureDefinition in XRInputDeviceDefinition.h
|
|
/// <summary>
|
|
/// Describes an individual input on a device, such as a trackpad, or button, or trigger.
|
|
/// </summary>
|
|
[Serializable]
|
|
public struct XRFeatureDescriptor
|
|
{
|
|
/// <summary>
|
|
/// The name of the feature.
|
|
/// </summary>
|
|
public string name;
|
|
/// <summary>
|
|
/// The uses that this feature should represent, such as trigger, or grip, or touchpad.
|
|
/// </summary>
|
|
public List<UsageHint> usageHints;
|
|
/// <summary>
|
|
/// The type of data this feature exposes.
|
|
/// </summary>
|
|
public FeatureType featureType;
|
|
/// <summary>
|
|
/// The overall size of the feature. This is only filled in when the <see cref="featureType"/> is <see cref="FeatureType.Custom"/>.
|
|
/// </summary>
|
|
public uint customSize;
|
|
}
|
|
|
|
//Sync to XRInputDeviceDefinition in XRInputDeviceDefinition.h
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
[Serializable]
|
|
public class XRDeviceDescriptor
|
|
{
|
|
/// <summary>
|
|
/// The name of the device.
|
|
/// </summary>
|
|
public string deviceName;
|
|
/// <summary>
|
|
/// The manufacturer of the device.
|
|
/// </summary>
|
|
public string manufacturer;
|
|
/// <summary>
|
|
/// The serial number of the device. An empty string if no serial number is available.
|
|
/// </summary>
|
|
public string serialNumber;
|
|
/// <summary>
|
|
/// 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).
|
|
/// </summary>
|
|
public InputDeviceCharacteristics characteristics;
|
|
/// <summary>
|
|
/// The underlying deviceId, this can be used with <see cref="UnityEngine.XR.InputDevices"/> to create a device.
|
|
/// </summary>
|
|
public int deviceId;
|
|
/// <summary>
|
|
/// A list of all input features. <seealso cref="XRFeatureDescriptor"/>
|
|
/// </summary>
|
|
public List<XRFeatureDescriptor> inputFeatures;
|
|
|
|
/// <summary>
|
|
/// Converts this structure to a JSON string.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public string ToJson()
|
|
{
|
|
return JsonUtility.ToJson(this);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts a json string to a new <see cref="XRDeviceDescriptor"/>.
|
|
/// </summary>
|
|
/// <param name="json">The JSON string containing <see cref="XRDeviceDescriptor"/> data.</param>
|
|
/// <returns>A new <see cref="XRDeviceDescriptor"/></returns>
|
|
public static XRDeviceDescriptor FromJson(string json)
|
|
{
|
|
return JsonUtility.FromJson<XRDeviceDescriptor>(json);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents a 3 dimensional, tracked bone within a hierarchy of other bones.
|
|
/// </summary>
|
|
public struct Bone
|
|
{
|
|
/// <summary>
|
|
/// The index with the device's controls array where the parent bone resides.
|
|
/// </summary>
|
|
public uint m_ParentBoneIndex;
|
|
|
|
/// <summary>
|
|
/// The tracked position of the bone.
|
|
/// </summary>
|
|
public Vector3 m_Position;
|
|
|
|
/// <summary>
|
|
/// The tracked rotation of the bone.
|
|
/// </summary>
|
|
public Quaternion m_Rotation;
|
|
|
|
/// <summary>
|
|
/// The index with the device's controls array where the parent bone resides.
|
|
/// </summary>
|
|
public uint parentBoneIndex
|
|
{
|
|
get => m_ParentBoneIndex;
|
|
set => m_ParentBoneIndex = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// The tracked position of the bone.
|
|
/// </summary>
|
|
public Vector3 position
|
|
{
|
|
get => m_Position;
|
|
set => m_Position = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// The tracked rotation of the bone.
|
|
/// </summary>
|
|
public Quaternion rotation
|
|
{
|
|
get => m_Rotation;
|
|
set => m_Rotation = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents a pair of tracked eyes.
|
|
/// </summary>
|
|
public struct Eyes
|
|
{
|
|
/// <summary>
|
|
/// The tracked position of the left eye.
|
|
/// </summary>
|
|
public Vector3 m_LeftEyePosition;
|
|
/// <summary>
|
|
/// The tracked rotation of the left eye.
|
|
/// </summary>
|
|
public Quaternion m_LeftEyeRotation;
|
|
/// <summary>
|
|
/// The tracked position of the right eye.
|
|
/// </summary>
|
|
public Vector3 m_RightEyePosition;
|
|
/// <summary>
|
|
/// The tracked rotation of the right eye.
|
|
/// </summary>
|
|
public Quaternion m_RightEyeRotation;
|
|
/// <summary>
|
|
/// The point in 3D space that the pair of eyes is looking.
|
|
/// </summary>
|
|
public Vector3 m_FixationPoint;
|
|
/// <summary>
|
|
/// The amount [0-1] the left eye is open or closed. 1.0 is fully open.
|
|
/// </summary>
|
|
public float m_LeftEyeOpenAmount;
|
|
/// <summary>
|
|
/// The amount [0-1] the right eye is open or closed. 1.0 is fully open.
|
|
/// </summary>
|
|
public float m_RightEyeOpenAmount;
|
|
|
|
/// <summary>
|
|
/// The tracked position of the left eye.
|
|
/// </summary>
|
|
public Vector3 leftEyePosition
|
|
{
|
|
get => m_LeftEyePosition;
|
|
set => m_LeftEyePosition = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// The tracked rotation of the left eye.
|
|
/// </summary>
|
|
public Quaternion leftEyeRotation
|
|
{
|
|
get => m_LeftEyeRotation;
|
|
set => m_LeftEyeRotation = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// The tracked position of the right eye.
|
|
/// </summary>
|
|
public Vector3 rightEyePosition
|
|
{
|
|
get => m_RightEyePosition;
|
|
set => m_RightEyePosition = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// The tracked rotation of the right eye.
|
|
/// </summary>
|
|
public Quaternion rightEyeRotation
|
|
{
|
|
get => m_RightEyeRotation;
|
|
set => m_RightEyeRotation = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// The point in 3D space that the pair of eyes is looking.
|
|
/// </summary>
|
|
public Vector3 fixationPoint
|
|
{
|
|
get => m_FixationPoint;
|
|
set => m_FixationPoint = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// The amount [0-1] the left eye is open or closed. 1.0 is fully open.
|
|
/// </summary>
|
|
public float leftEyeOpenAmount
|
|
{
|
|
get => m_LeftEyeOpenAmount;
|
|
set => m_LeftEyeOpenAmount = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// The amount [0-1] the right eye is open or closed. 1.0 is fully open.
|
|
/// </summary>
|
|
public float rightEyeOpenAmount
|
|
{
|
|
get => m_RightEyeOpenAmount;
|
|
set => m_RightEyeOpenAmount = value;
|
|
}
|
|
}
|
|
|
|
public class BoneControl : InputControl<Bone>
|
|
{
|
|
[InputControl(offset = 0, displayName = "parentBoneIndex")]
|
|
public IntegerControl parentBoneIndex { get; set; }
|
|
[InputControl(offset = 4, displayName = "Position")]
|
|
public Vector3Control position { get; set; }
|
|
[InputControl(offset = 16, displayName = "Rotation")]
|
|
public QuaternionControl rotation { get; set; }
|
|
|
|
protected override void FinishSetup()
|
|
{
|
|
parentBoneIndex = GetChildControl<IntegerControl>("parentBoneIndex");
|
|
position = GetChildControl<Vector3Control>("position");
|
|
rotation = GetChildControl<QuaternionControl>("rotation");
|
|
|
|
base.FinishSetup();
|
|
}
|
|
|
|
public override unsafe Bone ReadUnprocessedValueFromState(void* statePtr)
|
|
{
|
|
return new Bone()
|
|
{
|
|
parentBoneIndex = (uint)parentBoneIndex.ReadUnprocessedValueFromStateWithCaching(statePtr),
|
|
position = position.ReadUnprocessedValueFromStateWithCaching(statePtr),
|
|
rotation = rotation.ReadUnprocessedValueFromStateWithCaching(statePtr)
|
|
};
|
|
}
|
|
|
|
public override unsafe void WriteValueIntoState(Bone value, void* statePtr)
|
|
{
|
|
parentBoneIndex.WriteValueIntoState((int)value.parentBoneIndex, statePtr);
|
|
position.WriteValueIntoState(value.position, statePtr);
|
|
rotation.WriteValueIntoState(value.rotation, statePtr);
|
|
}
|
|
}
|
|
|
|
public class EyesControl : InputControl<Eyes>
|
|
{
|
|
[InputControl(offset = 0, displayName = "LeftEyePosition")]
|
|
public Vector3Control leftEyePosition { get; set; }
|
|
[InputControl(offset = 12, displayName = "LeftEyeRotation")]
|
|
public QuaternionControl leftEyeRotation { get; set; }
|
|
[InputControl(offset = 28, displayName = "RightEyePosition")]
|
|
public Vector3Control rightEyePosition { get; set; }
|
|
[InputControl(offset = 40, displayName = "RightEyeRotation")]
|
|
public QuaternionControl rightEyeRotation { get; set; }
|
|
[InputControl(offset = 56, displayName = "FixationPoint")]
|
|
public Vector3Control fixationPoint { get; set; }
|
|
[InputControl(offset = 68, displayName = "LeftEyeOpenAmount")]
|
|
public AxisControl leftEyeOpenAmount { get; set; }
|
|
[InputControl(offset = 72, displayName = "RightEyeOpenAmount")]
|
|
public AxisControl rightEyeOpenAmount { get; set; }
|
|
|
|
protected override void FinishSetup()
|
|
{
|
|
leftEyePosition = GetChildControl<Vector3Control>("leftEyePosition");
|
|
leftEyeRotation = GetChildControl<QuaternionControl>("leftEyeRotation");
|
|
rightEyePosition = GetChildControl<Vector3Control>("rightEyePosition");
|
|
rightEyeRotation = GetChildControl<QuaternionControl>("rightEyeRotation");
|
|
fixationPoint = GetChildControl<Vector3Control>("fixationPoint");
|
|
leftEyeOpenAmount = GetChildControl<AxisControl>("leftEyeOpenAmount");
|
|
rightEyeOpenAmount = GetChildControl<AxisControl>("rightEyeOpenAmount");
|
|
|
|
base.FinishSetup();
|
|
}
|
|
|
|
public override unsafe Eyes ReadUnprocessedValueFromState(void* statePtr)
|
|
{
|
|
return new Eyes()
|
|
{
|
|
leftEyePosition = leftEyePosition.ReadUnprocessedValueFromStateWithCaching(statePtr),
|
|
leftEyeRotation = leftEyeRotation.ReadUnprocessedValueFromStateWithCaching(statePtr),
|
|
rightEyePosition = rightEyePosition.ReadUnprocessedValueFromStateWithCaching(statePtr),
|
|
rightEyeRotation = rightEyeRotation.ReadUnprocessedValueFromStateWithCaching(statePtr),
|
|
fixationPoint = fixationPoint.ReadUnprocessedValueFromStateWithCaching(statePtr),
|
|
leftEyeOpenAmount = leftEyeOpenAmount.ReadUnprocessedValueFromStateWithCaching(statePtr),
|
|
rightEyeOpenAmount = rightEyeOpenAmount.ReadUnprocessedValueFromStateWithCaching(statePtr)
|
|
};
|
|
}
|
|
|
|
public override unsafe void WriteValueIntoState(Eyes value, void* statePtr)
|
|
{
|
|
leftEyePosition.WriteValueIntoState(value.leftEyePosition, statePtr);
|
|
leftEyeRotation.WriteValueIntoState(value.leftEyeRotation, statePtr);
|
|
rightEyePosition.WriteValueIntoState(value.rightEyePosition, statePtr);
|
|
rightEyeRotation.WriteValueIntoState(value.rightEyeRotation, statePtr);
|
|
fixationPoint.WriteValueIntoState(value.fixationPoint, statePtr);
|
|
leftEyeOpenAmount.WriteValueIntoState(value.leftEyeOpenAmount, statePtr);
|
|
rightEyeOpenAmount.WriteValueIntoState(value.rightEyeOpenAmount, statePtr);
|
|
}
|
|
}
|
|
#pragma warning restore 0649
|
|
|
|
/// <summary>
|
|
/// A small helper class to aid in initializing and registering XR devices and layout builders.
|
|
/// </summary>
|
|
#if UNITY_DISABLE_DEFAULT_INPUT_PLUGIN_INITIALIZATION
|
|
public
|
|
#else
|
|
internal
|
|
#endif
|
|
static class XRSupport
|
|
{
|
|
/// <summary>
|
|
/// Registers all initial templates and the generalized layout builder with the InputSystem.
|
|
/// </summary>
|
|
public static void Initialize()
|
|
{
|
|
#if !UNITY_FORCE_INPUTSYSTEM_XR_OFF
|
|
InputSystem.RegisterLayout<PoseControl>("Pose");
|
|
InputSystem.RegisterLayout<BoneControl>("Bone");
|
|
InputSystem.RegisterLayout<EyesControl>("Eyes");
|
|
|
|
InputSystem.RegisterLayout<XRHMD>();
|
|
InputSystem.RegisterLayout<XRController>();
|
|
|
|
InputSystem.onFindLayoutForDevice += XRLayoutBuilder.OnFindLayoutForDevice;
|
|
|
|
// Built-in layouts replaced by the com.unity.xr.windowsmr package.
|
|
#if !DISABLE_BUILTIN_INPUT_SYSTEM_WINDOWSMR
|
|
InputSystem.RegisterLayout<UnityEngine.XR.WindowsMR.Input.WMRHMD>(
|
|
matches: new InputDeviceMatcher()
|
|
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
|
.WithProduct("(Windows Mixed Reality HMD)|(Microsoft HoloLens)|(^(WindowsMR Headset))")
|
|
);
|
|
InputSystem.RegisterLayout<UnityEngine.XR.WindowsMR.Input.WMRSpatialController>(
|
|
matches: new InputDeviceMatcher()
|
|
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
|
.WithProduct(@"(^(Spatial Controller))|(^(OpenVR Controller\(WindowsMR))")
|
|
);
|
|
InputSystem.RegisterLayout<UnityEngine.XR.WindowsMR.Input.HololensHand>(
|
|
matches: new InputDeviceMatcher()
|
|
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
|
.WithProduct(@"(^(Hand -))")
|
|
);
|
|
#endif
|
|
|
|
// Built-in layouts replaced by the com.unity.xr.oculus package.
|
|
#if !DISABLE_BUILTIN_INPUT_SYSTEM_OCULUS
|
|
InputSystem.RegisterLayout<Unity.XR.Oculus.Input.OculusHMD>(
|
|
matches: new InputDeviceMatcher()
|
|
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
|
.WithProduct("^(Oculus Rift)|^(Oculus Quest)|^(Oculus Go)"));
|
|
InputSystem.RegisterLayout<Unity.XR.Oculus.Input.OculusTouchController>(
|
|
matches: new InputDeviceMatcher()
|
|
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
|
.WithProduct(@"(^(Oculus Touch Controller))|(^(Oculus Quest Controller))"));
|
|
InputSystem.RegisterLayout<Unity.XR.Oculus.Input.OculusRemote>(
|
|
matches: new InputDeviceMatcher()
|
|
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
|
.WithProduct(@"Oculus Remote"));
|
|
InputSystem.RegisterLayout<Unity.XR.Oculus.Input.OculusTrackingReference>(
|
|
matches: new InputDeviceMatcher()
|
|
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
|
.WithProduct(@"((Tracking Reference)|(^(Oculus Rift [a-zA-Z0-9]* \(Camera)))"));
|
|
|
|
InputSystem.RegisterLayout<Unity.XR.Oculus.Input.OculusHMDExtended>(
|
|
name: "GearVR",
|
|
matches: new InputDeviceMatcher()
|
|
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
|
.WithProduct("Oculus HMD"));
|
|
InputSystem.RegisterLayout<Unity.XR.Oculus.Input.GearVRTrackedController>(
|
|
matches: new InputDeviceMatcher()
|
|
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
|
.WithProduct("^(Oculus Tracked Remote)"));
|
|
#endif
|
|
|
|
// Built-in layouts replaced by the com.unity.xr.googlevr package.
|
|
#if !DISABLE_BUILTIN_INPUT_SYSTEM_GOOGLEVR
|
|
InputSystem.RegisterLayout<Unity.XR.GoogleVr.DaydreamHMD>(
|
|
matches: new InputDeviceMatcher()
|
|
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
|
.WithProduct("Daydream HMD"));
|
|
InputSystem.RegisterLayout<Unity.XR.GoogleVr.DaydreamController>(
|
|
matches: new InputDeviceMatcher()
|
|
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
|
.WithProduct("^(Daydream Controller)"));
|
|
#endif
|
|
|
|
// Built-in layouts replaced by the com.unity.xr.openvr package.
|
|
#if !DISABLE_BUILTIN_INPUT_SYSTEM_OPENVR
|
|
InputSystem.RegisterLayout<Unity.XR.OpenVR.OpenVRHMD>(
|
|
matches: new InputDeviceMatcher()
|
|
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
|
.WithProduct("^(OpenVR Headset)|^(Vive Pro)")
|
|
);
|
|
InputSystem.RegisterLayout<Unity.XR.OpenVR.OpenVRControllerWMR>(
|
|
matches: new InputDeviceMatcher()
|
|
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
|
.WithProduct("^(OpenVR Controller\\(WindowsMR)")
|
|
);
|
|
InputSystem.RegisterLayout<Unity.XR.OpenVR.ViveWand>(
|
|
matches: new InputDeviceMatcher()
|
|
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
|
.WithManufacturer("HTC")
|
|
.WithProduct(@"^(OpenVR Controller\(((Vive. Controller)|(VIVE. Controller)|(Vive Controller)))")
|
|
);
|
|
InputSystem.RegisterLayout<Unity.XR.OpenVR.OpenVROculusTouchController>(
|
|
matches: new InputDeviceMatcher()
|
|
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
|
.WithProduct(@"^(OpenVR Controller\(Oculus)")
|
|
);
|
|
|
|
InputSystem.RegisterLayout<Unity.XR.OpenVR.ViveTracker>(
|
|
matches: new InputDeviceMatcher()
|
|
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
|
.WithManufacturer("HTC")
|
|
.WithProduct(@"^(VIVE Tracker)")
|
|
);
|
|
InputSystem.RegisterLayout<Unity.XR.OpenVR.HandedViveTracker>(
|
|
matches: new InputDeviceMatcher()
|
|
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
|
.WithManufacturer("HTC")
|
|
.WithProduct(@"^(OpenVR Controller\(VIVE Tracker)")
|
|
);
|
|
InputSystem.RegisterLayout<Unity.XR.OpenVR.ViveLighthouse>(
|
|
matches: new InputDeviceMatcher()
|
|
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
|
.WithManufacturer("HTC")
|
|
.WithProduct(@"^(HTC V2-XD/XE)")
|
|
);
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
#endif
|