#if UNITY_OPENXR_PACKAGE || PACKAGE_DOCS_GENERATION
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Layouts;
using UnityEngine.InputSystem.XR;
using UnityEngine.Scripting;
using UnityEngine.XR.Hands;
using UnityEngine.XR.Management;
using UnityEngine.XR.OpenXR;
using UnityEngine.XR.OpenXR.Input;
using UnityEngine.XR.OpenXR.Features;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace UnityEngine.XR.Hands.OpenXR
{
///
/// This enables the use of Meta's
/// hand-tracking aim data in OpenXR. It will not work without also enabling
/// the feature. It enables
///
/// XR_FB_hand_tracking_aim in the underlying runtime. This creates
/// new s with the
/// characteristic where the
/// and represent the aim pose
/// exposed by this extension.
///
///
/// For this extension to be available, you must install the
///
/// XR Hands package.
///
#if UNITY_EDITOR
[UnityEditor.XR.OpenXR.Features.OpenXRFeature(UiName = "Meta Hand Tracking Aim",
BuildTargetGroups = new[] { BuildTargetGroup.Standalone, BuildTargetGroup.Android },
Company = "Unity",
Desc = "Allows for mapping input to the aim pose extension data. Will create an InputDevice for each hand if this and HandTracking are enabled.",
DocumentationLink = XRHelpURLConstants.k_CurrentManualDocsBaseUrl + "features/metahandtrackingaim.html",
Version = "0.0.1",
OpenxrExtensionStrings = extensionString,
Category = UnityEditor.XR.OpenXR.Features.FeatureCategory.Feature,
FeatureId = featureId)]
#endif
public partial class MetaHandTrackingAim : OpenXRFeature
{
///
/// The feature ID string. This is used to give the feature a well known
/// ID for reference.
///
public const string featureId = "com.unity.openxr.feature.input.metahandtrackingaim";
///
/// The OpenXR Extension string. OpenXR uses this to check if this
/// extension is available or enabled. See
/// Meta hand-tracking aim
/// documentation for more information on this OpenXR extension.
///
public const string extensionString = "XR_FB_hand_tracking_aim";
///
/// The device product name used when creating the s
/// that represent each hand in the extension.
///
const string deviceProductName = "Meta Aim Hand Tracking";
///
/// The device manufacturer name used when creating the s
/// that represent each hand in the extension.
///
const string deviceManufacturerName = "OpenXR Meta";
/// See .
protected override void OnSubsystemStart()
{
if (HandTracking.subsystem == null)
{
HandTracking.subsystemCreated += OnHandSubsystemCreated;
return;
}
Init(HandTracking.subsystem);
}
void OnHandSubsystemCreated(HandTracking.SubsystemCreatedEventArgs eventArgs) => Init(eventArgs.subsystem);
void Init(XRHandSubsystem subsystem)
{
if (NativeApi.ToggleMetaAim(true))
{
CreateHands();
subsystem.updatedHands += OnUpdatedHands;
}
else
{
Debug.LogError("Couldn't enable Meta aim retrieval in plugin - please ensure you enabled the Hand Tracking Subsystem feature in the OpenXR project settings.");
}
}
/// See .
protected override void OnSubsystemStop()
{
NativeApi.ToggleMetaAim(false);
if (HandTracking.subsystem != null)
HandTracking.subsystem.updatedHands -= OnUpdatedHands;
DestroyHands();
HandTracking.subsystemCreated -= OnHandSubsystemCreated;
}
void CreateHands()
{
if (Hands.MetaAimHand.left == null)
Hands.MetaAimHand.left = Hands.MetaAimHand.CreateHand(InputDeviceCharacteristics.Left);
if (Hands.MetaAimHand.right == null)
Hands.MetaAimHand.right = Hands.MetaAimHand.CreateHand(InputDeviceCharacteristics.Right);
}
void DestroyHands()
{
if (Hands.MetaAimHand.left != null)
{
InputSystem.InputSystem.RemoveDevice(Hands.MetaAimHand.left);
Hands.MetaAimHand.left = null;
}
if (Hands.MetaAimHand.right != null)
{
InputSystem.InputSystem.RemoveDevice(Hands.MetaAimHand.right);
Hands.MetaAimHand.right = null;
}
}
void OnUpdatedHands(XRHandSubsystem subsystem, XRHandSubsystem.UpdateSuccessFlags successFlags, XRHandSubsystem.UpdateType updateType)
{
if ((successFlags & (XRHandSubsystem.UpdateSuccessFlags.LeftHandRootPose | XRHandSubsystem.UpdateSuccessFlags.LeftHandJoints)) != 0)
Hands.MetaAimHand.left.UpdateHand(true, (successFlags & XRHandSubsystem.UpdateSuccessFlags.LeftHandRootPose) != 0);
if ((successFlags & (XRHandSubsystem.UpdateSuccessFlags.RightHandRootPose | XRHandSubsystem.UpdateSuccessFlags.RightHandJoints)) != 0)
Hands.MetaAimHand.right.UpdateHand(false, (successFlags & XRHandSubsystem.UpdateSuccessFlags.RightHandRootPose) != 0);
}
static class NativeApi
{
[DllImport(HandTracking.k_LibraryName, EntryPoint = "UnityOpenXRHands_ToggleMetaAim")]
static internal extern bool ToggleMetaAim(bool enable);
}
}
}
#endif // UNITY_OPENXR_PACKAGE || PACKAGE_DOCS_GENERATION