#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