VR4Medical/ICI/Library/PackageCache/com.unity.xr.openxr@3903c1059bcf/Runtime/Features/Interactions/MicrosoftHandInteraction.cs
2025-07-29 13:45:50 +03:00

354 lines
17 KiB
C#

using System.Collections.Generic;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Layouts;
using UnityEngine.InputSystem.XR;
using UnityEngine.Scripting;
using UnityEngine.XR.OpenXR.Input;
#if UNITY_EDITOR
using UnityEditor;
#endif
#if USE_INPUT_SYSTEM_POSE_CONTROL
using PoseControl = UnityEngine.InputSystem.XR.PoseControl;
#else
using PoseControl = UnityEngine.XR.OpenXR.Input.PoseControl;
#endif
namespace UnityEngine.XR.OpenXR.Features.Interactions
{
/// <summary>
/// This <see cref="OpenXRInteractionFeature"/> enables the use of Microsoft hand interaction profiles in OpenXR. It enables <a href="https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XR_MSFT_hand_interaction">XR_MSFT_hand_interaction</a> in the underyling runtime.
/// This creates a new <see cref="InputDevice"/> with the <see cref="InputDeviceCharacteristics.HandTracking"/> characteristic.
/// </summary>
#if UNITY_EDITOR
[UnityEditor.XR.OpenXR.Features.OpenXRFeature(UiName = "Microsoft Hand Interaction Profile",
BuildTargetGroups = new[] { BuildTargetGroup.Standalone, BuildTargetGroup.WSA, BuildTargetGroup.Android },
Company = "Unity",
Desc = "Allows for mapping input to the hand interaction profile. Will register the controller map for hand interaction if enabled.",
DocumentationLink = Constants.k_DocumentationManualURL + "features/microsofthandinteraction.html",
Version = "0.0.1",
OpenxrExtensionStrings = extensionString,
Category = UnityEditor.XR.OpenXR.Features.FeatureCategory.Interaction,
FeatureId = featureId)]
#endif
public class MicrosoftHandInteraction : OpenXRInteractionFeature
{
/// <summary>
/// The feature id string. This is used to give the feature a well known id for reference.
/// </summary>
public const string featureId = "com.unity.openxr.feature.input.handtracking";
/// <summary>
/// An Input System device based off the hand interaction profile in the <a href="https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XR_MSFT_hand_interaction">Hand Interaction Extension</a>. Enabled through <see cref="MicrosoftHandInteraction"/>.
/// </summary>
[Preserve, InputControlLayout(displayName = "Hololens Hand (OpenXR)", commonUsages = new[] { "LeftHand", "RightHand" })]
public class HoloLensHand : XRController
{
/// <summary>
/// An [AxisControl](xref:UnityEngine.InputSystem.Controls.AxisControl) that represents the <see cref="MicrosoftHandInteraction.select"/> OpenXR binding.
/// </summary>
[Preserve, InputControl(usage = "PrimaryAxis")]
public AxisControl select { get; private set; }
/// <summary>
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="MicrosoftHandInteraction.select"/> OpenXR binding.
/// </summary>
[Preserve, InputControl(aliases = new[] { "Primary", "selectbutton" }, usages = new[] { "PrimaryButton" })]
public ButtonControl selectPressed { get; private set; }
/// <summary>
/// An [AxisControl](xref:UnityEngine.InputSystem.Controls.AxisControl) that represents the <see cref="MicrosoftHandInteraction.squeeze"/> OpenXR binding.
/// </summary>
[Preserve, InputControl(alias = "Secondary", usage = "Grip")]
public AxisControl squeeze { get; private set; }
/// <summary>
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="MicrosoftHandInteraction.squeeze"/> OpenXR binding.
/// </summary>
[Preserve, InputControl(aliases = new[] { "GripButton", "squeezeClicked" }, usages = new[] { "GripButton" })]
public ButtonControl squeezePressed { get; private set; }
/// <summary>
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the Microsoft Hand Interaction devicePose OpenXR binding.
/// </summary>
[Preserve, InputControl(offset = 0, alias = "device", usage = "Device")]
public PoseControl devicePose { get; private set; }
/// <summary>
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the Microsoft Hand Interaction pointer OpenXR binding.
/// </summary>
[Preserve, InputControl(offset = 0, usage = "Pointer")]
public PoseControl pointer { get; private set; }
/// <summary>
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) required for backwards compatibility with the XRSDK layouts. This represents the overall tracking state of the device. This value is equivalent to mapping devicePose/isTracked.
/// </summary>
[Preserve, InputControl(offset = 132)]
new public ButtonControl isTracked { get; private set; }
/// <summary>
/// A [IntegerControl](xref:UnityEngine.InputSystem.Controls.IntegerControl) required for backwards compatibility with the XRSDK layouts. This represents the bit flag set to indicate what data is valid. This value is equivalent to mapping devicePose/trackingState.
/// </summary>
[Preserve, InputControl(offset = 136)]
new public IntegerControl trackingState { get; private set; }
/// <summary>
/// A [Vector3Control](xref:UnityEngine.InputSystem.Controls.Vector3Control) required for backwards compatibility with the XRSDK layouts. This is the device position, or grip position. This value is equivalent to mapping devicePose/position.
/// </summary>
[Preserve, InputControl(offset = 20, alias = "gripPosition")]
new public Vector3Control devicePosition { get; private set; }
/// <summary>
/// A [QuaternionControl](xref:UnityEngine.InputSystem.Controls.QuaternionControl) required for backwards compatibility with the XRSDK layouts. This is the device orientation, or grip orientation. This value is equivalent to mapping devicePose/rotation.
/// </summary>
[Preserve, InputControl(offset = 32, alias = "gripOrientation")]
new public QuaternionControl deviceRotation { get; private set; }
/// <summary>
/// A [Vector3Control](xref:UnityEngine.InputSystem.Controls.Vector3Control) required for backwards compatibility with the XRSDK layouts. This is the pointer position. This value is equivalent to mapping pointerPose/position.
/// </summary>
[Preserve, InputControl(offset = 80)]
public Vector3Control pointerPosition { get; private set; }
/// <summary>
/// A [QuaternionControl](xref:UnityEngine.InputSystem.Controls.QuaternionControl) required for backwards compatibility with the XRSDK layouts. This is the pointer rotation. This value is equivalent to mapping pointerPose/rotation.
/// </summary>
[Preserve, InputControl(offset = 92, alias = "pointerOrientation")]
public QuaternionControl pointerRotation { get; private set; }
/// <summary>
/// Internal call used to assign controls to the the correct element.
/// </summary>
protected override void FinishSetup()
{
base.FinishSetup();
select = GetChildControl<AxisControl>("select");
selectPressed = GetChildControl<ButtonControl>("selectPressed");
squeeze = GetChildControl<AxisControl>("squeeze");
squeezePressed = GetChildControl<ButtonControl>("squeezePressed");
devicePose = GetChildControl<PoseControl>("devicePose");
pointer = GetChildControl<PoseControl>("pointer");
isTracked = GetChildControl<ButtonControl>("isTracked");
trackingState = GetChildControl<IntegerControl>("trackingState");
devicePosition = GetChildControl<Vector3Control>("devicePosition");
deviceRotation = GetChildControl<QuaternionControl>("deviceRotation");
pointerPosition = GetChildControl<Vector3Control>("pointerPosition");
pointerRotation = GetChildControl<QuaternionControl>("pointerRotation");
}
}
/// <summary>The OpenXR Extension string. OpenXR uses this to check if this extension is available or enabled. See <a href="https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XR_MSFT_hand_interaction">hand interaction extension</a> documentation for more information on this OpenXR extension.</summary>
public const string extensionString = "XR_MSFT_hand_interaction";
/// <summary>
/// OpenXR string that represents the hand interaction profile.
/// </summary>
public const string profile = "/interaction_profiles/microsoft/hand_interaction";
/// <summary>
/// Constant for a float interaction binding '.../input/select/value' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
/// </summary>
public const string select = "/input/select/value";
/// <summary>
/// Constant for a float interaction binding '.../input/menu/value' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
/// </summary>
public const string squeeze = "/input/squeeze/value";
/// <summary>
/// Constant for a pose interaction binding '.../input/grip/pose' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
/// </summary>
public const string grip = "/input/grip/pose";
/// <summary>
/// Constant for a pose interaction binding '.../input/aim/pose' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
/// </summary>
public const string aim = "/input/aim/pose";
private const string kDeviceLocalizedName = "HoloLens Hand OpenXR";
/// <summary>
/// Registers the <see cref="HoloLensHand"/> layout with the Input System.
/// </summary>
protected override void RegisterDeviceLayout()
{
#if UNITY_EDITOR
if (!OpenXRLoaderEnabledForSelectedBuildTarget(EditorUserBuildSettings.selectedBuildTargetGroup))
return;
#endif
InputSystem.InputSystem.RegisterLayout(typeof(HoloLensHand),
matches: new InputDeviceMatcher()
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
.WithProduct(kDeviceLocalizedName));
}
/// <summary>
/// Removes the <see cref="HoloLensHand"/> layout from the Input System.
/// </summary>
protected override void UnregisterDeviceLayout()
{
#if UNITY_EDITOR
if (!OpenXRLoaderEnabledForSelectedBuildTarget(EditorUserBuildSettings.selectedBuildTargetGroup))
return;
#endif
InputSystem.InputSystem.RemoveLayout(nameof(HoloLensHand));
}
/// <summary>
/// Return device layout string that used for registering device for the Input System.
/// </summary>
/// <returns>Device layout string.</returns>
protected override string GetDeviceLayoutName()
{
return nameof(HoloLensHand);
}
/// <inheritdoc/>
protected override void RegisterActionMapsWithRuntime()
{
ActionMapConfig actionMap = new ActionMapConfig()
{
name = "microsofthandinteraction",
localizedName = kDeviceLocalizedName,
desiredInteractionProfile = profile,
manufacturer = "Microsoft",
serialNumber = "",
deviceInfos = new List<DeviceConfig>()
{
new DeviceConfig()
{
characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.HandTracking | InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.TrackedDevice | InputDeviceCharacteristics.Controller | InputDeviceCharacteristics.Left),
userPath = UserPaths.leftHand
},
new DeviceConfig()
{
characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.HandTracking | InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.TrackedDevice | InputDeviceCharacteristics.Controller | InputDeviceCharacteristics.Right),
userPath = UserPaths.rightHand
}
},
actions = new List<ActionConfig>()
{
// Select
new ActionConfig()
{
name = "select",
localizedName = "Select",
type = ActionType.Axis1D,
usages = new List<string>()
{
"PrimaryAxis"
},
bindings = new List<ActionBinding>()
{
new ActionBinding()
{
interactionPath = select,
interactionProfileName = profile,
}
}
},
// Select Pressed
new ActionConfig()
{
name = "selectPressed",
localizedName = "Select Pressed",
type = ActionType.Binary,
usages = new List<string>()
{
"PrimaryButton"
},
bindings = new List<ActionBinding>()
{
new ActionBinding()
{
interactionPath = select,
interactionProfileName = profile,
}
}
},
// Squeeze
new ActionConfig()
{
name = "squeeze",
localizedName = "Squeeze",
type = ActionType.Axis1D,
usages = new List<string>()
{
"Grip"
},
bindings = new List<ActionBinding>()
{
new ActionBinding()
{
interactionPath = squeeze,
interactionProfileName = profile,
}
}
},
// Squeeze Pressed
new ActionConfig()
{
name = "squeezePressed",
localizedName = "Squeeze Pressed",
type = ActionType.Binary,
usages = new List<string>()
{
"GripButton"
},
bindings = new List<ActionBinding>()
{
new ActionBinding()
{
interactionPath = squeeze,
interactionProfileName = profile,
}
}
},
// Device Pose
new ActionConfig()
{
name = "devicePose",
localizedName = "Device Pose",
type = ActionType.Pose,
usages = new List<string>()
{
"Device"
},
bindings = new List<ActionBinding>()
{
new ActionBinding()
{
interactionPath = grip,
interactionProfileName = profile,
}
}
},
// Pointer Pose
new ActionConfig()
{
name = "pointer",
localizedName = "Pointer Pose",
type = ActionType.Pose,
usages = new List<string>()
{
"Pointer"
},
bindings = new List<ActionBinding>()
{
new ActionBinding()
{
interactionPath = aim,
interactionProfileName = profile,
}
}
}
}
};
AddActionMap(actionMap);
}
}
}