// Copyright (c) Meta Platforms, Inc. and affiliates. #include "OculusXRSystemInfoExtensionPlugin.h" #include "IOpenXRHMDModule.h" #include "OculusXRAssetDirectory.h" #include "OculusXRXRFunctions.h" #include "OculusXROpenXRUtilities.h" #include "OculusXRHMDRuntimeSettings.h" DEFINE_LOG_CATEGORY(LogOculusSystemInfoExtensionPlugin); namespace OculusXR { enum EOculusAsset { LeftTouchRiftS, RightTouchRiftS, LeftTouchQuest2, RightTouchQuest2, LeftTouchQuestPro, RightTouchQuestPro, LeftTouchQuest3, RightTouchQuest3, OculusAssetTotal }; struct FRenderableDevice { FString Device; EOculusXRDeviceType MinDeviceRange; EOculusXRDeviceType MaxDeviceRange; FSoftObjectPath MeshAssetRef; }; static FRenderableDevice RenderableDevices[] = { #if PLATFORM_ANDROID // Quest 1 & 2 { "/user/hand/left", EOculusXRDeviceType::OculusQuest_Deprecated, EOculusXRDeviceType::OculusQuest2, FOculusAssetDirectory::AssetListing[LeftTouchQuest2] }, { "/user/hand/right", EOculusXRDeviceType::OculusQuest_Deprecated, EOculusXRDeviceType::OculusQuest2, FOculusAssetDirectory::AssetListing[RightTouchQuest2] }, // Quest Pro { "/user/hand/left", EOculusXRDeviceType::MetaQuestPro, EOculusXRDeviceType::MetaQuestPro, FOculusAssetDirectory::AssetListing[LeftTouchQuestPro] }, { "/user/hand/right", EOculusXRDeviceType::MetaQuestPro, EOculusXRDeviceType::MetaQuestPro, FOculusAssetDirectory::AssetListing[RightTouchQuestPro] }, // Quest 3 & 3s { "/user/hand/left", EOculusXRDeviceType::MetaQuest3, EOculusXRDeviceType::MetaQuest3S, FOculusAssetDirectory::AssetListing[LeftTouchQuest3] }, { "/user/hand/right", EOculusXRDeviceType::MetaQuest3, EOculusXRDeviceType::MetaQuest3S, FOculusAssetDirectory::AssetListing[RightTouchQuest3] }, #else // PC - Rift S { "/user/hand/left", EOculusXRDeviceType::Rift_S, EOculusXRDeviceType::Rift_S, FOculusAssetDirectory::AssetListing[LeftTouchRiftS] }, { "/user/hand/right", EOculusXRDeviceType::Rift_S, EOculusXRDeviceType::Rift_S, FOculusAssetDirectory::AssetListing[RightTouchRiftS] }, // PC - Quest 1 & 2 { "/user/hand/left", EOculusXRDeviceType::Quest_Link_Deprecated, EOculusXRDeviceType::Quest2_Link, FOculusAssetDirectory::AssetListing[LeftTouchQuest2] }, { "/user/hand/right", EOculusXRDeviceType::Quest_Link_Deprecated, EOculusXRDeviceType::Quest2_Link, FOculusAssetDirectory::AssetListing[RightTouchQuest2] }, // PC - Quest Pro { "/user/hand/left", EOculusXRDeviceType::MetaQuestProLink, EOculusXRDeviceType::MetaQuestProLink, FOculusAssetDirectory::AssetListing[LeftTouchQuestPro] }, { "/user/hand/right", EOculusXRDeviceType::MetaQuestProLink, EOculusXRDeviceType::MetaQuestProLink, FOculusAssetDirectory::AssetListing[RightTouchQuestPro] }, // Quest 3 & 3s { "/user/hand/left", EOculusXRDeviceType::MetaQuest3Link, EOculusXRDeviceType::MetaQuest3SLink, FOculusAssetDirectory::AssetListing[LeftTouchQuest3] }, { "/user/hand/right", EOculusXRDeviceType::MetaQuest3Link, EOculusXRDeviceType::MetaQuest3SLink, FOculusAssetDirectory::AssetListing[RightTouchQuest3] }, #endif }; static uint32 RenderableDeviceCount = sizeof(RenderableDevices) / sizeof(RenderableDevices[0]); FSoftObjectPath FindDeviceMesh(FString DevicePath, EOculusXRDeviceType SystemDeviceType) { if (DevicePath == "") { return NULL; } for (uint32 DeviceIndex = 0; DeviceIndex < RenderableDeviceCount; ++DeviceIndex) { const FRenderableDevice& RenderableDevice = RenderableDevices[DeviceIndex]; if (RenderableDevice.Device == DevicePath) { // If we have information about the current headset, load the model based of the headset information, otherwise load defaults. if (SystemDeviceType != EOculusXRDeviceType::OculusUnknown) { if (SystemDeviceType >= RenderableDevice.MinDeviceRange && SystemDeviceType <= RenderableDevice.MaxDeviceRange) { return RenderableDevice.MeshAssetRef; break; } } else { return RenderableDevice.MeshAssetRef; } } } return NULL; } namespace // anonymous { void AppendToChain(XrBaseOutStructure* ToAppend, XrBaseOutStructure* Chain) { while (Chain->next != XR_NULL_HANDLE) { if (Chain->next == ToAppend) { return; } Chain = Chain->next; } Chain->next = ToAppend; } bool IsEqualUuid(const XrUuidEXT& a, const XrUuidEXT& b) { return FMemory::Memcmp(&a, &b, sizeof(XrUuidEXT)) == 0; } XrColorSpaceFB ToXrColorSpace(EOculusXRColorSpace ColorSpace) { XrColorSpaceFB XrColorSpace = XR_COLOR_SPACE_UNMANAGED_FB; switch (ColorSpace) { case EOculusXRColorSpace::Unmanaged: XrColorSpace = XR_COLOR_SPACE_UNMANAGED_FB; break; case EOculusXRColorSpace::Rec_2020: XrColorSpace = XR_COLOR_SPACE_REC2020_FB; break; case EOculusXRColorSpace::Rec_709: XrColorSpace = XR_COLOR_SPACE_REC709_FB; break; case EOculusXRColorSpace::Rift_CV1: XrColorSpace = XR_COLOR_SPACE_RIFT_CV1_FB; break; case EOculusXRColorSpace::Rift_S: XrColorSpace = XR_COLOR_SPACE_RIFT_S_FB; break; case EOculusXRColorSpace::Quest: XrColorSpace = XR_COLOR_SPACE_QUEST_FB; break; case EOculusXRColorSpace::P3: XrColorSpace = XR_COLOR_SPACE_P3_FB; break; case EOculusXRColorSpace::Adobe_RGB: XrColorSpace = XR_COLOR_SPACE_ADOBE_RGB_FB; break; } return XrColorSpace; } EOculusXRColorSpace ToOculusXRColorSpace(XrColorSpaceFB InXrColorSpace) { EOculusXRColorSpace ColorSpace = EOculusXRColorSpace::Unknown; switch (InXrColorSpace) { case XR_COLOR_SPACE_UNMANAGED_FB: ColorSpace = EOculusXRColorSpace::Unmanaged; break; case XR_COLOR_SPACE_REC2020_FB: ColorSpace = EOculusXRColorSpace::Rec_2020; break; case XR_COLOR_SPACE_REC709_FB: ColorSpace = EOculusXRColorSpace::Rec_709; break; case XR_COLOR_SPACE_RIFT_CV1_FB: ColorSpace = EOculusXRColorSpace::Rift_CV1; break; case XR_COLOR_SPACE_RIFT_S_FB: ColorSpace = EOculusXRColorSpace::Rift_S; break; case XR_COLOR_SPACE_QUEST_FB: ColorSpace = EOculusXRColorSpace::Quest; break; case XR_COLOR_SPACE_P3_FB: ColorSpace = EOculusXRColorSpace::P3; break; case XR_COLOR_SPACE_ADOBE_RGB_FB: ColorSpace = EOculusXRColorSpace::Adobe_RGB; break; default: ColorSpace = EOculusXRColorSpace::Unknown; } return ColorSpace; } } // namespace FSystemInfoExtensionPlugin::FSystemInfoExtensionPlugin() : Instance(XR_NULL_HANDLE) , Session(XR_NULL_HANDLE) , SystemId(XR_NULL_SYSTEM_ID) , bExtHeadsetIdAvailable(false) , SystemHeadsetId{} , bSystemHeadsetIdValid(false) , SystemProductName{} , bExtDisplayRefreshAvailible(false) , bExtColorspaceAvailable(false) , bExtPassthroughAvailable(false) , bExtPassthroughPreferencesAvailable(false) { } bool FSystemInfoExtensionPlugin::GetRequiredExtensions(TArray& OutExtensions) { return true; } bool FSystemInfoExtensionPlugin::GetOptionalExtensions(TArray& OutExtensions) { OutExtensions.Add(XR_META_HEADSET_ID_EXTENSION_NAME); OutExtensions.Add(XR_FB_DISPLAY_REFRESH_RATE_EXTENSION_NAME); OutExtensions.Add(XR_FB_COLOR_SPACE_EXTENSION_NAME); OutExtensions.Add(XR_META_PASSTHROUGH_PREFERENCES_EXTENSION_NAME); return true; } void FSystemInfoExtensionPlugin::PostCreateInstance(XrInstance InInstance) { Instance = InInstance; } const void* FSystemInfoExtensionPlugin::OnCreateInstance(class IOpenXRHMDModule* InModule, const void* InNext) { if (InModule != nullptr) { bExtHeadsetIdAvailable = InModule->IsExtensionEnabled(XR_META_HEADSET_ID_EXTENSION_NAME); bExtDisplayRefreshAvailible = InModule->IsExtensionEnabled(XR_FB_DISPLAY_REFRESH_RATE_EXTENSION_NAME); bExtColorspaceAvailable = InModule->IsExtensionEnabled(XR_FB_COLOR_SPACE_EXTENSION_NAME); bExtPassthroughAvailable = InModule->IsExtensionEnabled(XR_FB_PASSTHROUGH_EXTENSION_NAME); bExtPassthroughPreferencesAvailable = InModule->IsExtensionEnabled(XR_META_PASSTHROUGH_PREFERENCES_EXTENSION_NAME); } return IOculusXRExtensionPlugin::OnCreateInstance(InModule, InNext); } void FSystemInfoExtensionPlugin::PostCreateSession(XrSession InSession) { Session = InSession; XrSystemGetInfo SystemGetInfo = { XR_TYPE_SYSTEM_GET_INFO }; SystemGetInfo.formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY; ENSURE_XRCMD(xrGetSystem(Instance, &SystemGetInfo, &SystemId)); XrSystemHeadsetIdPropertiesMETA SystemHeadsetIdProperties = { XR_TYPE_SYSTEM_HEADSET_ID_PROPERTIES_META }; XrSystemProperties SystemProperties = { XR_TYPE_SYSTEM_PROPERTIES }; if (bExtHeadsetIdAvailable) { AppendToChain( reinterpret_cast(&SystemHeadsetIdProperties), reinterpret_cast(&SystemProperties)); } ENSURE_XRCMD(xrGetSystemProperties(Instance, SystemId, &SystemProperties)); if (bExtHeadsetIdAvailable) { SystemHeadsetId = SystemHeadsetIdProperties.id; bSystemHeadsetIdValid = true; } SystemProductName = SystemProperties.systemName; SystemDeviceType = GetSystemHeadsetType(); const UOculusXRHMDRuntimeSettings* HMDSettings = GetDefault(); SetColorSpace(HMDSettings->ColorSpace); ControllerPaths.TouchControllerPath = FOpenXRPath("/interaction_profiles/oculus/touch_controller"); ControllerPaths.TouchControllerProPath = FOpenXRPath("/interaction_profiles/facebook/touch_controller_pro"); ControllerPaths.TouchControllerPlusPath = FOpenXRPath("/interaction_profiles/meta/touch_controller_plus"); ControllerPaths.LeftHandPath = FOpenXRPath("/user/hand/left"); ControllerPaths.RightHandPath = FOpenXRPath("/user/hand/right"); } bool FSystemInfoExtensionPlugin::GetControllerModel(XrInstance InInstance, XrPath InInteractionProfile, XrPath InDevicePath, FSoftObjectPath& OutPath) { if (InDevicePath == XR_NULL_PATH) { return false; } const FString DevicePath = FOpenXRPath(InDevicePath).ToString(); OutPath = FindDeviceMesh(DevicePath, SystemDeviceType); return OutPath.IsValid(); } void FSystemInfoExtensionPlugin::GetControllerModelsForCooking(TArray& OutPaths) { OutPaths.Append(FOculusAssetDirectory::AssetListing, OculusAssetTotal); } EOculusXRDeviceType FSystemInfoExtensionPlugin::GetDeviceType() { return SystemDeviceType; } EOculusXRDeviceType FSystemInfoExtensionPlugin::GetSystemHeadsetType() { // Magic legacy conversion paths from ovrplugin #if defined(__ANDROID__) constexpr XrUuidEXT XR_HEADSET_ID_QUEST = { { 0x4c, 0xa2, 0xf7, 0x94, 0xaf, 0x6a, 0x46, 0x9d, 0xbb, 0xe5, 0x1f, 0x7f, 0xce, 0xef, 0x7b, 0xad } }; constexpr XrUuidEXT XR_HEADSET_ID_QUEST2 = { { 0x30, 0x64, 0xf2, 0x39, 0x15, 0xed, 0x47, 0x22, 0xa6, 0x59, 0x5e, 0xa1, 0xec, 0xd8, 0x99, 0xc2 } }; // Quest Pro constexpr XrUuidEXT XR_HEADSET_ID_QUEST_PRO = { { 0xb5, 0x84, 0x43, 0xc9, 0xdf, 0x86, 0x40, 0xcd, 0x89, 0x18, 0x2a, 0x27, 0x8e, 0x18, 0xab, 0x71 } }; // Quest 3 constexpr XrUuidEXT XR_HEADSET_ID_QUEST_3 = { { 0x08, 0x27, 0x46, 0xba, 0xa0, 0x71, 0x4c, 0xf7, 0x8f, 0x87, 0xba, 0xde, 0x5c, 0xce, 0x43, 0xce } }; // Quest 3S constexpr XrUuidEXT XR_HEADSET_ID_QUEST_3S = { { 0x95, 0x10, 0x49, 0x2b, 0x0d, 0x42, 0x48, 0x72, 0xbc, 0xf4, 0xfb, 0x1a, 0x8d, 0xef, 0x6f, 0x0e } }; #else // PC Headsets constexpr XrUuidEXT XR_HEADSET_ID_RIFT_CV1 = { { 0xbe, 0x4f, 0x8d, 0x7c, 0x8e, 0x33, 0x4d, 0xa2, 0xbf, 0x54, 0xda, 0xd9, 0xea, 0x57, 0x54, 0x9f } }; constexpr XrUuidEXT XR_HEADSET_ID_RIFT_S = { { 0x0d, 0x42, 0xaa, 0xc6, 0x7f, 0x1c, 0x46, 0x27, 0x9c, 0xc5, 0x2c, 0xba, 0x8b, 0x0b, 0xaf, 0xfc } }; constexpr XrUuidEXT XR_HEADSET_ID_QUEST_LINK = { { 0x2f, 0x03, 0x26, 0xc0, 0x09, 0xeb, 0x4d, 0xa9, 0x9a, 0x88, 0x4c, 0xc2, 0x93, 0x53, 0x0a, 0xb2 } }; constexpr XrUuidEXT XR_HEADSET_ID_QUEST2_LINK = { { 0x52, 0x50, 0x78, 0xa5, 0x5a, 0xab, 0x4d, 0xc9, 0xb8, 0x02, 0x1e, 0xbd, 0x6c, 0x7c, 0xff, 0xf4 } }; // Quest Pro constexpr XrUuidEXT XR_HEADSET_ID_QUEST_PRO_LINK = { { 0x99, 0x09, 0x86, 0xc7, 0x9b, 0xad, 0x47, 0x5f, 0x89, 0x83, 0xc1, 0xc7, 0xbd, 0x49, 0xad, 0x51 } }; // Quest 3 constexpr XrUuidEXT XR_HEADSET_ID_QUEST_3_LINK = { { 0x64, 0x09, 0xe3, 0xb3, 0x50, 0x89, 0x4e, 0xd6, 0x86, 0x8e, 0xaa, 0xed, 0x82, 0xda, 0x36, 0x76 } }; // Quest 3S constexpr XrUuidEXT XR_HEADSET_ID_QUEST_3S_LINK = { { 0x8c, 0x2e, 0xc4, 0x47, 0xac, 0x73, 0x41, 0x9f, 0x90, 0x96, 0x36, 0xa7, 0x72, 0x33, 0x78, 0x62 } }; #endif // defined(__ANDROID__) #if defined(__ANDROID__) if (bSystemHeadsetIdValid) { UE_LOG(LogOculusSystemInfoExtensionPlugin, Log, TEXT("UID %x %x %x %x - %x %x %x %x - %x %x %x %x - %x %x %x %x"), SystemHeadsetId.data[0], SystemHeadsetId.data[1], SystemHeadsetId.data[2], SystemHeadsetId.data[3], SystemHeadsetId.data[4], SystemHeadsetId.data[5], SystemHeadsetId.data[6], SystemHeadsetId.data[7], SystemHeadsetId.data[8], SystemHeadsetId.data[9], SystemHeadsetId.data[10], SystemHeadsetId.data[11], SystemHeadsetId.data[12], SystemHeadsetId.data[13], SystemHeadsetId.data[14], SystemHeadsetId.data[15]); if (IsEqualUuid(SystemHeadsetId, XR_HEADSET_ID_QUEST)) { return EOculusXRDeviceType::OculusQuest_Deprecated; } else if (IsEqualUuid(SystemHeadsetId, XR_HEADSET_ID_QUEST2)) { return EOculusXRDeviceType::OculusQuest2; } else if (IsEqualUuid(SystemHeadsetId, XR_HEADSET_ID_QUEST_PRO)) { return EOculusXRDeviceType::MetaQuestPro; } else if (IsEqualUuid(SystemHeadsetId, XR_HEADSET_ID_QUEST_3)) { return EOculusXRDeviceType::MetaQuest3; } else if (IsEqualUuid(SystemHeadsetId, XR_HEADSET_ID_QUEST_3S)) { return EOculusXRDeviceType::MetaQuest3S; } else { return EOculusXRDeviceType::OculusQuest2; // return Quest 2 as the default headset type } } else { if (SystemProductName == TEXT("Oculus Quest")) { return EOculusXRDeviceType::OculusQuest_Deprecated; } else if (SystemProductName == TEXT("Oculus Quest2")) { return EOculusXRDeviceType::OculusQuest2; } else if (SystemProductName == TEXT("Meta Quest Pro") || SystemProductName == TEXT("Oculus Headset1")) { return EOculusXRDeviceType::MetaQuestPro; } else if (SystemProductName == TEXT("Meta Quest 3") || SystemProductName == TEXT("Oculus Headset2")) { return EOculusXRDeviceType::MetaQuest3; } else if (SystemProductName == TEXT("Meta Quest 3S") || SystemProductName == TEXT("Oculus Headset3")) { return EOculusXRDeviceType::MetaQuest3S; } else { return EOculusXRDeviceType::OculusQuest2; // return Quest 2 as the default headset type } } #else if (bSystemHeadsetIdValid) { if (IsEqualUuid(SystemHeadsetId, XR_HEADSET_ID_RIFT_CV1)) { return EOculusXRDeviceType::Rift; } else if (IsEqualUuid(SystemHeadsetId, XR_HEADSET_ID_RIFT_S)) { return EOculusXRDeviceType::Rift_S; } else if (IsEqualUuid(SystemHeadsetId, XR_HEADSET_ID_QUEST_LINK)) { return EOculusXRDeviceType::Quest_Link_Deprecated; } else if (IsEqualUuid(SystemHeadsetId, XR_HEADSET_ID_QUEST2_LINK)) { return EOculusXRDeviceType::Quest2_Link; } else if (IsEqualUuid(SystemHeadsetId, XR_HEADSET_ID_QUEST_PRO_LINK)) { return EOculusXRDeviceType::MetaQuestProLink; } else if (IsEqualUuid(SystemHeadsetId, XR_HEADSET_ID_QUEST_3_LINK)) { return EOculusXRDeviceType::MetaQuest3Link; } else if (IsEqualUuid(SystemHeadsetId, XR_HEADSET_ID_QUEST_3S_LINK)) { return EOculusXRDeviceType::MetaQuest3SLink; } else { return EOculusXRDeviceType::Quest2_Link; // return Quest 2 (over Link) as the default headset type } } else { if (SystemProductName == TEXT("Oculus Rift S")) { return EOculusXRDeviceType::Rift_S; } else if (SystemProductName == TEXT("Oculus Rift CV1")) { return EOculusXRDeviceType::Rift; } else { return EOculusXRDeviceType::Quest2_Link; // return Quest 2 (over Link) as the default headset type } } #endif // defined(__ANDROID__) } TArray FSystemInfoExtensionPlugin::GetSystemDisplayAvailableFrequencies() { TArray DisplayFrequencies; if (bExtDisplayRefreshAvailible) { check(xrEnumerateDisplayRefreshRatesFB.GetValue() != nullptr); uint32 TotalRates = 0; ENSURE_XRCMD(xrEnumerateDisplayRefreshRatesFB.GetValue()(Session, 0, &TotalRates, nullptr)); DisplayFrequencies.Init(0, TotalRates); ENSURE_XRCMD(xrEnumerateDisplayRefreshRatesFB.GetValue()(Session, TotalRates, &TotalRates, DisplayFrequencies.GetData())); } return DisplayFrequencies; } float FSystemInfoExtensionPlugin::GetSystemDisplayFrequency() { float Frequency = 0.0f; if (bExtDisplayRefreshAvailible) { check(xrGetDisplayRefreshRateFB.GetValue() != nullptr); ENSURE_XRCMD(xrGetDisplayRefreshRateFB.GetValue()(Session, &Frequency)); } return Frequency; } void FSystemInfoExtensionPlugin::SetSystemDisplayFrequency(float DisplayFrequency) { if (bExtDisplayRefreshAvailible) { check(xrRequestDisplayRefreshRateFB.GetValue() != nullptr); ENSURE_XRCMD(xrRequestDisplayRefreshRateFB.GetValue()(Session, DisplayFrequency)); } } void FSystemInfoExtensionPlugin::SetColorSpace(EOculusXRColorSpace ColorSpace) { if (bExtColorspaceAvailable) { XrColorSpaceFB XrColorSpace = ToXrColorSpace(ColorSpace); check(xrSetColorSpaceFB.GetValue() != nullptr); ENSURE_XRCMD(xrSetColorSpaceFB.GetValue()(Session, XrColorSpace)); } } EOculusXRColorSpace FSystemInfoExtensionPlugin::GetColorSpace() { EOculusXRColorSpace ColorSpace = EOculusXRColorSpace::Unknown; if (bExtColorspaceAvailable) { XrSystemColorSpacePropertiesFB ColorSpaceProperties = { XR_TYPE_SYSTEM_COLOR_SPACE_PROPERTIES_FB }; XrSystemProperties SystemProperties = { XR_TYPE_SYSTEM_PROPERTIES, &ColorSpaceProperties }; ENSURE_XRCMD(xrGetSystemProperties(Instance, SystemId, &SystemProperties)); ColorSpace = ToOculusXRColorSpace(ColorSpaceProperties.colorSpace); } return ColorSpace; } bool FSystemInfoExtensionPlugin::IsPassthroughSupported() { if (bExtPassthroughAvailable) { XrSystemPassthroughProperties2FB PassthroughProperties = { XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES2_FB }; XrSystemProperties SystemProperties = { XR_TYPE_SYSTEM_PROPERTIES, &PassthroughProperties }; XR_ENSURE(xrGetSystemProperties(Instance, SystemId, &SystemProperties)); return (PassthroughProperties.capabilities & XR_PASSTHROUGH_CAPABILITY_BIT_FB) == XR_PASSTHROUGH_CAPABILITY_BIT_FB; } return false; } bool FSystemInfoExtensionPlugin::IsColorPassthroughSupported() { if (bExtPassthroughAvailable) { XrSystemPassthroughProperties2FB PassthroughProperties = { XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES2_FB }; XrSystemProperties SystemProperties = { XR_TYPE_SYSTEM_PROPERTIES, &PassthroughProperties }; XR_ENSURE(xrGetSystemProperties(Instance, SystemId, &SystemProperties)); return (PassthroughProperties.capabilities & XR_PASSTHROUGH_CAPABILITY_COLOR_BIT_FB) == XR_PASSTHROUGH_CAPABILITY_COLOR_BIT_FB; } return false; } bool FSystemInfoExtensionPlugin::IsPassthroughRecommended() { if (bExtPassthroughPreferencesAvailable && OculusXR::xrGetPassthroughPreferencesMETA.IsSet()) { XrPassthroughPreferencesMETA PassthroughPreferences = { XR_TYPE_PASSTHROUGH_PREFERENCES_META }; ENSURE_XRCMD(OculusXR::xrGetPassthroughPreferencesMETA.GetValue()(Session, &PassthroughPreferences)); return (PassthroughPreferences.flags & XR_PASSTHROUGH_PREFERENCE_DEFAULT_TO_ACTIVE_BIT_META) == XR_PASSTHROUGH_PREFERENCE_DEFAULT_TO_ACTIVE_BIT_META; } return false; } EOculusXRControllerType FSystemInfoExtensionPlugin::GetControllerType(EControllerHand DeviceHand) { EOculusXRControllerType ControllerType = EOculusXRControllerType::Unknown; IXRTrackingSystem* TrackingSystem = GetOpenXRTrackingSystem(); if (TrackingSystem != nullptr) { if (DeviceHand != EControllerHand::Left || DeviceHand != EControllerHand::Right) { XrInteractionProfileState Profile; Profile.type = XR_TYPE_INTERACTION_PROFILE_STATE; Profile.next = nullptr; const XrPath TopLevelUserPath = DeviceHand != EControllerHand::Left ? ControllerPaths.LeftHandPath : ControllerPaths.RightHandPath; XR_ENSURE(xrGetCurrentInteractionProfile(Session, TopLevelUserPath, &Profile)); const XrPath InteractionProfile = Profile.interactionProfile; if (InteractionProfile == ControllerPaths.TouchControllerPath) { ControllerType = EOculusXRControllerType::MetaQuestTouch; } else if (InteractionProfile == ControllerPaths.TouchControllerProPath) { ControllerType = EOculusXRControllerType::MetaQuestTouchPro; } else if (InteractionProfile == ControllerPaths.TouchControllerPlusPath) { ControllerType = EOculusXRControllerType::MetaQuestTouchPlus; } } } return ControllerType; } } // namespace OculusXR