From c0bc43d1def582f44a91b9c9b3b59d5fc7486702 Mon Sep 17 00:00:00 2001 From: Bastiaan Olij Date: Mon, 28 Jul 2025 10:13:23 +1000 Subject: [PATCH] Add OpenXR 1.1 support --- .../4.5-stable.expected | 8 + .../openxr/action_map/openxr_action_map.cpp | 24 +- .../action_map/openxr_interaction_profile.cpp | 11 +- .../openxr_interaction_profile_metadata.cpp | 56 +++-- .../openxr_interaction_profile_metadata.h | 21 +- .../openxr/doc_classes/OpenXRAPIExtension.xml | 6 + .../doc_classes/OpenXRExtensionWrapper.xml | 8 +- .../OpenXRInteractionProfileMetadata.xml | 22 +- .../openxr_interaction_profile_editor.cpp | 21 +- ...enxr_select_interaction_profile_dialog.cpp | 10 +- ...enxr_android_thread_settings_extension.cpp | 2 +- ...openxr_android_thread_settings_extension.h | 2 +- ...enxr_composition_layer_depth_extension.cpp | 2 +- ...openxr_composition_layer_depth_extension.h | 2 +- .../openxr_composition_layer_extension.cpp | 2 +- .../openxr_composition_layer_extension.h | 2 +- .../openxr_debug_utils_extension.cpp | 2 +- .../extensions/openxr_debug_utils_extension.h | 2 +- .../openxr_dpad_binding_extension.cpp | 2 +- .../openxr_dpad_binding_extension.h | 2 +- .../extensions/openxr_extension_wrapper.cpp | 34 ++- .../extensions/openxr_extension_wrapper.h | 16 +- .../openxr_eye_gaze_interaction.cpp | 2 +- .../extensions/openxr_eye_gaze_interaction.h | 2 +- ...enxr_fb_display_refresh_rate_extension.cpp | 2 +- ...openxr_fb_display_refresh_rate_extension.h | 2 +- .../openxr_fb_foveation_extension.cpp | 2 +- .../openxr_fb_foveation_extension.h | 2 +- .../openxr_fb_update_swapchain_extension.cpp | 2 +- .../openxr_fb_update_swapchain_extension.h | 2 +- .../openxr_frame_synthesis_extension.cpp | 2 +- .../openxr_frame_synthesis_extension.h | 2 +- .../extensions/openxr_future_extension.cpp | 2 +- .../extensions/openxr_future_extension.h | 2 +- .../openxr_hand_interaction_extension.cpp | 5 +- .../openxr_hand_interaction_extension.h | 2 +- .../openxr_hand_tracking_extension.cpp | 2 +- .../openxr_hand_tracking_extension.h | 2 +- .../openxr_htc_controller_extension.cpp | 19 +- .../openxr_htc_controller_extension.h | 2 +- .../openxr_htc_vive_tracker_extension.cpp | 2 +- .../openxr_htc_vive_tracker_extension.h | 2 +- .../openxr_huawei_controller_extension.cpp | 4 +- .../openxr_huawei_controller_extension.h | 2 +- .../openxr_local_floor_extension.cpp | 9 +- .../extensions/openxr_local_floor_extension.h | 2 +- .../openxr_meta_controller_extension.cpp | 160 ++++++++++-- .../openxr_meta_controller_extension.h | 2 +- .../openxr_ml2_controller_extension.cpp | 10 +- .../openxr_ml2_controller_extension.h | 2 +- .../extensions/openxr_mxink_extension.cpp | 2 +- .../extensions/openxr_mxink_extension.h | 2 +- .../extensions/openxr_palm_pose_extension.cpp | 9 +- .../extensions/openxr_palm_pose_extension.h | 2 +- .../openxr_performance_settings_extension.cpp | 2 +- .../openxr_performance_settings_extension.h | 2 +- .../openxr_pico_controller_extension.cpp | 21 +- .../openxr_pico_controller_extension.h | 2 +- .../openxr_render_model_extension.cpp | 7 +- .../openxr_render_model_extension.h | 2 +- ...penxr_valve_analog_threshold_extension.cpp | 2 +- .../openxr_valve_analog_threshold_extension.h | 2 +- .../openxr_visibility_mask_extension.cpp | 2 +- .../openxr_visibility_mask_extension.h | 2 +- .../openxr_wmr_controller_extension.cpp | 20 +- .../openxr_wmr_controller_extension.h | 2 +- .../platform/openxr_android_extension.cpp | 4 +- .../platform/openxr_android_extension.h | 4 +- .../platform/openxr_d3d12_extension.cpp | 2 +- .../platform/openxr_d3d12_extension.h | 2 +- .../platform/openxr_metal_extension.h | 2 +- .../platform/openxr_metal_extension.mm | 2 +- .../platform/openxr_opengl_extension.cpp | 2 +- .../platform/openxr_opengl_extension.h | 2 +- .../platform/openxr_vulkan_extension.cpp | 2 +- .../platform/openxr_vulkan_extension.h | 2 +- .../openxr_spatial_anchor.cpp | 2 +- .../spatial_entities/openxr_spatial_anchor.h | 2 +- .../openxr_spatial_entity_extension.cpp | 2 +- .../openxr_spatial_entity_extension.h | 2 +- .../openxr_spatial_marker_tracking.cpp | 2 +- .../openxr_spatial_marker_tracking.h | 2 +- .../openxr_spatial_plane_tracking.cpp | 2 +- .../openxr_spatial_plane_tracking.h | 2 +- modules/openxr/openxr_api.cpp | 230 ++++++++++++++---- modules/openxr/openxr_api.h | 23 +- modules/openxr/openxr_api_extension.cpp | 6 + modules/openxr/openxr_api_extension.h | 1 + 88 files changed, 638 insertions(+), 251 deletions(-) diff --git a/misc/extension_api_validation/4.5-stable.expected b/misc/extension_api_validation/4.5-stable.expected index e7a86615fc4..b42f7e6ade7 100644 --- a/misc/extension_api_validation/4.5-stable.expected +++ b/misc/extension_api_validation/4.5-stable.expected @@ -128,3 +128,11 @@ Validate extension JSON: Error: Field 'builtin_classes/PackedVector3Array/method Validate extension JSON: Error: Field 'builtin_classes/PackedVector4Array/methods/bsearch': is_const changed value in new API, from false to true. bsearch method made const. Compatibility methods registered. + + +GH-109302 +--------- + +Validate extension JSON: Error: Field 'classes/OpenXRExtensionWrapper/methods/_set_instance_create_info_and_get_next_pointer/arguments': size changed value in new API, from 1 to 2. +Validate extension JSON: Error: Field 'classes/OpenXRExtensionWrapper/methods/_set_instance_create_info_and_get_next_pointer/arguments/0': type changed value in new API, from "void*" to "int". +Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/OpenXRExtensionWrapper/methods/_get_requested_extensions': arguments diff --git a/modules/openxr/action_map/openxr_action_map.cpp b/modules/openxr/action_map/openxr_action_map.cpp index d431bce4933..ed1135d7154 100644 --- a/modules/openxr/action_map/openxr_action_map.cpp +++ b/modules/openxr/action_map/openxr_action_map.cpp @@ -261,7 +261,7 @@ void OpenXRActionMap::create_default_action_sets() { profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose"); profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose"); profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose"); - profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose"); + profile->add_new_binding(palm_pose, "/user/hand/left/input/grip_surface/pose,/user/hand/right/input/grip_surface/pose"); profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/menu/click"); profile->add_new_binding(select_button, "/user/hand/left/input/select/click,/user/hand/right/input/select/click"); // generic has no support for triggers, grip, A/B buttons, nor joystick/trackpad inputs. @@ -273,7 +273,7 @@ void OpenXRActionMap::create_default_action_sets() { profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose"); profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose"); profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose"); - profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose"); + profile->add_new_binding(palm_pose, "/user/hand/left/input/grip_surface/pose,/user/hand/right/input/grip_surface/pose"); profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/menu/click"); profile->add_new_binding(select_button, "/user/hand/left/input/system/click,/user/hand/right/input/system/click"); // wmr controller has no a/b/x/y buttons. @@ -294,7 +294,7 @@ void OpenXRActionMap::create_default_action_sets() { profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose"); profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose"); profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose"); - profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose"); + profile->add_new_binding(palm_pose, "/user/hand/left/input/grip_surface/pose,/user/hand/right/input/grip_surface/pose"); // wmr controllers have no select button we can use. profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/menu/click"); // wmr controller has no a/b/x/y buttons. @@ -317,7 +317,7 @@ void OpenXRActionMap::create_default_action_sets() { profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose"); profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose"); profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose"); - profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose"); + profile->add_new_binding(palm_pose, "/user/hand/left/input/grip_surface/pose,/user/hand/right/input/grip_surface/pose"); // touch controllers have no select button we can use. profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/system/click"); // right hand system click may not be available. profile->add_new_binding(ax_button, "/user/hand/left/input/x/click,/user/hand/right/input/a/click"); // x on left hand, a on right hand. @@ -342,7 +342,7 @@ void OpenXRActionMap::create_default_action_sets() { profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose"); profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose"); profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose"); - profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose"); + profile->add_new_binding(palm_pose, "/user/hand/left/input/grip_surface/pose,/user/hand/right/input/grip_surface/pose"); profile->add_new_binding(select_button, "/user/hand/left/input/system/click,/user/hand/right/input/system/click"); // system click may not be available. profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click"); profile->add_new_binding(ax_button, "/user/hand/left/input/x/click,/user/hand/right/input/a/click"); // x on left hand, a on right hand. @@ -367,7 +367,7 @@ void OpenXRActionMap::create_default_action_sets() { profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose"); profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose"); profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose"); - profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose"); + profile->add_new_binding(palm_pose, "/user/hand/left/input/grip_surface/pose,/user/hand/right/input/grip_surface/pose"); // index controllers have no select button we can use. profile->add_new_binding(menu_button, "/user/hand/left/input/system/click,/user/hand/right/input/system/click"); profile->add_new_binding(ax_button, "/user/hand/left/input/a/click,/user/hand/right/input/a/click"); // a on both controllers. @@ -396,7 +396,7 @@ void OpenXRActionMap::create_default_action_sets() { profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose"); profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose"); profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose"); - profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose"); + profile->add_new_binding(palm_pose, "/user/hand/left/input/grip_surface/pose,/user/hand/right/input/grip_surface/pose"); // hpmr controllers have no select button we can use. profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/menu/click"); // hpmr controllers only register click, not touch, on our a/b/x/y buttons. @@ -419,7 +419,7 @@ void OpenXRActionMap::create_default_action_sets() { profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose"); profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose"); profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose"); - profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose"); + profile->add_new_binding(palm_pose, "/user/hand/left/input/grip_surface/pose,/user/hand/right/input/grip_surface/pose"); // Odyssey controllers have no select button we can use. profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/menu/click"); // Odyssey controller has no a/b/x/y buttons. @@ -442,7 +442,7 @@ void OpenXRActionMap::create_default_action_sets() { profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose"); profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose"); profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose"); - profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose"); + profile->add_new_binding(palm_pose, "/user/hand/left/input/grip_surface/pose,/user/hand/right/input/grip_surface/pose"); profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click"); profile->add_new_binding(select_button, "/user/hand/right/input/system/click"); // we'll map system to select. profile->add_new_binding(ax_button, "/user/hand/left/input/x/click,/user/hand/right/input/a/click"); // x on left hand, a on right hand. @@ -466,7 +466,7 @@ void OpenXRActionMap::create_default_action_sets() { profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose"); profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose"); profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose"); - profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose"); + profile->add_new_binding(palm_pose, "/user/hand/left/input/grip_surface/pose,/user/hand/right/input/grip_surface/pose"); profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click"); profile->add_new_binding(select_button, "/user/hand/right/input/system/click"); // we'll map system to select. profile->add_new_binding(ax_button, "/user/hand/left/input/x/click,/user/hand/right/input/a/click"); // x on left hand, a on right hand. @@ -490,7 +490,7 @@ void OpenXRActionMap::create_default_action_sets() { profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose"); profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose"); profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose"); - profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose"); + profile->add_new_binding(palm_pose, "/user/hand/left/input/grip_surface/pose,/user/hand/right/input/grip_surface/pose"); profile->add_new_binding(menu_button, "/user/hand/left/input/home/click,/user/hand/right/input/home/click"); profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value"); profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/click,/user/hand/right/input/trigger/click"); @@ -551,7 +551,7 @@ void OpenXRActionMap::create_default_action_sets() { profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose"); profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose"); profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose"); - profile->add_new_binding(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose"); + profile->add_new_binding(palm_pose, "/user/hand/left/input/grip_surface/pose,/user/hand/right/input/grip_surface/pose"); // Use pinch as primary. profile->add_new_binding(primary, "/user/hand/left/input/pinch_ext/value,/user/hand/right/input/pinch_ext/value"); diff --git a/modules/openxr/action_map/openxr_interaction_profile.cpp b/modules/openxr/action_map/openxr_interaction_profile.cpp index c3cb4e9150e..b1e4478f179 100644 --- a/modules/openxr/action_map/openxr_interaction_profile.cpp +++ b/modules/openxr/action_map/openxr_interaction_profile.cpp @@ -79,7 +79,14 @@ Ref OpenXRIPBinding::get_action() const { } void OpenXRIPBinding::set_binding_path(const String &p_path) { - binding_path = p_path; + OpenXRInteractionProfileMetadata *pmd = OpenXRInteractionProfileMetadata::get_singleton(); + if (pmd) { + binding_path = pmd->check_path_name(p_path); + } else { + // OpenXR not enabled, ignore checks. + binding_path = p_path; + } + emit_changed(); } @@ -244,7 +251,7 @@ void OpenXRInteractionProfile::set_interaction_profile_path(const String &p_inpu if (pmd) { interaction_profile_path = pmd->check_profile_name(p_input_profile_path); } else { - // OpenXR module not enabled, ignore checks. + // OpenXR not enabled, ignore checks. interaction_profile_path = p_input_profile_path; } emit_changed(); diff --git a/modules/openxr/action_map/openxr_interaction_profile_metadata.cpp b/modules/openxr/action_map/openxr_interaction_profile_metadata.cpp index 2ae5a2eed61..3fa5ed9a48e 100644 --- a/modules/openxr/action_map/openxr_interaction_profile_metadata.cpp +++ b/modules/openxr/action_map/openxr_interaction_profile_metadata.cpp @@ -47,9 +47,10 @@ OpenXRInteractionProfileMetadata::~OpenXRInteractionProfileMetadata() { void OpenXRInteractionProfileMetadata::_bind_methods() { ClassDB::bind_method(D_METHOD("register_profile_rename", "old_name", "new_name"), &OpenXRInteractionProfileMetadata::register_profile_rename); - ClassDB::bind_method(D_METHOD("register_top_level_path", "display_name", "openxr_path", "openxr_extension_name"), &OpenXRInteractionProfileMetadata::register_top_level_path); - ClassDB::bind_method(D_METHOD("register_interaction_profile", "display_name", "openxr_path", "openxr_extension_name"), &OpenXRInteractionProfileMetadata::register_interaction_profile); - ClassDB::bind_method(D_METHOD("register_io_path", "interaction_profile", "display_name", "toplevel_path", "openxr_path", "openxr_extension_name", "action_type"), &OpenXRInteractionProfileMetadata::register_io_path); + ClassDB::bind_method(D_METHOD("register_path_rename", "old_name", "new_name"), &OpenXRInteractionProfileMetadata::register_path_rename); + ClassDB::bind_method(D_METHOD("register_top_level_path", "display_name", "openxr_path", "openxr_extension_names"), &OpenXRInteractionProfileMetadata::register_top_level_path); + ClassDB::bind_method(D_METHOD("register_interaction_profile", "display_name", "openxr_path", "openxr_extension_names"), &OpenXRInteractionProfileMetadata::register_interaction_profile); + ClassDB::bind_method(D_METHOD("register_io_path", "interaction_profile", "display_name", "toplevel_path", "openxr_path", "openxr_extension_names", "action_type"), &OpenXRInteractionProfileMetadata::register_io_path); } void OpenXRInteractionProfileMetadata::register_profile_rename(const String &p_old_name, const String &p_new_name) { @@ -66,30 +67,44 @@ String OpenXRInteractionProfileMetadata::check_profile_name(const String &p_name return p_name; } -void OpenXRInteractionProfileMetadata::register_top_level_path(const String &p_display_name, const String &p_openxr_path, const String &p_openxr_extension_name) { +void OpenXRInteractionProfileMetadata::register_path_rename(const String &p_old_name, const String &p_new_name) { + ERR_FAIL_COND(path_renames.has(p_old_name)); + + path_renames[p_old_name] = p_new_name; +} + +String OpenXRInteractionProfileMetadata::check_path_name(const String &p_name) const { + if (path_renames.has(p_name)) { + return path_renames[p_name]; + } + + return p_name; +} + +void OpenXRInteractionProfileMetadata::register_top_level_path(const String &p_display_name, const String &p_openxr_path, const String &p_openxr_extension_names) { ERR_FAIL_COND_MSG(has_top_level_path(p_openxr_path), p_openxr_path + " had already been registered"); TopLevelPath new_toplevel_path = { p_display_name, p_openxr_path, - p_openxr_extension_name + p_openxr_extension_names }; top_level_paths.push_back(new_toplevel_path); } -void OpenXRInteractionProfileMetadata::register_interaction_profile(const String &p_display_name, const String &p_openxr_path, const String &p_openxr_extension_name) { +void OpenXRInteractionProfileMetadata::register_interaction_profile(const String &p_display_name, const String &p_openxr_path, const String &p_openxr_extension_names) { ERR_FAIL_COND_MSG(has_interaction_profile(p_openxr_path), p_openxr_path + " has already been registered"); InteractionProfile new_profile; new_profile.display_name = p_display_name; new_profile.openxr_path = p_openxr_path; - new_profile.openxr_extension_name = p_openxr_extension_name; + new_profile.openxr_extension_names = p_openxr_extension_names; interaction_profiles.push_back(new_profile); } -void OpenXRInteractionProfileMetadata::register_io_path(const String &p_interaction_profile, const String &p_display_name, const String &p_toplevel_path, const String &p_openxr_path, const String &p_openxr_extension_name, OpenXRAction::ActionType p_action_type) { +void OpenXRInteractionProfileMetadata::register_io_path(const String &p_interaction_profile, const String &p_display_name, const String &p_toplevel_path, const String &p_openxr_path, const String &p_openxr_extension_names, OpenXRAction::ActionType p_action_type) { ERR_FAIL_COND_MSG(!has_interaction_profile(p_interaction_profile), "Unknown interaction profile " + p_interaction_profile); ERR_FAIL_COND_MSG(!has_top_level_path(p_toplevel_path), "Unknown top level path " + p_toplevel_path); @@ -101,7 +116,7 @@ void OpenXRInteractionProfileMetadata::register_io_path(const String &p_interact p_display_name, p_toplevel_path, p_openxr_path, - p_openxr_extension_name, + p_openxr_extension_names, p_action_type }; @@ -130,10 +145,10 @@ String OpenXRInteractionProfileMetadata::get_top_level_name(const String &p_open return String(); } -String OpenXRInteractionProfileMetadata::get_top_level_extension(const String &p_openxr_path) const { +String OpenXRInteractionProfileMetadata::get_top_level_extensions(const String &p_openxr_path) const { for (int i = 0; i < top_level_paths.size(); i++) { if (top_level_paths[i].openxr_path == p_openxr_path) { - return top_level_paths[i].openxr_extension_name; + return top_level_paths[i].openxr_extension_names; } } @@ -150,10 +165,10 @@ bool OpenXRInteractionProfileMetadata::has_interaction_profile(const String &p_o return false; } -String OpenXRInteractionProfileMetadata::get_interaction_profile_extension(const String &p_openxr_path) const { +String OpenXRInteractionProfileMetadata::get_interaction_profile_extensions(const String &p_openxr_path) const { for (const InteractionProfile &interaction_profile : interaction_profiles) { if (interaction_profile.openxr_path == p_openxr_path) { - return interaction_profile.openxr_extension_name; + return interaction_profile.openxr_extension_names; } } @@ -218,6 +233,11 @@ void OpenXRInteractionProfileMetadata::_register_core_metadata() { // Note that we'll make an exception for XR_EXT_palm_pose, which is used everywhere + // OpenXR 1.1 uses various new names. + // We use the new names in our action map and translate back IF OpenXR 1.1 is not supported. + register_path_rename("/user/hand/left/input/palm_ext/pose", "/user/hand/left/input/grip_surface/pose"); + register_path_rename("/user/hand/right/input/palm_ext/pose", "/user/hand/right/input/grip_surface/pose"); + // Our core toplevel paths register_top_level_path("Left hand controller", "/user/hand/left", ""); register_top_level_path("Right hand controller", "/user/hand/right", ""); @@ -231,7 +251,7 @@ void OpenXRInteractionProfileMetadata::_register_core_metadata() { for (const String user_path : { "/user/hand/left", "/user/hand/right" }) { register_io_path(profile_path, "Grip pose", user_path, user_path + "/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); register_io_path(profile_path, "Aim pose", user_path, user_path + "/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); - register_io_path(profile_path, "Palm pose", user_path, user_path + "/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + register_io_path(profile_path, "Grip surface pose", user_path, user_path + "/input/grip_surface/pose", XR_EXT_PALM_POSE_EXTENSION_NAME "," XR_KHR_MAINTENANCE1_EXTENSION_NAME "," XR_OPENXR_1_1_NAME, OpenXRAction::OPENXR_ACTION_POSE); register_io_path(profile_path, "Menu click", user_path, user_path + "/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); register_io_path(profile_path, "Select click", user_path, user_path + "/input/select/click", "", OpenXRAction::OPENXR_ACTION_BOOL); @@ -246,7 +266,7 @@ void OpenXRInteractionProfileMetadata::_register_core_metadata() { for (const String user_path : { "/user/hand/left", "/user/hand/right" }) { register_io_path(profile_path, "Grip pose", user_path, user_path + "/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); register_io_path(profile_path, "Aim pose", user_path, user_path + "/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); - register_io_path(profile_path, "Palm pose", user_path, user_path + "/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + register_io_path(profile_path, "Grip surface pose", user_path, user_path + "/input/grip_surface/pose", XR_EXT_PALM_POSE_EXTENSION_NAME "," XR_KHR_MAINTENANCE1_EXTENSION_NAME "," XR_OPENXR_1_1_NAME, OpenXRAction::OPENXR_ACTION_POSE); register_io_path(profile_path, "Menu click", user_path, user_path + "/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); register_io_path(profile_path, "System click", user_path, user_path + "/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL); @@ -275,7 +295,7 @@ void OpenXRInteractionProfileMetadata::_register_core_metadata() { for (const String user_path : { "/user/hand/left", "/user/hand/right" }) { register_io_path(profile_path, "Grip pose", user_path, user_path + "/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); register_io_path(profile_path, "Aim pose", user_path, user_path + "/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); - register_io_path(profile_path, "Palm pose", user_path, user_path + "/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + register_io_path(profile_path, "Grip surface pose", user_path, user_path + "/input/grip_surface/pose", XR_EXT_PALM_POSE_EXTENSION_NAME "," XR_KHR_MAINTENANCE1_EXTENSION_NAME "," XR_OPENXR_1_1_NAME, OpenXRAction::OPENXR_ACTION_POSE); register_io_path(profile_path, "Menu click", user_path, user_path + "/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); @@ -310,7 +330,7 @@ void OpenXRInteractionProfileMetadata::_register_core_metadata() { for (const String user_path : { "/user/hand/left", "/user/hand/right" }) { register_io_path(profile_path, "Grip pose", user_path, user_path + "/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); register_io_path(profile_path, "Aim pose", user_path, user_path + "/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); - register_io_path(profile_path, "Palm pose", user_path, user_path + "/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + register_io_path(profile_path, "Grip surface pose", user_path, user_path + "/input/grip_surface/pose", XR_EXT_PALM_POSE_EXTENSION_NAME "," XR_KHR_MAINTENANCE1_EXTENSION_NAME "," XR_OPENXR_1_1_NAME, OpenXRAction::OPENXR_ACTION_POSE); register_io_path(profile_path, "Trigger", user_path, user_path + "/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); register_io_path(profile_path, "Trigger touch", user_path, user_path + "/input/trigger/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); @@ -349,7 +369,7 @@ void OpenXRInteractionProfileMetadata::_register_core_metadata() { for (const String user_path : { "/user/hand/left", "/user/hand/right" }) { register_io_path(profile_path, "Grip pose", user_path, user_path + "/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); register_io_path(profile_path, "Aim pose", user_path, user_path + "/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); - register_io_path(profile_path, "Palm pose", user_path, user_path + "/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + register_io_path(profile_path, "Grip surface pose", user_path, user_path + "/input/grip_surface/pose", XR_EXT_PALM_POSE_EXTENSION_NAME "," XR_KHR_MAINTENANCE1_EXTENSION_NAME "," XR_OPENXR_1_1_NAME, OpenXRAction::OPENXR_ACTION_POSE); register_io_path(profile_path, "System click", user_path, user_path + "/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL); diff --git a/modules/openxr/action_map/openxr_interaction_profile_metadata.h b/modules/openxr/action_map/openxr_interaction_profile_metadata.h index 44a529e11d7..4a052956555 100644 --- a/modules/openxr/action_map/openxr_interaction_profile_metadata.h +++ b/modules/openxr/action_map/openxr_interaction_profile_metadata.h @@ -64,21 +64,21 @@ public: struct TopLevelPath { String display_name; // User friendly display name (i.e. Left controller) String openxr_path; // Path in OpenXR (i.e. /user/hand/left) - String openxr_extension_name; // If set, only available if extension is enabled (i.e. XR_HTCX_vive_tracker_interaction) + String openxr_extension_names; // If set, only available if extension is enabled (i.e. XR_HTCX_vive_tracker_interaction) }; struct IOPath { String display_name; // User friendly display name (i.e. Grip pose (left controller)) String top_level_path; // Top level path identifying the usage of the device in relation to this input/output String openxr_path; // Path in OpenXR (i.e. /user/hand/left/input/grip/pose) - String openxr_extension_name; // If set, only available if extension is enabled (i.e. XR_EXT_palm_pose) + String openxr_extension_names; // If set, only available if extension is enabled (i.e. XR_EXT_palm_pose) OpenXRAction::ActionType action_type; // Type of input/output }; struct InteractionProfile { String display_name; // User friendly display name (i.e. Simple controller) String openxr_path; // Path in OpenXR (i.e. /interaction_profiles/khr/simple_controller) - String openxr_extension_name; // If set, only available if extension is enabled (i.e. XR_HTCX_vive_tracker_interaction) + String openxr_extension_names; // If set, only available if extension is enabled (i.e. XR_HTCX_vive_tracker_interaction) Vector io_paths; // Inputs and outputs for this device bool has_io_path(const String &p_io_path) const; @@ -89,6 +89,8 @@ private: static OpenXRInteractionProfileMetadata *singleton; HashMap profile_renames; + HashMap path_renames; + Vector top_level_paths; Vector interaction_profiles; @@ -106,17 +108,20 @@ public: void register_profile_rename(const String &p_old_name, const String &p_new_name); String check_profile_name(const String &p_name) const; - void register_top_level_path(const String &p_display_name, const String &p_openxr_path, const String &p_openxr_extension_name); + void register_path_rename(const String &p_old_name, const String &p_new_name); + String check_path_name(const String &p_name) const; + + void register_top_level_path(const String &p_display_name, const String &p_openxr_path, const String &p_openxr_extension_names); bool has_top_level_path(const String &p_openxr_path) const; String get_top_level_name(const String &p_openxr_path) const; - String get_top_level_extension(const String &p_openxr_path) const; + String get_top_level_extensions(const String &p_openxr_path) const; - void register_interaction_profile(const String &p_display_name, const String &p_openxr_path, const String &p_openxr_extension_name); + void register_interaction_profile(const String &p_display_name, const String &p_openxr_path, const String &p_openxr_extension_names); bool has_interaction_profile(const String &p_openxr_path) const; - String get_interaction_profile_extension(const String &p_openxr_path) const; + String get_interaction_profile_extensions(const String &p_openxr_path) const; const InteractionProfile *get_profile(const String &p_openxr_path) const; PackedStringArray get_interaction_profile_paths() const; - void register_io_path(const String &p_interaction_profile, const String &p_display_name, const String &p_toplevel_path, const String &p_openxr_path, const String &p_openxr_extension_name, OpenXRAction::ActionType p_action_type); + void register_io_path(const String &p_interaction_profile, const String &p_display_name, const String &p_toplevel_path, const String &p_openxr_path, const String &p_openxr_extension_names, OpenXRAction::ActionType p_action_type); const IOPath *get_io_path(const String &p_interaction_profile, const String &p_io_path) const; }; diff --git a/modules/openxr/doc_classes/OpenXRAPIExtension.xml b/modules/openxr/doc_classes/OpenXRAPIExtension.xml index e38a51e15c6..6dfc4bedf55 100644 --- a/modules/openxr/doc_classes/OpenXRAPIExtension.xml +++ b/modules/openxr/doc_classes/OpenXRAPIExtension.xml @@ -85,6 +85,12 @@ Returns the predicted display timing for the next frame. + + + + Returns the version of OpenXR that was initialized. Only valid after the OpenXR instance has been created. See [url=https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XR_MAKE_VERSION]XR_MAKE_VERSION[/url] for how the version is calculated. + + diff --git a/modules/openxr/doc_classes/OpenXRExtensionWrapper.xml b/modules/openxr/doc_classes/OpenXRExtensionWrapper.xml index 96c3bbefcca..f216ad91ba1 100644 --- a/modules/openxr/doc_classes/OpenXRExtensionWrapper.xml +++ b/modules/openxr/doc_classes/OpenXRExtensionWrapper.xml @@ -42,8 +42,9 @@ + - Returns a [Dictionary] of OpenXR extensions related to this extension. The [Dictionary] should contain the name of the extension, mapped to a [code]bool *[/code] cast to an integer: + Returns a [Dictionary] of OpenXR extensions related to this extension. [param xr_version] specifies the OpenXR version we're instantiating. This will be zero if the editor requests this list to flag supported features. The [Dictionary] should contain the name of the extension, mapped to a [code]bool *[/code] cast to an integer: - If the [code]bool *[/code] is a [code]nullptr[/code] this extension is mandatory. - If the [code]bool *[/code] points to a boolean, the boolean will be updated to [code]true[/code] if the extension is enabled. @@ -269,9 +270,10 @@ - + + - Add additional data structures when the OpenXR instance is created. + Add additional data structures when the OpenXR instance is created. [param xr_version] specifies the OpenXR version we're instantiating. diff --git a/modules/openxr/doc_classes/OpenXRInteractionProfileMetadata.xml b/modules/openxr/doc_classes/OpenXRInteractionProfileMetadata.xml index ebb739a8449..6eb98f3950e 100644 --- a/modules/openxr/doc_classes/OpenXRInteractionProfileMetadata.xml +++ b/modules/openxr/doc_classes/OpenXRInteractionProfileMetadata.xml @@ -13,10 +13,10 @@ - + Registers an interaction profile using its OpenXR designation (e.g. [code]/interaction_profiles/khr/simple_controller[/code] is the profile for OpenXR's simple controller profile). - [param display_name] is the description shown to the user. [param openxr_path] is the interaction profile path being registered. [param openxr_extension_name] optionally restricts this profile to the given extension being enabled/available. If the extension is not available, the profile and all related entries used in an action map are filtered out. + [param display_name] is the description shown to the user. [param openxr_path] is the interaction profile path being registered. [param openxr_extension_names] optionally restricts this profile to the given extension being enabled/available. If the extension is not available, the profile and all related entries used in an action map are filtered out. @@ -25,10 +25,18 @@ - + - Registers an input/output path for the given [param interaction_profile]. The profile should previously have been registered using [method register_interaction_profile]. [param display_name] is the description shown to the user. [param toplevel_path] specifies the bind path this input/output can be bound to (e.g. [code]/user/hand/left[/code] or [code]/user/hand/right[/code]). [param openxr_path] is the action input/output being registered (e.g. [code]/user/hand/left/input/aim/pose[/code]). [param openxr_extension_name] restricts this input/output to an enabled/available extension, this doesn't need to repeat the extension on the profile but relates to overlapping extension (e.g. [code]XR_EXT_palm_pose[/code] that introduces [code]…/input/palm_ext/pose[/code] input paths). [param action_type] defines the type of input or output provided by OpenXR. + Registers an input/output path for the given [param interaction_profile]. The profile should previously have been registered using [method register_interaction_profile]. [param display_name] is the description shown to the user. [param toplevel_path] specifies the bind path this input/output can be bound to (e.g. [code]/user/hand/left[/code] or [code]/user/hand/right[/code]). [param openxr_path] is the action input/output being registered (e.g. [code]/user/hand/left/input/aim/pose[/code]). [param openxr_extension_names] restricts this input/output to an enabled/available extension, this doesn't need to repeat the extension on the profile but relates to overlapping extension (e.g. [code]XR_EXT_palm_pose[/code] that introduces [code]…/input/palm_ext/pose[/code] input paths). [param action_type] defines the type of input or output provided by OpenXR. + + + + + + + + Allows for renaming old input/output paths to new paths in order to load and process older action maps. @@ -36,17 +44,17 @@ - Allows for renaming old interaction profile paths to new paths to maintain backwards compatibility with older action maps. + Allows for renaming old interaction profile paths to new paths in order to load and process older action maps. - + Registers a top level path to which profiles can be bound. For instance [code]/user/hand/left[/code] refers to the bind point for the player's left hand. Extensions can register additional top level paths, for instance a haptic vest extension might register [code]/user/body/vest[/code]. - [param display_name] is the name shown to the user. [param openxr_path] is the top level path being registered. [param openxr_extension_name] is optional and ensures the top level path is only used if the specified extension is available/enabled. + [param display_name] is the name shown to the user. [param openxr_path] is the top level path being registered. [param openxr_extension_names] is optional and ensures the top level path is only used if the specified extension is available/enabled. When a top level path ends up being bound by OpenXR, an [XRPositionalTracker] is instantiated to manage the state of the device. diff --git a/modules/openxr/editor/openxr_interaction_profile_editor.cpp b/modules/openxr/editor/openxr_interaction_profile_editor.cpp index 617266eea52..a48d1751c6d 100644 --- a/modules/openxr/editor/openxr_interaction_profile_editor.cpp +++ b/modules/openxr/editor/openxr_interaction_profile_editor.cpp @@ -198,10 +198,10 @@ void OpenXRInteractionProfileEditorBase::setup(const Ref &p_act if (profile_def != nullptr) { profile_name = profile_def->display_name; - if (!profile_def->openxr_extension_name.is_empty()) { + if (!profile_def->openxr_extension_names.is_empty()) { profile_name += "*"; - tooltip = vformat(TTR("Note: This interaction profile requires extension %s support."), profile_def->openxr_extension_name); + tooltip = vformat(TTR("Note: This interaction profile requires extension %s support."), profile_def->openxr_extension_names); } } @@ -242,11 +242,13 @@ void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, co Label *path_label = memnew(Label); path_label->set_focus_mode(FOCUS_ACCESSIBILITY); - if (p_io_path->openxr_extension_name.is_empty()) { + if (p_io_path->openxr_extension_names.is_empty()) { path_label->set_text(p_io_path->display_name); } else { path_label->set_text(p_io_path->display_name + "*"); - path_hb->set_tooltip_text(vformat(TTR("Note: This binding path requires extension %s support."), p_io_path->openxr_extension_name)); + + String extension_names = p_io_path->openxr_extension_names.replace(",", " or ").replace(XR_OPENXR_1_1_NAME, "OpenXR 1.1"); + path_hb->set_tooltip_text(vformat(TTR("Note: This binding path requires extension %s support."), extension_names)); } path_label->set_h_size_flags(Control::SIZE_EXPAND_FILL); path_hb->add_child(path_label); @@ -334,7 +336,7 @@ void OpenXRInteractionProfileEditor::_update_interaction_profile() { return; } - PackedStringArray requested_extensions = OpenXRAPI::get_all_requested_extensions(); + PackedStringArray requested_extensions = OpenXRAPI::get_all_requested_extensions(0); // out with the old... while (interaction_profile_hb->get_child_count() > 0) { @@ -369,7 +371,14 @@ void OpenXRInteractionProfileEditor::_update_interaction_profile() { for (int j = 0; j < profile_def->io_paths.size(); j++) { const OpenXRInteractionProfileMetadata::IOPath *io_path = &profile_def->io_paths[j]; - if (io_path->top_level_path == top_level_paths[i] && (io_path->openxr_extension_name.is_empty() || requested_extensions.has(io_path->openxr_extension_name))) { + + const Vector extensions = io_path->openxr_extension_names.split(",", false); + bool extension_is_requested = extensions.is_empty(); // If none, then yes we can use this. + for (const String &extension : extensions) { + extension_is_requested |= requested_extensions.has(extension); + } + + if (io_path->top_level_path == top_level_paths[i] && extension_is_requested) { _add_io_path(container, io_path); } } diff --git a/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp b/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp index 79fc4c4ea55..cda0cec284a 100644 --- a/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp +++ b/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp @@ -78,7 +78,7 @@ void OpenXRSelectInteractionProfileDialog::open(const PackedStringArray &p_do_no memdelete(main_vb->get_child(1)); } - PackedStringArray requested_extensions = OpenXRAPI::get_all_requested_extensions(); + PackedStringArray requested_extensions = OpenXRAPI::get_all_requested_extensions(0); selected_interaction_profile = ""; ip_buttons.clear(); @@ -86,8 +86,12 @@ void OpenXRSelectInteractionProfileDialog::open(const PackedStringArray &p_do_no // In with the new. PackedStringArray interaction_profiles = meta_data->get_interaction_profile_paths(); for (const String &path : interaction_profiles) { - const String extension = meta_data->get_interaction_profile_extension(path); - if (!p_do_not_include.has(path) && (extension.is_empty() || requested_extensions.has(extension))) { + const Vector extensions = meta_data->get_interaction_profile_extensions(path).split(",", false); + bool extension_is_requested = extensions.is_empty(); // If none, then yes we can use this. + for (const String &extension : extensions) { + extension_is_requested |= requested_extensions.has(extension); + } + if (!p_do_not_include.has(path) && extension_is_requested) { Button *ip_button = memnew(Button); ip_button->set_flat(true); ip_button->set_text(meta_data->get_profile(path)->display_name); diff --git a/modules/openxr/extensions/openxr_android_thread_settings_extension.cpp b/modules/openxr/extensions/openxr_android_thread_settings_extension.cpp index e27a6efd229..2ddc03e9b24 100644 --- a/modules/openxr/extensions/openxr_android_thread_settings_extension.cpp +++ b/modules/openxr/extensions/openxr_android_thread_settings_extension.cpp @@ -62,7 +62,7 @@ void OpenXRAndroidThreadSettingsExtension::_bind_methods() { BIND_ENUM_CONSTANT(THREAD_TYPE_RENDERER_WORKER); } -HashMap OpenXRAndroidThreadSettingsExtension::get_requested_extensions() { +HashMap OpenXRAndroidThreadSettingsExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; #ifdef XR_USE_PLATFORM_ANDROID diff --git a/modules/openxr/extensions/openxr_android_thread_settings_extension.h b/modules/openxr/extensions/openxr_android_thread_settings_extension.h index 482cdbb7c3d..b686fa100a4 100644 --- a/modules/openxr/extensions/openxr_android_thread_settings_extension.h +++ b/modules/openxr/extensions/openxr_android_thread_settings_extension.h @@ -50,7 +50,7 @@ public: OpenXRAndroidThreadSettingsExtension(); virtual ~OpenXRAndroidThreadSettingsExtension() override; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; virtual void on_instance_created(XrInstance p_instance) override; virtual void on_session_created(XrSession p_session) override; diff --git a/modules/openxr/extensions/openxr_composition_layer_depth_extension.cpp b/modules/openxr/extensions/openxr_composition_layer_depth_extension.cpp index b3c94d44f07..9f0aad90e35 100644 --- a/modules/openxr/extensions/openxr_composition_layer_depth_extension.cpp +++ b/modules/openxr/extensions/openxr_composition_layer_depth_extension.cpp @@ -44,7 +44,7 @@ OpenXRCompositionLayerDepthExtension::~OpenXRCompositionLayerDepthExtension() { singleton = nullptr; } -HashMap OpenXRCompositionLayerDepthExtension::get_requested_extensions() { +HashMap OpenXRCompositionLayerDepthExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; request_extensions[XR_KHR_COMPOSITION_LAYER_DEPTH_EXTENSION_NAME] = &available; diff --git a/modules/openxr/extensions/openxr_composition_layer_depth_extension.h b/modules/openxr/extensions/openxr_composition_layer_depth_extension.h index 6b4f81cdd97..82d88eac8c0 100644 --- a/modules/openxr/extensions/openxr_composition_layer_depth_extension.h +++ b/modules/openxr/extensions/openxr_composition_layer_depth_extension.h @@ -44,7 +44,7 @@ public: OpenXRCompositionLayerDepthExtension(); virtual ~OpenXRCompositionLayerDepthExtension() override; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; bool is_available(); virtual int get_composition_layer_count() override; virtual XrCompositionLayerBaseHeader *get_composition_layer(int p_index) override; diff --git a/modules/openxr/extensions/openxr_composition_layer_extension.cpp b/modules/openxr/extensions/openxr_composition_layer_extension.cpp index ad9bdf207b9..26fb9723a13 100644 --- a/modules/openxr/extensions/openxr_composition_layer_extension.cpp +++ b/modules/openxr/extensions/openxr_composition_layer_extension.cpp @@ -56,7 +56,7 @@ OpenXRCompositionLayerExtension::~OpenXRCompositionLayerExtension() { singleton = nullptr; } -HashMap OpenXRCompositionLayerExtension::get_requested_extensions() { +HashMap OpenXRCompositionLayerExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; request_extensions[XR_KHR_COMPOSITION_LAYER_CYLINDER_EXTENSION_NAME] = &cylinder_ext_available; diff --git a/modules/openxr/extensions/openxr_composition_layer_extension.h b/modules/openxr/extensions/openxr_composition_layer_extension.h index 770080ad85c..a476a2d26dd 100644 --- a/modules/openxr/extensions/openxr_composition_layer_extension.h +++ b/modules/openxr/extensions/openxr_composition_layer_extension.h @@ -126,7 +126,7 @@ public: OpenXRCompositionLayerExtension(); virtual ~OpenXRCompositionLayerExtension() override; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; virtual void on_instance_created(const XrInstance p_instance) override; virtual void on_session_created(const XrSession p_session) override; virtual void on_session_destroyed() override; diff --git a/modules/openxr/extensions/openxr_debug_utils_extension.cpp b/modules/openxr/extensions/openxr_debug_utils_extension.cpp index cb7f72d02d2..9aeaa12d697 100644 --- a/modules/openxr/extensions/openxr_debug_utils_extension.cpp +++ b/modules/openxr/extensions/openxr_debug_utils_extension.cpp @@ -50,7 +50,7 @@ OpenXRDebugUtilsExtension::~OpenXRDebugUtilsExtension() { singleton = nullptr; } -HashMap OpenXRDebugUtilsExtension::get_requested_extensions() { +HashMap OpenXRDebugUtilsExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; request_extensions[XR_EXT_DEBUG_UTILS_EXTENSION_NAME] = &debug_utils_ext; diff --git a/modules/openxr/extensions/openxr_debug_utils_extension.h b/modules/openxr/extensions/openxr_debug_utils_extension.h index 9c0402e5c69..248e51f0952 100644 --- a/modules/openxr/extensions/openxr_debug_utils_extension.h +++ b/modules/openxr/extensions/openxr_debug_utils_extension.h @@ -45,7 +45,7 @@ public: OpenXRDebugUtilsExtension(); virtual ~OpenXRDebugUtilsExtension() override; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; virtual void on_instance_created(const XrInstance p_instance) override; virtual void on_instance_destroyed() override; diff --git a/modules/openxr/extensions/openxr_dpad_binding_extension.cpp b/modules/openxr/extensions/openxr_dpad_binding_extension.cpp index 05da048ff1f..dfca2bed970 100644 --- a/modules/openxr/extensions/openxr_dpad_binding_extension.cpp +++ b/modules/openxr/extensions/openxr_dpad_binding_extension.cpp @@ -52,7 +52,7 @@ OpenXRDPadBindingExtension::~OpenXRDPadBindingExtension() { singleton = nullptr; } -HashMap OpenXRDPadBindingExtension::get_requested_extensions() { +HashMap OpenXRDPadBindingExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; // Note, we're dependent on the binding modifier extension, this may be requested by multiple extension wrappers. diff --git a/modules/openxr/extensions/openxr_dpad_binding_extension.h b/modules/openxr/extensions/openxr_dpad_binding_extension.h index 72f49c596c7..128ae20ae4c 100644 --- a/modules/openxr/extensions/openxr_dpad_binding_extension.h +++ b/modules/openxr/extensions/openxr_dpad_binding_extension.h @@ -48,7 +48,7 @@ public: OpenXRDPadBindingExtension(); virtual ~OpenXRDPadBindingExtension() override; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; bool is_available(); diff --git a/modules/openxr/extensions/openxr_extension_wrapper.cpp b/modules/openxr/extensions/openxr_extension_wrapper.cpp index 0665562a984..58df171f9a4 100644 --- a/modules/openxr/extensions/openxr_extension_wrapper.cpp +++ b/modules/openxr/extensions/openxr_extension_wrapper.cpp @@ -34,9 +34,9 @@ #include "../openxr_api_extension.h" void OpenXRExtensionWrapper::_bind_methods() { - GDVIRTUAL_BIND(_get_requested_extensions); + GDVIRTUAL_BIND(_get_requested_extensions, "xr_version"); GDVIRTUAL_BIND(_set_system_properties_and_get_next_pointer, "next_pointer"); - GDVIRTUAL_BIND(_set_instance_create_info_and_get_next_pointer, "next_pointer"); + GDVIRTUAL_BIND(_set_instance_create_info_and_get_next_pointer, "xr_version", "next_pointer"); GDVIRTUAL_BIND(_set_session_create_and_get_next_pointer, "next_pointer"); GDVIRTUAL_BIND(_set_swapchain_create_info_and_get_next_pointer, "next_pointer"); GDVIRTUAL_BIND(_set_hand_joint_locations_and_get_next_pointer, "hand_index", "next_pointer"); @@ -79,14 +79,19 @@ void OpenXRExtensionWrapper::_bind_methods() { GDVIRTUAL_BIND(_on_viewport_composition_layer_destroyed, "layer"); GDVIRTUAL_BIND(_set_android_surface_swapchain_create_info_and_get_next_pointer, "property_values", "next_pointer"); +#ifndef DISABLE_DEPRECATED + GDVIRTUAL_BIND_COMPAT(_get_requested_extensions_bind_compat_109302); + GDVIRTUAL_BIND_COMPAT(_set_instance_create_info_and_get_next_pointer_bind_compat_109302, "next_pointer"); +#endif + ClassDB::bind_method(D_METHOD("get_openxr_api"), &OpenXRExtensionWrapper::_gdextension_get_openxr_api); ClassDB::bind_method(D_METHOD("register_extension_wrapper"), &OpenXRExtensionWrapper::_gdextension_register_extension_wrapper); } -HashMap OpenXRExtensionWrapper::get_requested_extensions() { +HashMap OpenXRExtensionWrapper::get_requested_extensions(XrVersion p_xr_version) { Dictionary request_extension; - if (GDVIRTUAL_CALL(_get_requested_extensions, request_extension)) { + if (GDVIRTUAL_CALL(_get_requested_extensions, (uint64_t)p_xr_version, request_extension)) { HashMap result; for (const KeyValue &kv : request_extension) { GDExtensionPtr value = VariantCaster>::cast(kv.value); @@ -95,6 +100,17 @@ HashMap OpenXRExtensionWrapper::get_requested_extensions() { return result; } +#ifndef DISABLE_DEPRECATED + if (GDVIRTUAL_CALL(_get_requested_extensions_bind_compat_109302, request_extension)) { + HashMap result; + for (const KeyValue &kv : request_extension) { + GDExtensionPtr value = VariantCaster>::cast(kv.value); + result.insert(kv.key, value); + } + return result; + } +#endif + return HashMap(); } @@ -108,13 +124,19 @@ void *OpenXRExtensionWrapper::set_system_properties_and_get_next_pointer(void *p return nullptr; } -void *OpenXRExtensionWrapper::set_instance_create_info_and_get_next_pointer(void *p_next_pointer) { +void *OpenXRExtensionWrapper::set_instance_create_info_and_get_next_pointer(XrVersion p_xr_version, void *p_next_pointer) { uint64_t pointer; - if (GDVIRTUAL_CALL(_set_instance_create_info_and_get_next_pointer, GDExtensionPtr(p_next_pointer), pointer)) { + if (GDVIRTUAL_CALL(_set_instance_create_info_and_get_next_pointer, (uint64_t)p_xr_version, GDExtensionPtr(p_next_pointer), pointer)) { return reinterpret_cast(pointer); } +#ifndef DISABLE_DEPRECATED + if (GDVIRTUAL_CALL(_set_instance_create_info_and_get_next_pointer_bind_compat_109302, GDExtensionPtr(p_next_pointer), pointer)) { + return reinterpret_cast(pointer); + } +#endif + return nullptr; } diff --git a/modules/openxr/extensions/openxr_extension_wrapper.h b/modules/openxr/extensions/openxr_extension_wrapper.h index 5729df237a2..34af812b654 100644 --- a/modules/openxr/extensions/openxr_extension_wrapper.h +++ b/modules/openxr/extensions/openxr_extension_wrapper.h @@ -60,12 +60,15 @@ protected: public: // `get_requested_extensions` should return a list of OpenXR extensions related to this extension. + // This function can be called multiple times. + // p_xr_version is the OpenXR version which we're attempting to initialize. + // Note: when called from the editor, p_xr_version will be 0 and we should return any extension we may initialize. // If the bool * is a nullptr this extension is mandatory // If the bool * points to a boolean, the boolean will be updated // to true if the extension is enabled. - virtual HashMap get_requested_extensions(); + virtual HashMap get_requested_extensions(XrVersion p_xr_version); - GDVIRTUAL0R(Dictionary, _get_requested_extensions); + GDVIRTUAL1R(Dictionary, _get_requested_extensions, uint64_t); // These functions allow an extension to add entries to a struct chain. // `p_next_pointer` points to the last struct that was created for this chain @@ -74,7 +77,7 @@ public: // If you are not adding any structs, just return `p_next_pointer`. // See existing extensions for examples of this implementation. virtual void *set_system_properties_and_get_next_pointer(void *p_next_pointer); // Add additional data structures when we interrogate OpenXR's system abilities. - virtual void *set_instance_create_info_and_get_next_pointer(void *p_next_pointer); // Add additional data structures when we create our OpenXR instance. + virtual void *set_instance_create_info_and_get_next_pointer(XrVersion p_xr_version, void *p_next_pointer); // Add additional data structures when we create our OpenXR instance. virtual void *set_session_create_and_get_next_pointer(void *p_next_pointer); // Add additional data structures when we create our OpenXR session. virtual void *set_swapchain_create_info_and_get_next_pointer(void *p_next_pointer); // Add additional data structures when creating OpenXR swap chains. virtual void *set_hand_joint_locations_and_get_next_pointer(int p_hand_index, void *p_next_pointer); @@ -91,7 +94,7 @@ public: //TODO workaround as GDExtensionPtr return type results in build error in godot-cpp GDVIRTUAL1R(uint64_t, _set_system_properties_and_get_next_pointer, GDExtensionPtr); - GDVIRTUAL1R(uint64_t, _set_instance_create_info_and_get_next_pointer, GDExtensionPtr); + GDVIRTUAL2R(uint64_t, _set_instance_create_info_and_get_next_pointer, uint64_t, GDExtensionPtr); GDVIRTUAL1R(uint64_t, _set_session_create_and_get_next_pointer, GDExtensionPtr); GDVIRTUAL1R(uint64_t, _set_swapchain_create_info_and_get_next_pointer, GDExtensionPtr); GDVIRTUAL2R(uint64_t, _set_hand_joint_locations_and_get_next_pointer, int, GDExtensionPtr); @@ -107,6 +110,11 @@ public: GDVIRTUAL2R(uint64_t, _set_view_configuration_and_get_next_pointer, uint32_t, GDExtensionPtr); GDVIRTUAL1C(_print_view_configuration_info, int); +#ifndef DISABLE_DEPRECATED + GDVIRTUAL0R_COMPAT(_get_requested_extensions_bind_compat_109302, Dictionary, _get_requested_extensions); + GDVIRTUAL1R_COMPAT(_set_instance_create_info_and_get_next_pointer_bind_compat_109302, uint64_t, _set_instance_create_info_and_get_next_pointer, GDExtensionPtr); +#endif + virtual PackedStringArray get_suggested_tracker_names(); GDVIRTUAL0R(PackedStringArray, _get_suggested_tracker_names); diff --git a/modules/openxr/extensions/openxr_eye_gaze_interaction.cpp b/modules/openxr/extensions/openxr_eye_gaze_interaction.cpp index 0131a801331..402ac95d551 100644 --- a/modules/openxr/extensions/openxr_eye_gaze_interaction.cpp +++ b/modules/openxr/extensions/openxr_eye_gaze_interaction.cpp @@ -51,7 +51,7 @@ OpenXREyeGazeInteractionExtension::~OpenXREyeGazeInteractionExtension() { singleton = nullptr; } -HashMap OpenXREyeGazeInteractionExtension::get_requested_extensions() { +HashMap OpenXREyeGazeInteractionExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; // Only enable this extension when requested. diff --git a/modules/openxr/extensions/openxr_eye_gaze_interaction.h b/modules/openxr/extensions/openxr_eye_gaze_interaction.h index f8a2d43d655..acc3e4eb7b1 100644 --- a/modules/openxr/extensions/openxr_eye_gaze_interaction.h +++ b/modules/openxr/extensions/openxr_eye_gaze_interaction.h @@ -44,7 +44,7 @@ public: OpenXREyeGazeInteractionExtension(); ~OpenXREyeGazeInteractionExtension(); - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; virtual void *set_system_properties_and_get_next_pointer(void *p_next_pointer) override; PackedStringArray get_suggested_tracker_names() override; diff --git a/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.cpp b/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.cpp index 402389144ab..fc229cbe0bd 100644 --- a/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.cpp +++ b/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.cpp @@ -45,7 +45,7 @@ OpenXRDisplayRefreshRateExtension::~OpenXRDisplayRefreshRateExtension() { display_refresh_rate_ext = false; } -HashMap OpenXRDisplayRefreshRateExtension::get_requested_extensions() { +HashMap OpenXRDisplayRefreshRateExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; request_extensions[XR_FB_DISPLAY_REFRESH_RATE_EXTENSION_NAME] = &display_refresh_rate_ext; diff --git a/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.h b/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.h index 532e353edf3..c184314fbc7 100644 --- a/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.h +++ b/modules/openxr/extensions/openxr_fb_display_refresh_rate_extension.h @@ -51,7 +51,7 @@ public: OpenXRDisplayRefreshRateExtension(); virtual ~OpenXRDisplayRefreshRateExtension() override; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; virtual void on_instance_created(const XrInstance p_instance) override; virtual void on_instance_destroyed() override; diff --git a/modules/openxr/extensions/openxr_fb_foveation_extension.cpp b/modules/openxr/extensions/openxr_fb_foveation_extension.cpp index 79eea0ec385..07a3bf475a6 100644 --- a/modules/openxr/extensions/openxr_fb_foveation_extension.cpp +++ b/modules/openxr/extensions/openxr_fb_foveation_extension.cpp @@ -75,7 +75,7 @@ OpenXRFBFoveationExtension::~OpenXRFBFoveationExtension() { swapchain_update_state_ext = nullptr; } -HashMap OpenXRFBFoveationExtension::get_requested_extensions() { +HashMap OpenXRFBFoveationExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; request_extensions[XR_FB_FOVEATION_EXTENSION_NAME] = &fb_foveation_ext; diff --git a/modules/openxr/extensions/openxr_fb_foveation_extension.h b/modules/openxr/extensions/openxr_fb_foveation_extension.h index 0cc0804eff5..f1aec59c57d 100644 --- a/modules/openxr/extensions/openxr_fb_foveation_extension.h +++ b/modules/openxr/extensions/openxr_fb_foveation_extension.h @@ -52,7 +52,7 @@ public: OpenXRFBFoveationExtension(const String &p_rendering_driver); virtual ~OpenXRFBFoveationExtension() override; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; virtual void on_instance_created(const XrInstance p_instance) override; virtual void on_instance_destroyed() override; diff --git a/modules/openxr/extensions/openxr_fb_update_swapchain_extension.cpp b/modules/openxr/extensions/openxr_fb_update_swapchain_extension.cpp index 16ee917de15..9f3ce85a69c 100644 --- a/modules/openxr/extensions/openxr_fb_update_swapchain_extension.cpp +++ b/modules/openxr/extensions/openxr_fb_update_swapchain_extension.cpp @@ -61,7 +61,7 @@ OpenXRFBUpdateSwapchainExtension::~OpenXRFBUpdateSwapchainExtension() { singleton = nullptr; } -HashMap OpenXRFBUpdateSwapchainExtension::get_requested_extensions() { +HashMap OpenXRFBUpdateSwapchainExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; request_extensions[XR_FB_SWAPCHAIN_UPDATE_STATE_EXTENSION_NAME] = &fb_swapchain_update_state_ext; diff --git a/modules/openxr/extensions/openxr_fb_update_swapchain_extension.h b/modules/openxr/extensions/openxr_fb_update_swapchain_extension.h index 242b870ea02..f79bac7ee26 100644 --- a/modules/openxr/extensions/openxr_fb_update_swapchain_extension.h +++ b/modules/openxr/extensions/openxr_fb_update_swapchain_extension.h @@ -54,7 +54,7 @@ public: OpenXRFBUpdateSwapchainExtension(const String &p_rendering_driver); virtual ~OpenXRFBUpdateSwapchainExtension() override; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; virtual void on_instance_created(const XrInstance p_instance) override; virtual void on_instance_destroyed() override; diff --git a/modules/openxr/extensions/openxr_frame_synthesis_extension.cpp b/modules/openxr/extensions/openxr_frame_synthesis_extension.cpp index ef58f0f519a..f547d23ebc3 100644 --- a/modules/openxr/extensions/openxr_frame_synthesis_extension.cpp +++ b/modules/openxr/extensions/openxr_frame_synthesis_extension.cpp @@ -68,7 +68,7 @@ OpenXRFrameSynthesisExtension::~OpenXRFrameSynthesisExtension() { singleton = nullptr; } -HashMap OpenXRFrameSynthesisExtension::get_requested_extensions() { +HashMap OpenXRFrameSynthesisExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; if (GLOBAL_GET("xr/openxr/extensions/frame_synthesis")) { diff --git a/modules/openxr/extensions/openxr_frame_synthesis_extension.h b/modules/openxr/extensions/openxr_frame_synthesis_extension.h index 1b454b58948..3189f354aa8 100644 --- a/modules/openxr/extensions/openxr_frame_synthesis_extension.h +++ b/modules/openxr/extensions/openxr_frame_synthesis_extension.h @@ -44,7 +44,7 @@ public: OpenXRFrameSynthesisExtension(); virtual ~OpenXRFrameSynthesisExtension() override; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; virtual void on_instance_created(const XrInstance p_instance) override; virtual void on_instance_destroyed() override; diff --git a/modules/openxr/extensions/openxr_future_extension.cpp b/modules/openxr/extensions/openxr_future_extension.cpp index 9d7e7afdc57..e88b1a945cf 100644 --- a/modules/openxr/extensions/openxr_future_extension.cpp +++ b/modules/openxr/extensions/openxr_future_extension.cpp @@ -129,7 +129,7 @@ void OpenXRFutureExtension::_bind_methods() { ClassDB::bind_method(D_METHOD("cancel_future", "future"), &OpenXRFutureExtension::_cancel_future); } -HashMap OpenXRFutureExtension::get_requested_extensions() { +HashMap OpenXRFutureExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; request_extensions[XR_EXT_FUTURE_EXTENSION_NAME] = &future_ext; diff --git a/modules/openxr/extensions/openxr_future_extension.h b/modules/openxr/extensions/openxr_future_extension.h index 5ebaf5bbfd6..dfb434b830c 100644 --- a/modules/openxr/extensions/openxr_future_extension.h +++ b/modules/openxr/extensions/openxr_future_extension.h @@ -104,7 +104,7 @@ public: OpenXRFutureExtension(); virtual ~OpenXRFutureExtension() override; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; virtual void on_instance_created(const XrInstance p_instance) override; virtual void on_instance_destroyed() override; diff --git a/modules/openxr/extensions/openxr_hand_interaction_extension.cpp b/modules/openxr/extensions/openxr_hand_interaction_extension.cpp index 4d91eeca1fc..a0d30097687 100644 --- a/modules/openxr/extensions/openxr_hand_interaction_extension.cpp +++ b/modules/openxr/extensions/openxr_hand_interaction_extension.cpp @@ -31,6 +31,7 @@ #include "openxr_hand_interaction_extension.h" #include "../action_map/openxr_interaction_profile_metadata.h" +#include "../openxr_api.h" #include "core/config/project_settings.h" #include @@ -49,7 +50,7 @@ OpenXRHandInteractionExtension::~OpenXRHandInteractionExtension() { singleton = nullptr; } -HashMap OpenXRHandInteractionExtension::get_requested_extensions() { +HashMap OpenXRHandInteractionExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; // Only enable this extension when requested. @@ -78,7 +79,7 @@ void OpenXRHandInteractionExtension::on_register_metadata() { openxr_metadata->register_io_path(profile_path, "Aim pose", user_path, user_path + "/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Pinch pose", user_path, user_path + "/input/pinch_ext/pose", "", OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Poke pose", user_path, user_path + "/input/poke_ext/pose", "", OpenXRAction::OPENXR_ACTION_POSE); - openxr_metadata->register_io_path(profile_path, "Palm pose", user_path, user_path + "/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + openxr_metadata->register_io_path(profile_path, "Grip surface pose", user_path, user_path + "/input/grip_surface/pose", XR_EXT_PALM_POSE_EXTENSION_NAME "," XR_KHR_MAINTENANCE1_EXTENSION_NAME "," XR_OPENXR_1_1_NAME, OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Pinch", user_path, user_path + "/input/pinch_ext/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); openxr_metadata->register_io_path(profile_path, "Pinch ready", user_path, user_path + "/input/pinch_ext/ready_ext", "", OpenXRAction::OPENXR_ACTION_BOOL); diff --git a/modules/openxr/extensions/openxr_hand_interaction_extension.h b/modules/openxr/extensions/openxr_hand_interaction_extension.h index e93ce403054..a9c2f3181fe 100644 --- a/modules/openxr/extensions/openxr_hand_interaction_extension.h +++ b/modules/openxr/extensions/openxr_hand_interaction_extension.h @@ -61,7 +61,7 @@ public: OpenXRHandInteractionExtension(); virtual ~OpenXRHandInteractionExtension() override; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; bool is_available(); diff --git a/modules/openxr/extensions/openxr_hand_tracking_extension.cpp b/modules/openxr/extensions/openxr_hand_tracking_extension.cpp index 6f4e3ede592..44729817d5e 100644 --- a/modules/openxr/extensions/openxr_hand_tracking_extension.cpp +++ b/modules/openxr/extensions/openxr_hand_tracking_extension.cpp @@ -55,7 +55,7 @@ OpenXRHandTrackingExtension::~OpenXRHandTrackingExtension() { singleton = nullptr; } -HashMap OpenXRHandTrackingExtension::get_requested_extensions() { +HashMap OpenXRHandTrackingExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; unobstructed_data_source = GLOBAL_GET("xr/openxr/extensions/hand_tracking_unobstructed_data_source"); diff --git a/modules/openxr/extensions/openxr_hand_tracking_extension.h b/modules/openxr/extensions/openxr_hand_tracking_extension.h index 9c433f20b99..7a301b384aa 100644 --- a/modules/openxr/extensions/openxr_hand_tracking_extension.h +++ b/modules/openxr/extensions/openxr_hand_tracking_extension.h @@ -76,7 +76,7 @@ public: OpenXRHandTrackingExtension(); virtual ~OpenXRHandTrackingExtension() override; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; virtual void on_instance_created(const XrInstance p_instance) override; virtual void on_instance_destroyed() override; diff --git a/modules/openxr/extensions/openxr_htc_controller_extension.cpp b/modules/openxr/extensions/openxr_htc_controller_extension.cpp index 122754a28ea..e395da70245 100644 --- a/modules/openxr/extensions/openxr_htc_controller_extension.cpp +++ b/modules/openxr/extensions/openxr_htc_controller_extension.cpp @@ -31,12 +31,17 @@ #include "openxr_htc_controller_extension.h" #include "../action_map/openxr_interaction_profile_metadata.h" +#include "../openxr_api.h" -HashMap OpenXRHTCControllerExtension::get_requested_extensions() { +HashMap OpenXRHTCControllerExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; - request_extensions[XR_HTC_VIVE_COSMOS_CONTROLLER_INTERACTION_EXTENSION_NAME] = &available[HTC_VIVE_COSMOS]; - request_extensions[XR_HTC_VIVE_FOCUS3_CONTROLLER_INTERACTION_EXTENSION_NAME] = &available[HTC_VIVE_FOCUS3]; + if (p_version < XR_API_VERSION_1_1_0) { + // Extensions where promoted in OpenXR 1.1, only include it in OpenXR 1.0. + request_extensions[XR_HTC_VIVE_COSMOS_CONTROLLER_INTERACTION_EXTENSION_NAME] = &available[HTC_VIVE_COSMOS]; + request_extensions[XR_HTC_VIVE_FOCUS3_CONTROLLER_INTERACTION_EXTENSION_NAME] = &available[HTC_VIVE_FOCUS3]; + } + request_extensions[XR_HTC_HAND_INTERACTION_EXTENSION_NAME] = &available[HTC_HAND_INTERACTION]; return request_extensions; @@ -63,11 +68,11 @@ void OpenXRHTCControllerExtension::on_register_metadata() { { // HTC Vive Cosmos controller const String profile_path = "/interaction_profiles/htc/vive_cosmos_controller"; - openxr_metadata->register_interaction_profile("Vive Cosmos controller", profile_path, XR_HTC_VIVE_COSMOS_CONTROLLER_INTERACTION_EXTENSION_NAME); + openxr_metadata->register_interaction_profile("Vive Cosmos controller", profile_path, XR_HTC_VIVE_COSMOS_CONTROLLER_INTERACTION_EXTENSION_NAME "," XR_OPENXR_1_1_NAME); for (const String user_path : { "/user/hand/left", "/user/hand/right" }) { openxr_metadata->register_io_path(profile_path, "Grip pose", user_path, user_path + "/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Aim pose", user_path, user_path + "/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); - openxr_metadata->register_io_path(profile_path, "Palm pose", user_path, user_path + "/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + openxr_metadata->register_io_path(profile_path, "Grip surface pose", user_path, user_path + "/input/grip_surface/pose", XR_EXT_PALM_POSE_EXTENSION_NAME "," XR_KHR_MAINTENANCE1_EXTENSION_NAME "," XR_OPENXR_1_1_NAME, OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Shoulder click", user_path, user_path + "/input/shoulder/click", "", OpenXRAction::OPENXR_ACTION_BOOL); @@ -98,11 +103,11 @@ void OpenXRHTCControllerExtension::on_register_metadata() { { // HTC Vive Focus 3 controller const String profile_path = "/interaction_profiles/htc/vive_focus3_controller"; - openxr_metadata->register_interaction_profile("Vive Focus 3 controller", profile_path, XR_HTC_VIVE_FOCUS3_CONTROLLER_INTERACTION_EXTENSION_NAME); + openxr_metadata->register_interaction_profile("Vive Focus 3 controller", profile_path, XR_HTC_VIVE_FOCUS3_CONTROLLER_INTERACTION_EXTENSION_NAME "," XR_OPENXR_1_1_NAME); for (const String user_path : { "/user/hand/left", "/user/hand/right" }) { openxr_metadata->register_io_path(profile_path, "Grip pose", user_path, user_path + "/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Aim pose", user_path, user_path + "/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); - openxr_metadata->register_io_path(profile_path, "Palm pose", user_path, user_path + "/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + openxr_metadata->register_io_path(profile_path, "Grip surface pose", user_path, user_path + "/input/grip_surface/pose", XR_EXT_PALM_POSE_EXTENSION_NAME "," XR_KHR_MAINTENANCE1_EXTENSION_NAME "," XR_OPENXR_1_1_NAME, OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Trigger", user_path, user_path + "/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); openxr_metadata->register_io_path(profile_path, "Trigger click", user_path, user_path + "/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); diff --git a/modules/openxr/extensions/openxr_htc_controller_extension.h b/modules/openxr/extensions/openxr_htc_controller_extension.h index 13c9d2ace2f..6cbc860574a 100644 --- a/modules/openxr/extensions/openxr_htc_controller_extension.h +++ b/modules/openxr/extensions/openxr_htc_controller_extension.h @@ -47,7 +47,7 @@ public: HTC_MAX_CONTROLLERS }; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; PackedStringArray get_suggested_tracker_names() override; diff --git a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp index dd3a32e4748..41e49175141 100644 --- a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp +++ b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp @@ -34,7 +34,7 @@ #include "core/string/print_string.h" -HashMap OpenXRHTCViveTrackerExtension::get_requested_extensions() { +HashMap OpenXRHTCViveTrackerExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; request_extensions[XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME] = &available; diff --git a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.h b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.h index a6f766da035..47c30e60512 100644 --- a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.h +++ b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.h @@ -39,7 +39,7 @@ protected: static void _bind_methods() {} public: - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; PackedStringArray get_suggested_tracker_names() override; diff --git a/modules/openxr/extensions/openxr_huawei_controller_extension.cpp b/modules/openxr/extensions/openxr_huawei_controller_extension.cpp index a89fb40f101..15efcec9db6 100644 --- a/modules/openxr/extensions/openxr_huawei_controller_extension.cpp +++ b/modules/openxr/extensions/openxr_huawei_controller_extension.cpp @@ -31,8 +31,9 @@ #include "openxr_huawei_controller_extension.h" #include "../action_map/openxr_interaction_profile_metadata.h" +#include "../openxr_api.h" -HashMap OpenXRHuaweiControllerExtension::get_requested_extensions() { +HashMap OpenXRHuaweiControllerExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; request_extensions[XR_HUAWEI_CONTROLLER_INTERACTION_EXTENSION_NAME] = &available; @@ -55,6 +56,7 @@ void OpenXRHuaweiControllerExtension::on_register_metadata() { openxr_metadata->register_io_path(profile_path, "Grip pose", user_path, user_path + "/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Aim pose", user_path, user_path + "/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Palm pose", user_path, user_path + "/input/palm_ext/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + openxr_metadata->register_io_path(profile_path, "Grip surface pose", user_path, user_path + "/input/grip_surface/pose", XR_OPENXR_1_1_NAME, OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Home click", user_path, user_path + "/input/home/click", "", OpenXRAction::OPENXR_ACTION_BOOL); openxr_metadata->register_io_path(profile_path, "Back click", user_path, user_path + "/input/back/click", "", OpenXRAction::OPENXR_ACTION_BOOL); diff --git a/modules/openxr/extensions/openxr_huawei_controller_extension.h b/modules/openxr/extensions/openxr_huawei_controller_extension.h index 77d5bee0c8e..39a5b3877c7 100644 --- a/modules/openxr/extensions/openxr_huawei_controller_extension.h +++ b/modules/openxr/extensions/openxr_huawei_controller_extension.h @@ -39,7 +39,7 @@ protected: static void _bind_methods() {} public: - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; bool is_available(); diff --git a/modules/openxr/extensions/openxr_local_floor_extension.cpp b/modules/openxr/extensions/openxr_local_floor_extension.cpp index 5e17ba715b7..91d7f1ea942 100644 --- a/modules/openxr/extensions/openxr_local_floor_extension.cpp +++ b/modules/openxr/extensions/openxr_local_floor_extension.cpp @@ -30,6 +30,8 @@ #include "openxr_local_floor_extension.h" +#include "../openxr_api.h" + OpenXRLocalFloorExtension *OpenXRLocalFloorExtension::singleton = nullptr; OpenXRLocalFloorExtension *OpenXRLocalFloorExtension::get_singleton() { @@ -44,10 +46,13 @@ OpenXRLocalFloorExtension::~OpenXRLocalFloorExtension() { singleton = nullptr; } -HashMap OpenXRLocalFloorExtension::get_requested_extensions() { +HashMap OpenXRLocalFloorExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; - request_extensions[XR_EXT_LOCAL_FLOOR_EXTENSION_NAME] = &available; + if (p_version < XR_API_VERSION_1_1_0) { + // Extension was promoted in OpenXR 1.1, only include it in OpenXR 1.0. + request_extensions[XR_EXT_LOCAL_FLOOR_EXTENSION_NAME] = &available; + } return request_extensions; } diff --git a/modules/openxr/extensions/openxr_local_floor_extension.h b/modules/openxr/extensions/openxr_local_floor_extension.h index a3899b4a16c..50b44bac0a1 100644 --- a/modules/openxr/extensions/openxr_local_floor_extension.h +++ b/modules/openxr/extensions/openxr_local_floor_extension.h @@ -44,7 +44,7 @@ public: OpenXRLocalFloorExtension(); virtual ~OpenXRLocalFloorExtension() override; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; bool is_available(); diff --git a/modules/openxr/extensions/openxr_meta_controller_extension.cpp b/modules/openxr/extensions/openxr_meta_controller_extension.cpp index add959e76aa..1fc8f5ee0c6 100644 --- a/modules/openxr/extensions/openxr_meta_controller_extension.cpp +++ b/modules/openxr/extensions/openxr_meta_controller_extension.cpp @@ -31,13 +31,30 @@ #include "openxr_meta_controller_extension.h" #include "../action_map/openxr_interaction_profile_metadata.h" +#include "../openxr_api.h" -HashMap OpenXRMetaControllerExtension::get_requested_extensions() { +const char *touch_controller = "/interaction_profiles/oculus/touch_controller"; +const char *touch_pro_controller = "/interaction_profiles/meta/touch_pro_controller"; +const char *touch_plus_controller = "/interaction_profiles/meta/touch_plus_controller"; +const char *rift_cv1_controller = "/interaction_profiles/meta/touch_controller_rift_cv1"; +const char *quest1_rift_s_controller = "/interaction_profiles/meta/touch_controller_quest_1_rift_s"; +const char *quest2_controller = "/interaction_profiles/meta/touch_controller_quest_2"; + +// Vendor extension paths (promoted) +const char *touch_controller_pro_fb = "/interaction_profiles/facebook/touch_controller_pro"; +const char *touch_controller_plus_fb = "/interaction_profiles/facebook/touch_controller_plus"; +const char *touch_controller_plus_meta = "/interaction_profiles/meta/touch_controller_plus"; + +HashMap OpenXRMetaControllerExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; + if (p_version < XR_API_VERSION_1_1_0) { + // Extensions where promoted in OpenXR 1.1, only include it in OpenXR 1.0. + request_extensions[XR_FB_TOUCH_CONTROLLER_PRO_EXTENSION_NAME] = &available[META_TOUCH_PRO]; + request_extensions[XR_META_TOUCH_CONTROLLER_PLUS_EXTENSION_NAME] = &available[META_TOUCH_PLUS]; + } + request_extensions[XR_FB_TOUCH_CONTROLLER_PROXIMITY_EXTENSION_NAME] = &available[META_TOUCH_PROXIMITY]; - request_extensions[XR_FB_TOUCH_CONTROLLER_PRO_EXTENSION_NAME] = &available[META_TOUCH_PRO]; - request_extensions[XR_META_TOUCH_CONTROLLER_PLUS_EXTENSION_NAME] = &available[META_TOUCH_PLUS]; return request_extensions; } @@ -50,34 +67,69 @@ void OpenXRMetaControllerExtension::on_register_metadata() { OpenXRInteractionProfileMetadata *openxr_metadata = OpenXRInteractionProfileMetadata::get_singleton(); ERR_FAIL_NULL(openxr_metadata); - // Note, we register controllers regardless if they are supported on the current hardware. + // Note, we register controllers regardless if they are supported on the current hardware, + // this allows the editor to configure controllers for other platforms. + // Unsupported entries will be filtered out of the action map if applicable. - { // Normal touch controller is part of the core spec, but we do have some extensions. - const String profile_path = "/interaction_profiles/oculus/touch_controller"; + // OpenXR 1.1 uses various new names for profile and input/output paths. + // We use these new names in our action map and translate back IF OpenXR 1.1 is not supported. + openxr_metadata->register_profile_rename(touch_controller_pro_fb, touch_pro_controller); + openxr_metadata->register_profile_rename(touch_controller_plus_fb, touch_controller_plus_meta); // This was an incorrect profile path that we need to correct. + openxr_metadata->register_profile_rename(touch_controller_plus_meta, touch_plus_controller); + + openxr_metadata->register_path_rename("/user/hand/left/input/stylus_fb/force", "/user/hand/left/input/stylus/force"); + openxr_metadata->register_path_rename("/user/hand/right/input/stylus_fb/force", "/user/hand/right/input/stylus/force"); + openxr_metadata->register_path_rename("/user/hand/left/input/trigger/proximity_fb", "/user/hand/left/input/trigger/proximity"); + openxr_metadata->register_path_rename("/user/hand/right/input/trigger/proximity_fb", "/user/hand/right/input/trigger/proximity"); + openxr_metadata->register_path_rename("/user/hand/left/output/haptic_trigger_fb", "/user/hand/left/output/haptic_trigger"); + openxr_metadata->register_path_rename("/user/hand/right/output/haptic_trigger_fb", "/user/hand/right/output/haptic_trigger"); + openxr_metadata->register_path_rename("/user/hand/left/output/haptic_thumb_fb", "/user/hand/left/output/haptic_thumb"); + openxr_metadata->register_path_rename("/user/hand/right/output/haptic_thumb_fb", "/user/hand/right/output/haptic_thumb"); + openxr_metadata->register_path_rename("/user/hand/left/input/thumb_fb/proximity_fb", "/user/hand/left/input/thumb_resting_surfaces/proximity"); + openxr_metadata->register_path_rename("/user/hand/right/input/thumb_fb/proximity_fb", "/user/hand/right/input/thumb_resting_surfaces/proximity"); + openxr_metadata->register_path_rename("/user/hand/left/input/trigger/curl_fb", "/user/hand/left/input/trigger_curl/value"); + openxr_metadata->register_path_rename("/user/hand/right/input/trigger/curl_fb", "/user/hand/right/input/trigger_curl/value"); + openxr_metadata->register_path_rename("/user/hand/left/input/trigger/slide_fb", "/user/hand/left/input/trigger_slide/value"); + openxr_metadata->register_path_rename("/user/hand/right/input/trigger/slide_fb", "/user/hand/right/input/trigger_slide/value"); + + openxr_metadata->register_path_rename("/user/hand/left/input/trigger/proximity_meta", "/user/hand/left/input/trigger/proximity"); + openxr_metadata->register_path_rename("/user/hand/right/input/trigger/proximity_meta", "/user/hand/right/input/trigger/proximity"); + openxr_metadata->register_path_rename("/user/hand/left/input/thumb_meta/proximity_meta", "/user/hand/left/input/thumb_resting_surfaces/proximity"); + openxr_metadata->register_path_rename("/user/hand/right/input/thumb_meta/proximity_meta", "/user/hand/right/input/thumb_resting_surfaces/proximity"); + openxr_metadata->register_path_rename("/user/hand/left/input/trigger/curl_meta", "/user/hand/left/input/trigger_curl/value"); + openxr_metadata->register_path_rename("/user/hand/right/input/trigger/curl_meta", "/user/hand/right/input/trigger_curl/value"); + openxr_metadata->register_path_rename("/user/hand/left/input/trigger/slide_meta", "/user/hand/left/input/trigger_slide/value"); + openxr_metadata->register_path_rename("/user/hand/right/input/trigger/slide_meta", "/user/hand/right/input/trigger_slide/value"); + + { // Normal touch controller is part of the core spec and still relies on the XR_FB_touch_controller_proximity extension for these two new paths. + const String profile_path = touch_controller; for (const String user_path : { "/user/hand/left", "/user/hand/right" }) { - openxr_metadata->register_io_path(profile_path, "Trigger proximity", user_path, user_path + "/input/trigger/proximity_fb ", "XR_FB_touch_controller_proximity", OpenXRAction::OPENXR_ACTION_BOOL); - openxr_metadata->register_io_path(profile_path, "Thumb proximity", user_path, user_path + "/input/thumb_fb/proximity_fb ", "XR_FB_touch_controller_proximity", OpenXRAction::OPENXR_ACTION_BOOL); + openxr_metadata->register_io_path(profile_path, "Trigger proximity", user_path, user_path + "/input/trigger/proximity", XR_FB_TOUCH_CONTROLLER_PROXIMITY_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_BOOL); + openxr_metadata->register_io_path(profile_path, "Thumb proximity", user_path, user_path + "/input/thumb_resting_surfaces/proximity", XR_FB_TOUCH_CONTROLLER_PROXIMITY_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_BOOL); } } { // Touch controller pro (Quest Pro) - const String profile_path = "/interaction_profiles/facebook/touch_controller_pro"; - openxr_metadata->register_interaction_profile("Touch controller pro", profile_path, "XR_FB_touch_controller_pro"); + const String profile_path = touch_pro_controller; + openxr_metadata->register_interaction_profile("Touch controller pro", profile_path, XR_FB_TOUCH_CONTROLLER_PRO_EXTENSION_NAME "," XR_OPENXR_1_1_NAME); for (const String user_path : { "/user/hand/left", "/user/hand/right" }) { openxr_metadata->register_io_path(profile_path, "Grip pose", user_path, user_path + "/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Aim pose", user_path, user_path + "/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); - openxr_metadata->register_io_path(profile_path, "Palm pose", user_path, user_path + "/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + openxr_metadata->register_io_path(profile_path, "Grip surface pose", user_path, user_path + "/input/grip_surface/pose", XR_EXT_PALM_POSE_EXTENSION_NAME "," XR_KHR_MAINTENANCE1_EXTENSION_NAME "," XR_OPENXR_1_1_NAME, OpenXRAction::OPENXR_ACTION_POSE); + + openxr_metadata->register_io_path(profile_path, "Pinch pose", user_path, user_path + "/input/pinch_ext/pose", XR_EXT_HAND_INTERACTION_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + openxr_metadata->register_io_path(profile_path, "Poke pose", user_path, user_path + "/input/poke_ext/pose", XR_EXT_HAND_INTERACTION_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Trigger", user_path, user_path + "/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); openxr_metadata->register_io_path(profile_path, "Trigger touch", user_path, user_path + "/input/trigger/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); - openxr_metadata->register_io_path(profile_path, "Trigger proximity", user_path, user_path + "/input/trigger/proximity_fb", "", OpenXRAction::OPENXR_ACTION_BOOL); - openxr_metadata->register_io_path(profile_path, "Trigger curl", user_path, user_path + "/input/trigger/curl_fb", "", OpenXRAction::OPENXR_ACTION_FLOAT); - openxr_metadata->register_io_path(profile_path, "Trigger slide", user_path, user_path + "/input/trigger/slide_fb", "", OpenXRAction::OPENXR_ACTION_FLOAT); + openxr_metadata->register_io_path(profile_path, "Trigger proximity", user_path, user_path + "/input/trigger/proximity", "", OpenXRAction::OPENXR_ACTION_BOOL); + openxr_metadata->register_io_path(profile_path, "Trigger curl", user_path, user_path + "/input/trigger_curl/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + openxr_metadata->register_io_path(profile_path, "Trigger slide", user_path, user_path + "/input/trigger_slide/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); openxr_metadata->register_io_path(profile_path, "Trigger force", user_path, user_path + "/input/trigger/force", "", OpenXRAction::OPENXR_ACTION_FLOAT); openxr_metadata->register_io_path(profile_path, "Squeeze", user_path, user_path + "/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); - openxr_metadata->register_io_path(profile_path, "Thumb proximity", user_path, user_path + "/input/thumb_fb/proximity_fb", "", OpenXRAction::OPENXR_ACTION_BOOL); + openxr_metadata->register_io_path(profile_path, "Thumb proximity", user_path, user_path + "/input/thumb_resting_surfaces/proximity", "", OpenXRAction::OPENXR_ACTION_BOOL); openxr_metadata->register_io_path(profile_path, "Thumbstick", user_path, user_path + "/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2); openxr_metadata->register_io_path(profile_path, "Thumbstick X", user_path, user_path + "/input/thumbstick/x", "", OpenXRAction::OPENXR_ACTION_FLOAT); @@ -92,11 +144,11 @@ void OpenXRMetaControllerExtension::on_register_metadata() { openxr_metadata->register_io_path(profile_path, "Thumbrest touch", user_path, user_path + "/input/thumbrest/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); openxr_metadata->register_io_path(profile_path, "Thumbrest force", user_path, user_path + "/input/thumbrest/force", "", OpenXRAction::OPENXR_ACTION_FLOAT); - openxr_metadata->register_io_path(profile_path, "Stylus force", user_path, user_path + "/input/stylus_fb/force", "", OpenXRAction::OPENXR_ACTION_FLOAT); + openxr_metadata->register_io_path(profile_path, "Stylus force", user_path, user_path + "/input/stylus/force", "", OpenXRAction::OPENXR_ACTION_FLOAT); openxr_metadata->register_io_path(profile_path, "Haptic output", user_path, user_path + "/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); - openxr_metadata->register_io_path(profile_path, "Haptic trigger output", user_path, user_path + "/output/haptic_trigger_fb", "", OpenXRAction::OPENXR_ACTION_HAPTIC); - openxr_metadata->register_io_path(profile_path, "Haptic thumb output", user_path, user_path + "/output/haptic_thumb_fb", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + openxr_metadata->register_io_path(profile_path, "Haptic trigger output", user_path, user_path + "/output/haptic_trigger", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + openxr_metadata->register_io_path(profile_path, "Haptic thumb output", user_path, user_path + "/output/haptic_thumb", "", OpenXRAction::OPENXR_ACTION_HAPTIC); } openxr_metadata->register_io_path(profile_path, "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); @@ -112,24 +164,27 @@ void OpenXRMetaControllerExtension::on_register_metadata() { openxr_metadata->register_io_path(profile_path, "B touch", "/user/hand/right", "/user/hand/right/input/b/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); } - { // Touch controller plus (Quest 3) - const String profile_path = "/interaction_profiles/meta/touch_controller_plus"; - openxr_metadata->register_interaction_profile("Touch controller plus", profile_path, "XR_META_touch_controller_plus"); + { // Touch controller plus (Quest 3 + 3S) + const String profile_path = touch_plus_controller; + openxr_metadata->register_interaction_profile("Touch controller plus", profile_path, XR_META_TOUCH_CONTROLLER_PLUS_EXTENSION_NAME "," XR_OPENXR_1_1_NAME); for (const String user_path : { "/user/hand/left", "/user/hand/right" }) { openxr_metadata->register_io_path(profile_path, "Grip pose", user_path, user_path + "/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Aim pose", user_path, user_path + "/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); - openxr_metadata->register_io_path(profile_path, "Palm pose", user_path, user_path + "/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + openxr_metadata->register_io_path(profile_path, "Grip surface pose", user_path, user_path + "/input/grip_surface/pose", XR_EXT_PALM_POSE_EXTENSION_NAME "," XR_KHR_MAINTENANCE1_EXTENSION_NAME "," XR_OPENXR_1_1_NAME, OpenXRAction::OPENXR_ACTION_POSE); + + openxr_metadata->register_io_path(profile_path, "Pinch pose", user_path, user_path + "/input/pinch_ext/pose", XR_EXT_HAND_INTERACTION_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + openxr_metadata->register_io_path(profile_path, "Poke pose", user_path, user_path + "/input/poke_ext/pose", XR_EXT_HAND_INTERACTION_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Trigger", user_path, user_path + "/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); openxr_metadata->register_io_path(profile_path, "Trigger touch", user_path, user_path + "/input/trigger/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); - openxr_metadata->register_io_path(profile_path, "Trigger proximity", user_path, user_path + "/input/trigger/proximity_meta", "", OpenXRAction::OPENXR_ACTION_BOOL); - openxr_metadata->register_io_path(profile_path, "Trigger curl", user_path, user_path + "/input/trigger/curl_meta", "", OpenXRAction::OPENXR_ACTION_FLOAT); - openxr_metadata->register_io_path(profile_path, "Trigger slide", user_path, user_path + "/input/trigger/slide_meta", "", OpenXRAction::OPENXR_ACTION_FLOAT); + openxr_metadata->register_io_path(profile_path, "Trigger proximity", user_path, user_path + "/input/trigger/proximity", "", OpenXRAction::OPENXR_ACTION_BOOL); + openxr_metadata->register_io_path(profile_path, "Trigger curl", user_path, user_path + "/input/trigger_curl/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + openxr_metadata->register_io_path(profile_path, "Trigger slide", user_path, user_path + "/input/trigger_slide/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); openxr_metadata->register_io_path(profile_path, "Trigger force", user_path, user_path + "/input/trigger/force", "", OpenXRAction::OPENXR_ACTION_FLOAT); openxr_metadata->register_io_path(profile_path, "Squeeze", user_path, user_path + "/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); - openxr_metadata->register_io_path(profile_path, "Thumb proximity", user_path, user_path + "/input/thumb_meta/proximity_meta", "", OpenXRAction::OPENXR_ACTION_BOOL); + openxr_metadata->register_io_path(profile_path, "Thumb proximity", user_path, user_path + "/input/thumb_resting_surfaces/proximity", "", OpenXRAction::OPENXR_ACTION_BOOL); openxr_metadata->register_io_path(profile_path, "Thumbstick", user_path, user_path + "/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2); openxr_metadata->register_io_path(profile_path, "Thumbstick X", user_path, user_path + "/input/thumbstick/x", "", OpenXRAction::OPENXR_ACTION_FLOAT); @@ -158,4 +213,57 @@ void OpenXRMetaControllerExtension::on_register_metadata() { openxr_metadata->register_io_path(profile_path, "B click", "/user/hand/right", "/user/hand/right/input/b/click", "", OpenXRAction::OPENXR_ACTION_BOOL); openxr_metadata->register_io_path(profile_path, "B touch", "/user/hand/right", "/user/hand/right/input/b/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); } + + { + // In OpenXR 1.1 we have controller profiles for Meta legacy controllers. They are all the same as the normal touch controller profile. + openxr_metadata->register_interaction_profile("Touch controller Rift CV1", rift_cv1_controller, XR_OPENXR_1_1_NAME); + openxr_metadata->register_interaction_profile("Touch controller Quest 1 or Rift S", quest1_rift_s_controller, XR_OPENXR_1_1_NAME); + openxr_metadata->register_interaction_profile("Touch controller Quest 2", quest2_controller, XR_OPENXR_1_1_NAME); + + for (const String profile_path : { rift_cv1_controller, quest1_rift_s_controller, quest2_controller }) { + for (const String user_path : { "/user/hand/left", "/user/hand/right" }) { + openxr_metadata->register_io_path(profile_path, "Grip pose", user_path, user_path + "/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + openxr_metadata->register_io_path(profile_path, "Aim pose", user_path, user_path + "/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + openxr_metadata->register_io_path(profile_path, "Grip surface pose", user_path, user_path + "/input/grip_surface/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + + openxr_metadata->register_io_path(profile_path, "Pinch pose", user_path, user_path + "/input/pinch_ext/pose", XR_EXT_HAND_INTERACTION_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + openxr_metadata->register_io_path(profile_path, "Poke pose", user_path, user_path + "/input/poke_ext/pose", XR_EXT_HAND_INTERACTION_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + + openxr_metadata->register_io_path(profile_path, "Trigger", user_path, user_path + "/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + openxr_metadata->register_io_path(profile_path, "Trigger touch", user_path, user_path + "/input/trigger/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + + openxr_metadata->register_io_path(profile_path, "Squeeze", user_path, user_path + "/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + + // Note, unlike the default touch controller interaction profile, these are not dependent on the XR_FB_touch_controller_proximity extension! + openxr_metadata->register_io_path(profile_path, "Trigger proximity", user_path, user_path + "/input/trigger/proximity", "", OpenXRAction::OPENXR_ACTION_BOOL); + openxr_metadata->register_io_path(profile_path, "Thumb proximity", user_path, user_path + "/input/thumb_resting_surfaces/proximity", "", OpenXRAction::OPENXR_ACTION_BOOL); + + openxr_metadata->register_io_path(profile_path, "Thumbstick", user_path, user_path + "/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + openxr_metadata->register_io_path(profile_path, "Thumbstick X", user_path, user_path + "/input/thumbstick/x", "", OpenXRAction::OPENXR_ACTION_FLOAT); + openxr_metadata->register_io_path(profile_path, "Thumbstick Y", user_path, user_path + "/input/thumbstick/y", "", OpenXRAction::OPENXR_ACTION_FLOAT); + openxr_metadata->register_io_path(profile_path, "Thumbstick click", user_path, user_path + "/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + openxr_metadata->register_io_path(profile_path, "Thumbstick touch", user_path, user_path + "/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + openxr_metadata->register_io_path(profile_path, "Thumbstick Dpad Up", user_path, user_path + "/input/thumbstick/dpad_up", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL); + openxr_metadata->register_io_path(profile_path, "Thumbstick Dpad Down", user_path, user_path + "/input/thumbstick/dpad_down", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL); + openxr_metadata->register_io_path(profile_path, "Thumbstick Dpad Left", user_path, user_path + "/input/thumbstick/dpad_left", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL); + openxr_metadata->register_io_path(profile_path, "Thumbstick Dpad Right", user_path, user_path + "/input/thumbstick/dpad_right", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL); + + openxr_metadata->register_io_path(profile_path, "Thumbrest touch", user_path, user_path + "/input/thumbrest/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + + openxr_metadata->register_io_path(profile_path, "Haptic output", user_path, user_path + "/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + } + + openxr_metadata->register_io_path(profile_path, "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + openxr_metadata->register_io_path(profile_path, "System click", "/user/hand/right", "/user/hand/right/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + openxr_metadata->register_io_path(profile_path, "X click", "/user/hand/left", "/user/hand/left/input/x/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + openxr_metadata->register_io_path(profile_path, "X touch", "/user/hand/left", "/user/hand/left/input/x/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + openxr_metadata->register_io_path(profile_path, "Y click", "/user/hand/left", "/user/hand/left/input/y/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + openxr_metadata->register_io_path(profile_path, "Y touch", "/user/hand/left", "/user/hand/left/input/y/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + openxr_metadata->register_io_path(profile_path, "A click", "/user/hand/right", "/user/hand/right/input/a/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + openxr_metadata->register_io_path(profile_path, "A touch", "/user/hand/right", "/user/hand/right/input/a/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + openxr_metadata->register_io_path(profile_path, "B click", "/user/hand/right", "/user/hand/right/input/b/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + openxr_metadata->register_io_path(profile_path, "B touch", "/user/hand/right", "/user/hand/right/input/b/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + } + } } diff --git a/modules/openxr/extensions/openxr_meta_controller_extension.h b/modules/openxr/extensions/openxr_meta_controller_extension.h index fbcdcdd5951..415f2c0b8b7 100644 --- a/modules/openxr/extensions/openxr_meta_controller_extension.h +++ b/modules/openxr/extensions/openxr_meta_controller_extension.h @@ -46,7 +46,7 @@ public: META_MAX_CONTROLLERS }; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; bool is_available(MetaControllers p_type); diff --git a/modules/openxr/extensions/openxr_ml2_controller_extension.cpp b/modules/openxr/extensions/openxr_ml2_controller_extension.cpp index cdf17deec9f..049320e614f 100644 --- a/modules/openxr/extensions/openxr_ml2_controller_extension.cpp +++ b/modules/openxr/extensions/openxr_ml2_controller_extension.cpp @@ -31,11 +31,15 @@ #include "openxr_ml2_controller_extension.h" #include "../action_map/openxr_interaction_profile_metadata.h" +#include "../openxr_api.h" -HashMap OpenXRML2ControllerExtension::get_requested_extensions() { +HashMap OpenXRML2ControllerExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; - request_extensions[XR_ML_ML2_CONTROLLER_INTERACTION_EXTENSION_NAME] = &available; + if (p_version < XR_API_VERSION_1_1_0) { + // Extension was promoted in OpenXR 1.1, only include it in OpenXR 1.0. + request_extensions[XR_ML_ML2_CONTROLLER_INTERACTION_EXTENSION_NAME] = &available; + } return request_extensions; } @@ -50,7 +54,7 @@ void OpenXRML2ControllerExtension::on_register_metadata() { // Magic Leap 2 Controller const String profile_path = "/interaction_profiles/ml/ml2_controller"; - openxr_metadata->register_interaction_profile("Magic Leap 2 controller", profile_path, XR_ML_ML2_CONTROLLER_INTERACTION_EXTENSION_NAME); + openxr_metadata->register_interaction_profile("Magic Leap 2 controller", profile_path, XR_ML_ML2_CONTROLLER_INTERACTION_EXTENSION_NAME "," XR_OPENXR_1_1_NAME); for (const String user_path : { "/user/hand/left", "/user/hand/right" }) { openxr_metadata->register_io_path(profile_path, "Grip pose", user_path, user_path + "/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Aim pose", user_path, user_path + "/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); diff --git a/modules/openxr/extensions/openxr_ml2_controller_extension.h b/modules/openxr/extensions/openxr_ml2_controller_extension.h index 91801d2326c..0e7401f9144 100644 --- a/modules/openxr/extensions/openxr_ml2_controller_extension.h +++ b/modules/openxr/extensions/openxr_ml2_controller_extension.h @@ -39,7 +39,7 @@ protected: static void _bind_methods() {} public: - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; bool is_available(); diff --git a/modules/openxr/extensions/openxr_mxink_extension.cpp b/modules/openxr/extensions/openxr_mxink_extension.cpp index e0585060a0a..cb4ad10e349 100644 --- a/modules/openxr/extensions/openxr_mxink_extension.cpp +++ b/modules/openxr/extensions/openxr_mxink_extension.cpp @@ -35,7 +35,7 @@ // Not in base XR libs needs def #define XR_LOGITECH_MX_INK_STYLUS_INTERACTION_EXTENSION_NAME "XR_LOGITECH_mx_ink_stylus_interaction" -HashMap OpenXRMxInkExtension::get_requested_extensions() { +HashMap OpenXRMxInkExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; request_extensions[XR_LOGITECH_MX_INK_STYLUS_INTERACTION_EXTENSION_NAME] = &available; diff --git a/modules/openxr/extensions/openxr_mxink_extension.h b/modules/openxr/extensions/openxr_mxink_extension.h index 5203702be23..2bef1852dad 100644 --- a/modules/openxr/extensions/openxr_mxink_extension.h +++ b/modules/openxr/extensions/openxr_mxink_extension.h @@ -39,7 +39,7 @@ protected: static void _bind_methods() {} public: - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; bool is_available(); diff --git a/modules/openxr/extensions/openxr_palm_pose_extension.cpp b/modules/openxr/extensions/openxr_palm_pose_extension.cpp index 7f8e771fcd0..ab87caf689c 100644 --- a/modules/openxr/extensions/openxr_palm_pose_extension.cpp +++ b/modules/openxr/extensions/openxr_palm_pose_extension.cpp @@ -30,6 +30,8 @@ #include "openxr_palm_pose_extension.h" +#include "../openxr_api.h" + OpenXRPalmPoseExtension *OpenXRPalmPoseExtension::singleton = nullptr; OpenXRPalmPoseExtension *OpenXRPalmPoseExtension::get_singleton() { @@ -44,10 +46,13 @@ OpenXRPalmPoseExtension::~OpenXRPalmPoseExtension() { singleton = nullptr; } -HashMap OpenXRPalmPoseExtension::get_requested_extensions() { +HashMap OpenXRPalmPoseExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; - request_extensions[XR_EXT_PALM_POSE_EXTENSION_NAME] = &available; + if (p_version < XR_API_VERSION_1_1_0) { + // Extension was promoted in OpenXR 1.1, only include it in OpenXR 1.0. + request_extensions[XR_EXT_PALM_POSE_EXTENSION_NAME] = &available; + } return request_extensions; } diff --git a/modules/openxr/extensions/openxr_palm_pose_extension.h b/modules/openxr/extensions/openxr_palm_pose_extension.h index c94642d6e32..43d5ab94138 100644 --- a/modules/openxr/extensions/openxr_palm_pose_extension.h +++ b/modules/openxr/extensions/openxr_palm_pose_extension.h @@ -44,7 +44,7 @@ public: OpenXRPalmPoseExtension(); virtual ~OpenXRPalmPoseExtension() override; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; bool is_available(); diff --git a/modules/openxr/extensions/openxr_performance_settings_extension.cpp b/modules/openxr/extensions/openxr_performance_settings_extension.cpp index deb9a285109..b2d2a0a6b72 100644 --- a/modules/openxr/extensions/openxr_performance_settings_extension.cpp +++ b/modules/openxr/extensions/openxr_performance_settings_extension.cpp @@ -46,7 +46,7 @@ OpenXRPerformanceSettingsExtension::~OpenXRPerformanceSettingsExtension() { singleton = nullptr; } -HashMap OpenXRPerformanceSettingsExtension::get_requested_extensions() { +HashMap OpenXRPerformanceSettingsExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; request_extensions[XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME] = &available; diff --git a/modules/openxr/extensions/openxr_performance_settings_extension.h b/modules/openxr/extensions/openxr_performance_settings_extension.h index 35b3984db9a..6107bd4ad5f 100644 --- a/modules/openxr/extensions/openxr_performance_settings_extension.h +++ b/modules/openxr/extensions/openxr_performance_settings_extension.h @@ -41,7 +41,7 @@ public: OpenXRPerformanceSettingsExtension(); virtual ~OpenXRPerformanceSettingsExtension() override; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; virtual void on_instance_created(const XrInstance p_instance) override; virtual bool on_event_polled(const XrEventDataBuffer &event) override; diff --git a/modules/openxr/extensions/openxr_pico_controller_extension.cpp b/modules/openxr/extensions/openxr_pico_controller_extension.cpp index 41f06190322..f2766a7652c 100644 --- a/modules/openxr/extensions/openxr_pico_controller_extension.cpp +++ b/modules/openxr/extensions/openxr_pico_controller_extension.cpp @@ -31,15 +31,20 @@ #include "openxr_pico_controller_extension.h" #include "../action_map/openxr_interaction_profile_metadata.h" +#include "../openxr_api.h" -HashMap OpenXRPicoControllerExtension::get_requested_extensions() { +HashMap OpenXRPicoControllerExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; // Note, this used to be XR_PICO_controller_interaction but that has since been retired // and was never part of the OpenXX specification. // All PICO devices should be updated to an OS supporting the official extension. - request_extensions[XR_BD_CONTROLLER_INTERACTION_EXTENSION_NAME] = &available; + if (true || p_version < XR_API_VERSION_1_1_0) { + // Extension was promoted in OpenXR 1.1, only include it in OpenXR 1.0. + // Note, we still need it for pico4_interaction, hence the temporary `if (true || ...` + request_extensions[XR_BD_CONTROLLER_INTERACTION_EXTENSION_NAME] = &available; + } return request_extensions; } @@ -57,11 +62,11 @@ void OpenXRPicoControllerExtension::on_register_metadata() { { // Pico neo 3 controller. const String profile_path = "/interaction_profiles/bytedance/pico_neo3_controller"; - openxr_metadata->register_interaction_profile("Pico Neo3 controller", profile_path, XR_BD_CONTROLLER_INTERACTION_EXTENSION_NAME); + openxr_metadata->register_interaction_profile("Pico Neo3 controller", profile_path, XR_BD_CONTROLLER_INTERACTION_EXTENSION_NAME "," XR_OPENXR_1_1_NAME); for (const String user_path : { "/user/hand/left", "/user/hand/right" }) { openxr_metadata->register_io_path(profile_path, "Grip pose", user_path, user_path + "/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Aim pose", user_path, user_path + "/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); - openxr_metadata->register_io_path(profile_path, "Palm pose", user_path, user_path + "/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + openxr_metadata->register_io_path(profile_path, "Grip surface pose", user_path, user_path + "/input/grip_surface/pose", XR_EXT_PALM_POSE_EXTENSION_NAME "," XR_KHR_MAINTENANCE1_EXTENSION_NAME "," XR_OPENXR_1_1_NAME, OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Menu click", user_path, user_path + "/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); openxr_metadata->register_io_path(profile_path, "System click", user_path, user_path + "/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL); @@ -94,11 +99,11 @@ void OpenXRPicoControllerExtension::on_register_metadata() { { // Pico 4 controller. const String profile_path = "/interaction_profiles/bytedance/pico4_controller"; - openxr_metadata->register_interaction_profile("Pico 4 controller", profile_path, XR_BD_CONTROLLER_INTERACTION_EXTENSION_NAME); + openxr_metadata->register_interaction_profile("Pico 4 controller", profile_path, XR_BD_CONTROLLER_INTERACTION_EXTENSION_NAME "," XR_OPENXR_1_1_NAME); for (const String user_path : { "/user/hand/left", "/user/hand/right" }) { openxr_metadata->register_io_path(profile_path, "Grip pose", user_path, user_path + "/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Aim pose", user_path, user_path + "/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); - openxr_metadata->register_io_path(profile_path, "Palm pose", user_path, user_path + "/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + openxr_metadata->register_io_path(profile_path, "Grip surface pose", user_path, user_path + "/input/grip_surface/pose", XR_EXT_PALM_POSE_EXTENSION_NAME "," XR_KHR_MAINTENANCE1_EXTENSION_NAME "," XR_OPENXR_1_1_NAME, OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "System click", user_path, user_path + "/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL); @@ -131,13 +136,13 @@ void OpenXRPicoControllerExtension::on_register_metadata() { openxr_metadata->register_io_path(profile_path, "B touch", "/user/hand/right", "/user/hand/right/input/b/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); } - { // Pico 4 Ultra controller. + { // Pico 4 Ultra controller, note: not provided by OpenXR 1.1 const String profile_path = "/interaction_profiles/bytedance/pico4s_controller"; openxr_metadata->register_interaction_profile("Pico 4 Ultra controller", profile_path, XR_BD_CONTROLLER_INTERACTION_EXTENSION_NAME); for (const String user_path : { "/user/hand/left", "/user/hand/right" }) { openxr_metadata->register_io_path(profile_path, "Grip pose", user_path, user_path + "/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Aim pose", user_path, user_path + "/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); - openxr_metadata->register_io_path(profile_path, "Palm pose", user_path, user_path + "/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + openxr_metadata->register_io_path(profile_path, "Grip surface pose", user_path, user_path + "/input/grip_surface/pose", XR_EXT_PALM_POSE_EXTENSION_NAME "," XR_KHR_MAINTENANCE1_EXTENSION_NAME "," XR_OPENXR_1_1_NAME, OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "System click", user_path, user_path + "/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL); diff --git a/modules/openxr/extensions/openxr_pico_controller_extension.h b/modules/openxr/extensions/openxr_pico_controller_extension.h index 23271ef9b2d..fea2ca91221 100644 --- a/modules/openxr/extensions/openxr_pico_controller_extension.h +++ b/modules/openxr/extensions/openxr_pico_controller_extension.h @@ -39,7 +39,7 @@ protected: static void _bind_methods() {} public: - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; bool is_available(); diff --git a/modules/openxr/extensions/openxr_render_model_extension.cpp b/modules/openxr/extensions/openxr_render_model_extension.cpp index 63176da8a52..72a87145342 100644 --- a/modules/openxr/extensions/openxr_render_model_extension.cpp +++ b/modules/openxr/extensions/openxr_render_model_extension.cpp @@ -71,11 +71,14 @@ OpenXRRenderModelExtension::~OpenXRRenderModelExtension() { singleton = nullptr; } -HashMap OpenXRRenderModelExtension::get_requested_extensions() { +HashMap OpenXRRenderModelExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; if (GLOBAL_GET("xr/openxr/extensions/render_model")) { - request_extensions[XR_EXT_UUID_EXTENSION_NAME] = &uuid_ext; + if (p_version < XR_API_VERSION_1_1_0) { + // Extension was promoted in OpenXR 1.1, only include it in OpenXR 1.0. + request_extensions[XR_EXT_UUID_EXTENSION_NAME] = &uuid_ext; + } request_extensions[XR_EXT_RENDER_MODEL_EXTENSION_NAME] = &render_model_ext; request_extensions[XR_EXT_INTERACTION_RENDER_MODEL_EXTENSION_NAME] = &interaction_render_model_ext; } diff --git a/modules/openxr/extensions/openxr_render_model_extension.h b/modules/openxr/extensions/openxr_render_model_extension.h index d5bc446847a..a9d54460585 100644 --- a/modules/openxr/extensions/openxr_render_model_extension.h +++ b/modules/openxr/extensions/openxr_render_model_extension.h @@ -74,7 +74,7 @@ public: OpenXRRenderModelExtension(); virtual ~OpenXRRenderModelExtension() override; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; virtual void on_instance_created(const XrInstance p_instance) override; virtual void on_session_created(const XrSession p_session) override; diff --git a/modules/openxr/extensions/openxr_valve_analog_threshold_extension.cpp b/modules/openxr/extensions/openxr_valve_analog_threshold_extension.cpp index 58f9df35e5d..39c9506f246 100644 --- a/modules/openxr/extensions/openxr_valve_analog_threshold_extension.cpp +++ b/modules/openxr/extensions/openxr_valve_analog_threshold_extension.cpp @@ -53,7 +53,7 @@ OpenXRValveAnalogThresholdExtension::~OpenXRValveAnalogThresholdExtension() { singleton = nullptr; } -HashMap OpenXRValveAnalogThresholdExtension::get_requested_extensions() { +HashMap OpenXRValveAnalogThresholdExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; // Note, we're dependent on the binding modifier extension, this may be requested by multiple extension wrappers. diff --git a/modules/openxr/extensions/openxr_valve_analog_threshold_extension.h b/modules/openxr/extensions/openxr_valve_analog_threshold_extension.h index f2b97dd3e19..3d614a065fc 100644 --- a/modules/openxr/extensions/openxr_valve_analog_threshold_extension.h +++ b/modules/openxr/extensions/openxr_valve_analog_threshold_extension.h @@ -48,7 +48,7 @@ public: OpenXRValveAnalogThresholdExtension(); virtual ~OpenXRValveAnalogThresholdExtension() override; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; bool is_available(); diff --git a/modules/openxr/extensions/openxr_visibility_mask_extension.cpp b/modules/openxr/extensions/openxr_visibility_mask_extension.cpp index 145d03cbe56..08ae0ac3cfa 100644 --- a/modules/openxr/extensions/openxr_visibility_mask_extension.cpp +++ b/modules/openxr/extensions/openxr_visibility_mask_extension.cpp @@ -69,7 +69,7 @@ OpenXRVisibilityMaskExtension::~OpenXRVisibilityMaskExtension() { singleton = nullptr; } -HashMap OpenXRVisibilityMaskExtension::get_requested_extensions() { +HashMap OpenXRVisibilityMaskExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; request_extensions[XR_KHR_VISIBILITY_MASK_EXTENSION_NAME] = &available; diff --git a/modules/openxr/extensions/openxr_visibility_mask_extension.h b/modules/openxr/extensions/openxr_visibility_mask_extension.h index bb5c1b71c99..e07bcbd04ec 100644 --- a/modules/openxr/extensions/openxr_visibility_mask_extension.h +++ b/modules/openxr/extensions/openxr_visibility_mask_extension.h @@ -58,7 +58,7 @@ public: OpenXRVisibilityMaskExtension(); virtual ~OpenXRVisibilityMaskExtension() override; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; virtual void on_instance_created(const XrInstance p_instance) override; diff --git a/modules/openxr/extensions/openxr_wmr_controller_extension.cpp b/modules/openxr/extensions/openxr_wmr_controller_extension.cpp index bac215bb117..df894607c1e 100644 --- a/modules/openxr/extensions/openxr_wmr_controller_extension.cpp +++ b/modules/openxr/extensions/openxr_wmr_controller_extension.cpp @@ -31,13 +31,17 @@ #include "openxr_wmr_controller_extension.h" #include "../action_map/openxr_interaction_profile_metadata.h" +#include "../openxr_api.h" -HashMap OpenXRWMRControllerExtension::get_requested_extensions() { +HashMap OpenXRWMRControllerExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; // Note HP G2 is available on WMR and SteamVR, but Odessey is only available on WMR - request_extensions[XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME] = &available[WMR_HPMR]; - request_extensions[XR_EXT_SAMSUNG_ODYSSEY_CONTROLLER_EXTENSION_NAME] = &available[WMR_SAMSUNG_ODESSY]; + if (p_version < XR_API_VERSION_1_1_0) { + // Extensions where promoted in OpenXR 1.1, only include it in OpenXR 1.0. + request_extensions[XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME] = &available[WMR_HPMR]; + request_extensions[XR_EXT_SAMSUNG_ODYSSEY_CONTROLLER_EXTENSION_NAME] = &available[WMR_SAMSUNG_ODESSY]; + } request_extensions[XR_MSFT_HAND_INTERACTION_EXTENSION_NAME] = &available[WMR_HAND_INTERACTION]; return request_extensions; @@ -53,11 +57,11 @@ void OpenXRWMRControllerExtension::on_register_metadata() { { // HP MR controller (newer G2 controllers) const String profile_path = "/interaction_profiles/hp/mixed_reality_controller"; - openxr_metadata->register_interaction_profile("HPMR controller", profile_path, XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME); + openxr_metadata->register_interaction_profile("HPMR controller", profile_path, XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME "," XR_OPENXR_1_1_NAME); for (const String user_path : { "/user/hand/left", "/user/hand/right" }) { openxr_metadata->register_io_path(profile_path, "Grip pose", user_path, user_path + "/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Aim pose", user_path, user_path + "/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); - openxr_metadata->register_io_path(profile_path, "Palm pose", user_path, user_path + "/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + openxr_metadata->register_io_path(profile_path, "Grip surface pose", user_path, user_path + "/input/grip_surface/pose", XR_EXT_PALM_POSE_EXTENSION_NAME "," XR_KHR_MAINTENANCE1_EXTENSION_NAME "," XR_OPENXR_1_1_NAME, OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Menu click", user_path, user_path + "/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); @@ -84,11 +88,11 @@ void OpenXRWMRControllerExtension::on_register_metadata() { { // Samsung Odyssey controller const String profile_path = "/interaction_profiles/samsung/odyssey_controller"; - openxr_metadata->register_interaction_profile("Samsung Odyssey controller", profile_path, XR_EXT_SAMSUNG_ODYSSEY_CONTROLLER_EXTENSION_NAME); + openxr_metadata->register_interaction_profile("Samsung Odyssey controller", profile_path, XR_EXT_SAMSUNG_ODYSSEY_CONTROLLER_EXTENSION_NAME "," XR_OPENXR_1_1_NAME); for (const String user_path : { "/user/hand/left", "/user/hand/right" }) { openxr_metadata->register_io_path(profile_path, "Grip pose", user_path, user_path + "/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Aim pose", user_path, user_path + "/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); - openxr_metadata->register_io_path(profile_path, "Palm pose", user_path, user_path + "/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + openxr_metadata->register_io_path(profile_path, "Grip surface pose", user_path, user_path + "/input/grip_surface/pose", XR_EXT_PALM_POSE_EXTENSION_NAME "," XR_KHR_MAINTENANCE1_EXTENSION_NAME "," XR_OPENXR_1_1_NAME, OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Menu click", user_path, user_path + "/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); @@ -125,7 +129,7 @@ void OpenXRWMRControllerExtension::on_register_metadata() { openxr_metadata->register_io_path(profile_path, "Aim pose", user_path, user_path + "/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Pinch pose", user_path, user_path + "/input/pinch_ext/pose", XR_EXT_HAND_INTERACTION_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Poke pose", user_path, user_path + "/input/poke_ext/pose", XR_EXT_HAND_INTERACTION_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); - openxr_metadata->register_io_path(profile_path, "Palm pose", user_path, user_path + "/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + openxr_metadata->register_io_path(profile_path, "Grip surface pose", user_path, user_path + "/input/grip_surface/pose", XR_EXT_PALM_POSE_EXTENSION_NAME "," XR_KHR_MAINTENANCE1_EXTENSION_NAME "," XR_OPENXR_1_1_NAME, OpenXRAction::OPENXR_ACTION_POSE); openxr_metadata->register_io_path(profile_path, "Select (pinch)", user_path, user_path + "/input/select/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); diff --git a/modules/openxr/extensions/openxr_wmr_controller_extension.h b/modules/openxr/extensions/openxr_wmr_controller_extension.h index 899a75fe153..d80532f0d0f 100644 --- a/modules/openxr/extensions/openxr_wmr_controller_extension.h +++ b/modules/openxr/extensions/openxr_wmr_controller_extension.h @@ -46,7 +46,7 @@ public: WMR_MAX_CONTROLLERS }; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; bool is_available(WMRControllers p_type); diff --git a/modules/openxr/extensions/platform/openxr_android_extension.cpp b/modules/openxr/extensions/platform/openxr_android_extension.cpp index dfefe655108..8c5e03416f8 100644 --- a/modules/openxr/extensions/platform/openxr_android_extension.cpp +++ b/modules/openxr/extensions/platform/openxr_android_extension.cpp @@ -55,7 +55,7 @@ OpenXRAndroidExtension::OpenXRAndroidExtension() { activity_object = env->NewGlobalRef(static_cast(OS::get_singleton())->get_godot_java()->get_activity()); } -HashMap OpenXRAndroidExtension::get_requested_extensions() { +HashMap OpenXRAndroidExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; // XR_KHR_LOADER_INIT_EXTENSION_NAME is a dependency of XR_KHR_LOADER_INIT_ANDROID_EXTENSION_NAME @@ -87,7 +87,7 @@ void OpenXRAndroidExtension::on_before_instance_created() { // This is reasonably safe as the struct is only used during initialization and the extension is a singleton. static XrInstanceCreateInfoAndroidKHR instance_create_info; -void *OpenXRAndroidExtension::set_instance_create_info_and_get_next_pointer(void *p_next_pointer) { +void *OpenXRAndroidExtension::set_instance_create_info_and_get_next_pointer(XrVersion p_xr_version, void *p_next_pointer) { if (!create_instance_extension_available) { if (!loader_init_android_extension_available) { WARN_PRINT("No Android extensions available, couldn't pass JVM and Activity to OpenXR"); diff --git a/modules/openxr/extensions/platform/openxr_android_extension.h b/modules/openxr/extensions/platform/openxr_android_extension.h index f599ba5df97..6a531597937 100644 --- a/modules/openxr/extensions/platform/openxr_android_extension.h +++ b/modules/openxr/extensions/platform/openxr_android_extension.h @@ -41,9 +41,9 @@ public: OpenXRAndroidExtension(); - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; virtual void on_before_instance_created() override; - virtual void *set_instance_create_info_and_get_next_pointer(void *p_next_pointer) override; + virtual void *set_instance_create_info_and_get_next_pointer(XrVersion p_xr_version, void *p_next_pointer) override; virtual ~OpenXRAndroidExtension() override; diff --git a/modules/openxr/extensions/platform/openxr_d3d12_extension.cpp b/modules/openxr/extensions/platform/openxr_d3d12_extension.cpp index 7e5e45d0cb6..f982b3fb24d 100644 --- a/modules/openxr/extensions/platform/openxr_d3d12_extension.cpp +++ b/modules/openxr/extensions/platform/openxr_d3d12_extension.cpp @@ -37,7 +37,7 @@ #include "servers/rendering/rendering_server.h" #include "servers/rendering/rendering_server_globals.h" -HashMap OpenXRD3D12Extension::get_requested_extensions() { +HashMap OpenXRD3D12Extension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; request_extensions[XR_KHR_D3D12_ENABLE_EXTENSION_NAME] = nullptr; diff --git a/modules/openxr/extensions/platform/openxr_d3d12_extension.h b/modules/openxr/extensions/platform/openxr_d3d12_extension.h index 7fef6e4862b..c9f95966ab9 100644 --- a/modules/openxr/extensions/platform/openxr_d3d12_extension.h +++ b/modules/openxr/extensions/platform/openxr_d3d12_extension.h @@ -44,7 +44,7 @@ class OpenXRD3D12Extension : public OpenXRGraphicsExtensionWrapper, D3D12Hooks { public: - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; virtual void on_instance_created(const XrInstance p_instance) override; virtual void *set_session_create_and_get_next_pointer(void *p_next_pointer) override; diff --git a/modules/openxr/extensions/platform/openxr_metal_extension.h b/modules/openxr/extensions/platform/openxr_metal_extension.h index 8654a2be776..c71be519a8b 100644 --- a/modules/openxr/extensions/platform/openxr_metal_extension.h +++ b/modules/openxr/extensions/platform/openxr_metal_extension.h @@ -41,7 +41,7 @@ class OpenXRMetalExtension : public OpenXRGraphicsExtensionWrapper { public: - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; virtual void on_instance_created(const XrInstance p_instance) override; virtual void *set_session_create_and_get_next_pointer(void *p_next_pointer) override; diff --git a/modules/openxr/extensions/platform/openxr_metal_extension.mm b/modules/openxr/extensions/platform/openxr_metal_extension.mm index 0d12824cbf8..58921e2a3f5 100644 --- a/modules/openxr/extensions/platform/openxr_metal_extension.mm +++ b/modules/openxr/extensions/platform/openxr_metal_extension.mm @@ -35,7 +35,7 @@ #import "drivers/metal/rendering_device_driver_metal.h" #include "servers/rendering/rendering_server_globals.h" -HashMap OpenXRMetalExtension::get_requested_extensions() { +HashMap OpenXRMetalExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; request_extensions[XR_KHR_METAL_ENABLE_EXTENSION_NAME] = nullptr; diff --git a/modules/openxr/extensions/platform/openxr_opengl_extension.cpp b/modules/openxr/extensions/platform/openxr_opengl_extension.cpp index d20817c407d..4bcc1103410 100644 --- a/modules/openxr/extensions/platform/openxr_opengl_extension.cpp +++ b/modules/openxr/extensions/platform/openxr_opengl_extension.cpp @@ -56,7 +56,7 @@ // feature off. // See: https://registry.khronos.org/OpenGL/extensions/EXT/EXT_sRGB_write_control.txt -HashMap OpenXROpenGLExtension::get_requested_extensions() { +HashMap OpenXROpenGLExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; #ifdef ANDROID_ENABLED diff --git a/modules/openxr/extensions/platform/openxr_opengl_extension.h b/modules/openxr/extensions/platform/openxr_opengl_extension.h index 8c6a29b8238..25261f80639 100644 --- a/modules/openxr/extensions/platform/openxr_opengl_extension.h +++ b/modules/openxr/extensions/platform/openxr_opengl_extension.h @@ -43,7 +43,7 @@ class OpenXROpenGLExtension : public OpenXRGraphicsExtensionWrapper { public: - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; virtual void on_instance_created(const XrInstance p_instance) override; virtual void *set_session_create_and_get_next_pointer(void *p_next_pointer) override; diff --git a/modules/openxr/extensions/platform/openxr_vulkan_extension.cpp b/modules/openxr/extensions/platform/openxr_vulkan_extension.cpp index 8d752a0c7d9..9218f7054c7 100644 --- a/modules/openxr/extensions/platform/openxr_vulkan_extension.cpp +++ b/modules/openxr/extensions/platform/openxr_vulkan_extension.cpp @@ -39,7 +39,7 @@ #include "servers/rendering/rendering_server.h" #include "servers/rendering/rendering_server_globals.h" -HashMap OpenXRVulkanExtension::get_requested_extensions() { +HashMap OpenXRVulkanExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; request_extensions[XR_KHR_VULKAN_ENABLE2_EXTENSION_NAME] = nullptr; // must be available diff --git a/modules/openxr/extensions/platform/openxr_vulkan_extension.h b/modules/openxr/extensions/platform/openxr_vulkan_extension.h index 1a1729206f9..aac85b48f53 100644 --- a/modules/openxr/extensions/platform/openxr_vulkan_extension.h +++ b/modules/openxr/extensions/platform/openxr_vulkan_extension.h @@ -45,7 +45,7 @@ public: OpenXRVulkanExtension() = default; virtual ~OpenXRVulkanExtension() override = default; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; virtual void on_instance_created(const XrInstance p_instance) override; virtual void *set_session_create_and_get_next_pointer(void *p_next_pointer) override; diff --git a/modules/openxr/extensions/spatial_entities/openxr_spatial_anchor.cpp b/modules/openxr/extensions/spatial_entities/openxr_spatial_anchor.cpp index 2348ebbf154..ff28662df9e 100644 --- a/modules/openxr/extensions/spatial_entities/openxr_spatial_anchor.cpp +++ b/modules/openxr/extensions/spatial_entities/openxr_spatial_anchor.cpp @@ -332,7 +332,7 @@ void OpenXRSpatialAnchorCapability::_bind_methods() { BIND_ENUM_CONSTANT(PERSISTENCE_SCOPE_LOCAL_ANCHORS); } -HashMap OpenXRSpatialAnchorCapability::get_requested_extensions() { +HashMap OpenXRSpatialAnchorCapability::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; if (GLOBAL_GET_CACHED(bool, "xr/openxr/extensions/spatial_entity/enabled") && GLOBAL_GET_CACHED(bool, "xr/openxr/extensions/spatial_entity/enable_spatial_anchors")) { diff --git a/modules/openxr/extensions/spatial_entities/openxr_spatial_anchor.h b/modules/openxr/extensions/spatial_entities/openxr_spatial_anchor.h index a3e8d762167..6b2c0d5f7cc 100644 --- a/modules/openxr/extensions/spatial_entities/openxr_spatial_anchor.h +++ b/modules/openxr/extensions/spatial_entities/openxr_spatial_anchor.h @@ -158,7 +158,7 @@ public: OpenXRSpatialAnchorCapability(); virtual ~OpenXRSpatialAnchorCapability() override; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; virtual void on_instance_created(const XrInstance p_instance) override; virtual void on_instance_destroyed() override; diff --git a/modules/openxr/extensions/spatial_entities/openxr_spatial_entity_extension.cpp b/modules/openxr/extensions/spatial_entities/openxr_spatial_entity_extension.cpp index 6cc60042332..e77d2a75552 100644 --- a/modules/openxr/extensions/spatial_entities/openxr_spatial_entity_extension.cpp +++ b/modules/openxr/extensions/spatial_entities/openxr_spatial_entity_extension.cpp @@ -106,7 +106,7 @@ OpenXRSpatialEntityExtension::~OpenXRSpatialEntityExtension() { singleton = nullptr; } -HashMap OpenXRSpatialEntityExtension::get_requested_extensions() { +HashMap OpenXRSpatialEntityExtension::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; if (GLOBAL_GET_CACHED(bool, "xr/openxr/extensions/spatial_entity/enabled")) { diff --git a/modules/openxr/extensions/spatial_entities/openxr_spatial_entity_extension.h b/modules/openxr/extensions/spatial_entities/openxr_spatial_entity_extension.h index 3c1babd38c9..f5811b63897 100644 --- a/modules/openxr/extensions/spatial_entities/openxr_spatial_entity_extension.h +++ b/modules/openxr/extensions/spatial_entities/openxr_spatial_entity_extension.h @@ -69,7 +69,7 @@ public: OpenXRSpatialEntityExtension(); virtual ~OpenXRSpatialEntityExtension() override; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; virtual void on_instance_created(const XrInstance p_instance) override; virtual void on_instance_destroyed() override; diff --git a/modules/openxr/extensions/spatial_entities/openxr_spatial_marker_tracking.cpp b/modules/openxr/extensions/spatial_entities/openxr_spatial_marker_tracking.cpp index 1d9e832c4dc..b387ba9453b 100644 --- a/modules/openxr/extensions/spatial_entities/openxr_spatial_marker_tracking.cpp +++ b/modules/openxr/extensions/spatial_entities/openxr_spatial_marker_tracking.cpp @@ -444,7 +444,7 @@ void OpenXRSpatialMarkerTrackingCapability::_bind_methods() { ClassDB::bind_method(D_METHOD("is_april_tag_supported"), &OpenXRSpatialMarkerTrackingCapability::is_april_tag_supported); } -HashMap OpenXRSpatialMarkerTrackingCapability::get_requested_extensions() { +HashMap OpenXRSpatialMarkerTrackingCapability::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; if (GLOBAL_GET_CACHED(bool, "xr/openxr/extensions/spatial_entity/enabled") && GLOBAL_GET_CACHED(bool, "xr/openxr/extensions/spatial_entity/enable_marker_tracking")) { diff --git a/modules/openxr/extensions/spatial_entities/openxr_spatial_marker_tracking.h b/modules/openxr/extensions/spatial_entities/openxr_spatial_marker_tracking.h index 05e11913221..b9e0d616979 100644 --- a/modules/openxr/extensions/spatial_entities/openxr_spatial_marker_tracking.h +++ b/modules/openxr/extensions/spatial_entities/openxr_spatial_marker_tracking.h @@ -228,7 +228,7 @@ public: OpenXRSpatialMarkerTrackingCapability(); virtual ~OpenXRSpatialMarkerTrackingCapability() override; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; virtual void on_session_created(const XrSession p_session) override; virtual void on_session_destroyed() override; diff --git a/modules/openxr/extensions/spatial_entities/openxr_spatial_plane_tracking.cpp b/modules/openxr/extensions/spatial_entities/openxr_spatial_plane_tracking.cpp index 504905e69ee..e22e613ac16 100644 --- a/modules/openxr/extensions/spatial_entities/openxr_spatial_plane_tracking.cpp +++ b/modules/openxr/extensions/spatial_entities/openxr_spatial_plane_tracking.cpp @@ -583,7 +583,7 @@ void OpenXRSpatialPlaneTrackingCapability::_bind_methods() { ClassDB::bind_method(D_METHOD("is_supported"), &OpenXRSpatialPlaneTrackingCapability::is_supported); } -HashMap OpenXRSpatialPlaneTrackingCapability::get_requested_extensions() { +HashMap OpenXRSpatialPlaneTrackingCapability::get_requested_extensions(XrVersion p_version) { HashMap request_extensions; if (GLOBAL_GET_CACHED(bool, "xr/openxr/extensions/spatial_entity/enabled") && GLOBAL_GET_CACHED(bool, "xr/openxr/extensions/spatial_entity/enable_plane_tracking")) { diff --git a/modules/openxr/extensions/spatial_entities/openxr_spatial_plane_tracking.h b/modules/openxr/extensions/spatial_entities/openxr_spatial_plane_tracking.h index b2bf3244bcb..7100f9205ec 100644 --- a/modules/openxr/extensions/spatial_entities/openxr_spatial_plane_tracking.h +++ b/modules/openxr/extensions/spatial_entities/openxr_spatial_plane_tracking.h @@ -219,7 +219,7 @@ public: OpenXRSpatialPlaneTrackingCapability(); virtual ~OpenXRSpatialPlaneTrackingCapability() override; - virtual HashMap get_requested_extensions() override; + virtual HashMap get_requested_extensions(XrVersion p_version) override; virtual void on_session_created(const XrSession p_session) override; virtual void on_session_destroyed() override; diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp index db1aeab4b71..3e36b5d5a6b 100644 --- a/modules/openxr/openxr_api.cpp +++ b/modules/openxr/openxr_api.cpp @@ -445,11 +445,14 @@ bool OpenXRAPI::is_extension_supported(const String &p_extension) const { return false; } -bool OpenXRAPI::is_extension_enabled(const String &p_extension) const { - CharString extension = p_extension.ascii(); +bool OpenXRAPI::is_any_extension_enabled(const String &p_extensions) const { + // We allow a comma separated list of extensions here, only one needs to be supported. + // This allows us to check for extensions that were renamed or that were embedded in core + // at a specific OpenXR version. + for (const String &name : p_extensions.split(",", false)) { + CharString extension = name.utf8(); - for (int i = 0; i < enabled_extensions.size(); i++) { - if (strcmp(enabled_extensions[i].ptr(), extension.ptr()) == 0) { + if (enabled_extensions.has(extension)) { return true; } } @@ -458,19 +461,19 @@ bool OpenXRAPI::is_extension_enabled(const String &p_extension) const { } bool OpenXRAPI::is_top_level_path_supported(const String &p_toplevel_path) { - String required_extension = OpenXRInteractionProfileMetadata::get_singleton()->get_top_level_extension(p_toplevel_path); + String required_extensions = OpenXRInteractionProfileMetadata::get_singleton()->get_top_level_extensions(p_toplevel_path); // If unsupported is returned we likely have a misspelled interaction profile path in our action map. Always output that as an error. - ERR_FAIL_COND_V_MSG(required_extension == XR_PATH_UNSUPPORTED_NAME, false, "OpenXR: Unsupported toplevel path " + p_toplevel_path); + ERR_FAIL_COND_V_MSG(required_extensions == XR_PATH_UNSUPPORTED_NAME, false, "OpenXR: Unsupported toplevel path " + p_toplevel_path); - if (required_extension == "") { + if (required_extensions == "") { // no extension needed, core top level are always "supported", they just won't be used if not really supported return true; } - if (!is_extension_enabled(required_extension)) { + if (!is_any_extension_enabled(required_extensions)) { // It is very likely we have top level paths for which the extension is not available so don't flood the logs with unnecessary spam. - print_verbose("OpenXR: Top level path " + p_toplevel_path + " requires extension " + required_extension); + print_verbose("OpenXR: Top level path " + p_toplevel_path + " requires extension " + required_extensions.replace(",", " or ")); return false; } @@ -478,19 +481,19 @@ bool OpenXRAPI::is_top_level_path_supported(const String &p_toplevel_path) { } bool OpenXRAPI::is_interaction_profile_supported(const String &p_ip_path) { - String required_extension = OpenXRInteractionProfileMetadata::get_singleton()->get_interaction_profile_extension(p_ip_path); + String required_extensions = OpenXRInteractionProfileMetadata::get_singleton()->get_interaction_profile_extensions(p_ip_path); // If unsupported is returned we likely have a misspelled interaction profile path in our action map. Always output that as an error. - ERR_FAIL_COND_V_MSG(required_extension == XR_PATH_UNSUPPORTED_NAME, false, "OpenXR: Unsupported interaction profile " + p_ip_path); + ERR_FAIL_COND_V_MSG(required_extensions == XR_PATH_UNSUPPORTED_NAME, false, "OpenXR: Unsupported interaction profile " + p_ip_path); - if (required_extension == "") { + if (required_extensions == "") { // no extension needed, core interaction profiles are always "supported", they just won't be used if not really supported return true; } - if (!is_extension_enabled(required_extension)) { + if (!is_any_extension_enabled(required_extensions)) { // It is very likely we have interaction profiles for which the extension is not available so don't flood the logs with unnecessary spam. - print_verbose("OpenXR: Interaction profile " + p_ip_path + " requires extension " + required_extension); + print_verbose("OpenXR: Interaction profile " + p_ip_path + " requires extension " + required_extensions.replace(",", " or ")); return false; } @@ -507,14 +510,14 @@ bool OpenXRAPI::interaction_profile_supports_io_path(const String &p_ip_path, co // If the io_path is not part of our metadata we've likely got a misspelled name or a bad action map, report ERR_FAIL_NULL_V_MSG(io_path, false, "OpenXR: Unsupported io path " + String(p_ip_path) + String(p_io_path)); - if (io_path->openxr_extension_name == "") { + if (io_path->openxr_extension_names == "") { // no extension needed, core io paths are always "supported", they just won't be used if not really supported return true; } - if (!is_extension_enabled(io_path->openxr_extension_name)) { + if (!is_any_extension_enabled(io_path->openxr_extension_names)) { // It is very likely we have io paths for which the extension is not available so don't flood the logs with unnecessary spam. - print_verbose("OpenXR: IO path " + String(p_ip_path) + String(p_io_path) + " requires extension " + io_path->openxr_extension_name); + print_verbose("OpenXR: IO path " + String(p_ip_path) + String(p_io_path) + " requires extension " + io_path->openxr_extension_names.replace(",", " or ")); return false; } @@ -534,13 +537,13 @@ void OpenXRAPI::copy_string_to_char_buffer(const String &p_string, char *p_buffe } } -PackedStringArray OpenXRAPI::get_all_requested_extensions() { +PackedStringArray OpenXRAPI::get_all_requested_extensions(XrVersion p_xr_version) { // This returns all extensions we will request regardless of whether they are available. - // This is mostly used by the editor to filter features not enabled through project settings. + // This is used by the editor to filter features not enabled through project settings. PackedStringArray requested_extensions; for (OpenXRExtensionWrapper *wrapper : registered_extension_wrappers) { - const HashMap &wrapper_request_extensions = wrapper->get_requested_extensions(); + const HashMap &wrapper_request_extensions = wrapper->get_requested_extensions(p_xr_version); for (const KeyValue &requested_extension : wrapper_request_extensions) { if (!requested_extensions.has(requested_extension.key)) { @@ -549,36 +552,30 @@ PackedStringArray OpenXRAPI::get_all_requested_extensions() { } } + // Also add in our OpenXR Version "extension", so we can switch logic on that. + requested_extensions.push_back(XR_OPENXR_1_1_NAME); + return requested_extensions; } -bool OpenXRAPI::create_instance() { - // Create our OpenXR instance, this will query any registered extension wrappers for extensions we need to enable. +XrResult OpenXRAPI::attempt_create_instance(XrVersion p_version) { + enabled_extensions.clear(); - // We can request an extension multiple times if there are dependencies - struct RequestExtension { - String name; - bool *enabled; - }; - - // Find all extensions we wish to enable. - Vector requested_extensions; + // Find all extensions we wish to enable for the requested OpenXR version. + LocalVector requested_extensions; for (OpenXRExtensionWrapper *wrapper : registered_extension_wrappers) { - const HashMap &wrapper_request_extensions = wrapper->get_requested_extensions(); + const HashMap &wrapper_request_extensions = wrapper->get_requested_extensions(p_version); for (const KeyValue &requested_extension : wrapper_request_extensions) { requested_extensions.push_back({ requested_extension.key, requested_extension.value }); } } - // Check which extensions are supported. - enabled_extensions.clear(); - - for (RequestExtension &requested_extension : requested_extensions) { + for (const RequestExtension &requested_extension : requested_extensions) { if (!is_extension_supported(requested_extension.name)) { if (requested_extension.enabled == nullptr) { // Null means this is a mandatory extension so we fail. - ERR_FAIL_V_MSG(false, String("OpenXR: OpenXR Runtime does not support ") + requested_extension.name + String(" extension!")); + ERR_FAIL_V_MSG(XR_ERROR_INITIALIZATION_FAILED, String("OpenXR: OpenXR Runtime does not support ") + requested_extension.name + String(" extension!")); } else { // Set this extension as not supported. *requested_extension.enabled = false; @@ -590,41 +587,41 @@ bool OpenXRAPI::create_instance() { } // And record that we want to enable it (dependent extensions may be requested multiple times). - CharString ext_name = requested_extension.name.ascii(); + CharString ext_name = requested_extension.name.utf8(); if (!enabled_extensions.has(ext_name)) { enabled_extensions.push_back(ext_name); } } } - Vector extension_ptrs; - for (int i = 0; i < enabled_extensions.size(); i++) { - print_verbose(String("OpenXR: Enabling extension ") + String(enabled_extensions[i].get_data())); - extension_ptrs.push_back(enabled_extensions[i].get_data()); + // Convert our enabled extensions so we can send it to OpenXR. + LocalVector extension_ptrs; + extension_ptrs.reserve(enabled_extensions.size()); + + for (const CharString &enabled_extension : enabled_extensions) { + const char *extension = enabled_extension.get_data(); + extension_ptrs.push_back(extension); } - // We explicitly set the version to 1.0.48 in order to workaround a bug (see #108850) in Meta's runtime. - // Once that is fixed, restore this to using XR_API_VERSION_1_0, which is the version associated with the - // OpenXR headers that we're using. - XrVersion openxr_version = XR_MAKE_VERSION(1, 0, 48); - - // Create our OpenXR instance + // Attempt to create our OpenXR instance for the requested version. XrApplicationInfo application_info{ "Godot Engine", // applicationName, if we're running a game we'll update this down below. 1, // applicationVersion, we don't currently have this "Godot Engine", // engineName GODOT_VERSION_MAJOR * 10000 + GODOT_VERSION_MINOR * 100 + GODOT_VERSION_PATCH, // engineVersion 4.0 -> 40000, 4.0.1 -> 40001, 4.1 -> 40100, etc. - openxr_version, // apiVersion + p_version // apiVersion }; + // Get additional entries from our extension wrappers. void *next_pointer = nullptr; for (OpenXRExtensionWrapper *wrapper : registered_extension_wrappers) { - void *np = wrapper->set_instance_create_info_and_get_next_pointer(next_pointer); + void *np = wrapper->set_instance_create_info_and_get_next_pointer(p_version, next_pointer); if (np != nullptr) { next_pointer = np; } } + // Try and create this instance. XrInstanceCreateInfo instance_create_info = { XR_TYPE_INSTANCE_CREATE_INFO, // type next_pointer, // next @@ -636,16 +633,44 @@ bool OpenXRAPI::create_instance() { extension_ptrs.ptr() // enabledExtensionNames }; - // Get our project name + // Get our project name. String project_name = GLOBAL_GET("application/config/name"); if (!project_name.is_empty()) { copy_string_to_char_buffer(project_name, instance_create_info.applicationInfo.applicationName, XR_MAX_APPLICATION_NAME_SIZE); } XrResult result = xrCreateInstance(&instance_create_info, &instance); - ERR_FAIL_COND_V_MSG(XR_FAILED(result), false, "Failed to create XR instance [" + get_error_string(result) + "]."); + if (XR_SUCCEEDED(result)) { + // Record version we've successfully enabled. + openxr_version = p_version; + print_line("OpenXR: Created instance for OpenXR", OpenXRUtil::make_xr_version_string(openxr_version)); - // from this point on we can use get_error_string to get more info about our errors... + if (is_print_verbose_enabled()) { + // Print out enabled extensions. + for (const char *extension : extension_ptrs) { + print_line("OpenXR: Enabled extension ", extension); + } + } + } + + return result; +} + +bool OpenXRAPI::create_instance() { + // Create our OpenXR instance, this will query any registered extension wrappers for extensions we need to enable. + + // We explicitly set the version to 1.x.48 in order to workaround a bug (see #108850) in Meta's runtime. + // Once that is fixed, restore this to using XR_API_VERSION_1_x, which is the version associated with the + // OpenXR headers that we're using. + + XrResult result = attempt_create_instance(XR_MAKE_VERSION(1, 1, 48)); // Replace with XR_API_VERSION_1_1 + if (result == XR_ERROR_API_VERSION_UNSUPPORTED) { + // Couldn't initialize OpenXR 1.1, try 1.0 + print_verbose("OpenXR: Falling back to OpenXR 1.0"); + + result = attempt_create_instance(XR_MAKE_VERSION(1, 0, 48)); // Replace with XR_API_VERSION_1_0 + } + ERR_FAIL_COND_V_MSG(XR_FAILED(result), false, "Failed to create XR instance [" + get_error_string(result) + "]."); XrInstanceProperties instanceProps = { XR_TYPE_INSTANCE_PROPERTIES, // type; @@ -669,6 +694,12 @@ bool OpenXRAPI::create_instance() { print_line("OpenXR: Running on OpenXR runtime: ", runtime_name, " ", runtime_version); } + // We add an extension string to indicate we're on OpenXR 1.1, + // this makes it easier to check for this in various places where we're already checking on extensions. + if (XR_VERSION_MAJOR(openxr_version) == 1 && XR_VERSION_MINOR(openxr_version) == 1) { + enabled_extensions.push_back(XR_OPENXR_1_1_NAME); + } + for (OpenXRExtensionWrapper *wrapper : registered_extension_wrappers) { wrapper->on_instance_created(instance); } @@ -979,6 +1010,8 @@ bool OpenXRAPI::setup_play_space() { } else if (is_reference_space_supported(requested_reference_space)) { new_reference_space = requested_reference_space; } else if (requested_reference_space == XR_REFERENCE_SPACE_TYPE_LOCAL_FLOOR_EXT && is_reference_space_supported(XR_REFERENCE_SPACE_TYPE_STAGE)) { + // Note, in OpenXR 1.0 XR_EXT_LOCAL_FLOOR_EXTENSION_NAME needs to be enabled + // but from OpenXR 1.1 onwards this should always be available. print_verbose("OpenXR: LOCAL_FLOOR space isn't supported, emulating using STAGE and LOCAL spaces."); new_reference_space = XR_REFERENCE_SPACE_TYPE_LOCAL; @@ -3410,7 +3443,9 @@ RID OpenXRAPI::interaction_profile_create(const String &p_name) { InteractionProfile new_interaction_profile; - XrResult result = xrStringToPath(instance, p_name.utf8().get_data(), &new_interaction_profile.path); + new_interaction_profile.internal_name = get_interaction_profile_internal_name(p_name); + + XrResult result = xrStringToPath(instance, new_interaction_profile.internal_name.get_data(), &new_interaction_profile.path); if (XR_FAILED(result)) { print_line("OpenXR: failed to get path for ", p_name, "! [", get_error_string(result), "]"); return RID(); @@ -3443,6 +3478,93 @@ void OpenXRAPI::interaction_profile_clear_bindings(RID p_interaction_profile) { ip->bindings.clear(); } +CharString OpenXRAPI::get_interaction_profile_internal_name(const String &p_interaction_profile_name) const { + CharString internal_name = p_interaction_profile_name.utf8(); + + if (openxr_version < XR_API_VERSION_1_1_0) { + // These interaction profiles were renamed in OpenXR 1.1, + // if we don't support OpenXR 1.1, rename them back. + if (internal_name == "/interaction_profiles/meta/touch_pro_controller") { + return "/interaction_profiles/facebook/touch_controller_pro"; + } else if (internal_name == "/interaction_profiles/meta/touch_plus_controller") { + return "/interaction_profiles/meta/touch_controller_plus"; + } + } + + return internal_name; +} + +const char *OpenXRAPI::check_profile_path(const CharString &p_interaction_profile_name, const char *p_path) const { + // We store the new names of these paths in our action map, so if we're on older versions of OpenXR, + // we need to use the old names. + + struct RenameMap { + const XrVersion before_version; // If we're on an older version of OpenXR than this (if none zero). + const char *from; // Rename from this + const char *to; // to this + const char *profile; // limiting to this profile (unless nullptr) + }; + + // The order of entries is important as we early exit when we encounter a before_version value before our current value (excluding 0). + const RenameMap renames[] = { + // The touch_controller is an exception where it is still using the vendor names because they were introduced after OpenXR 1.1 was defined. + { 0, "/user/hand/left/input/trigger/proximity", "/user/hand/left/input/trigger/proximity_fb", "/interaction_profiles/oculus/touch_controller" }, + { 0, "/user/hand/right/input/trigger/proximity", "/user/hand/right/input/trigger/proximity_fb", "/interaction_profiles/oculus/touch_controller" }, + { 0, "/user/hand/left/input/thumb_resting_surfaces/proximity", "/user/hand/left/input/thumb_fb/proximity_fb", "/interaction_profiles/oculus/touch_controller" }, + { 0, "/user/hand/right/input/thumb_resting_surfaces/proximity", "/user/hand/right/input/thumb_fb/proximity_fb", "/interaction_profiles/oculus/touch_controller" }, + + // Once applicable, add XR_API_VERSION_1_2 here. + + // Before OpenXR 1.1 we're using palm_ext/pose (we're checking for enabled palm pose extension elsewhere). + { XR_API_VERSION_1_1_0, "/user/hand/left/input/grip_surface/pose", "/user/hand/left/input/palm_ext/pose", nullptr }, + { XR_API_VERSION_1_1_0, "/user/hand/right/input/grip_surface/pose", "/user/hand/right/input/palm_ext/pose", nullptr }, + + // Specific renames for touch_controller_pro, note that we would have already renamed it to the old name. + { XR_API_VERSION_1_1_0, "/user/hand/left/input/grip_surface/pose", "/user/hand/left/input/palm_ext/pose", "/interaction_profiles/facebook/touch_controller_pro" }, + { XR_API_VERSION_1_1_0, "/user/hand/right/input/grip_surface/pose", "/user/hand/right/input/palm_ext/pose", "/interaction_profiles/facebook/touch_controller_pro" }, + { XR_API_VERSION_1_1_0, "/user/hand/left/input/stylus/force", "/user/hand/left/input/stylus_fb/force", "/interaction_profiles/facebook/touch_controller_pro" }, + { XR_API_VERSION_1_1_0, "/user/hand/right/input/stylus/force", "/user/hand/right/input/stylus_fb/force", "/interaction_profiles/facebook/touch_controller_pro" }, + { XR_API_VERSION_1_1_0, "/user/hand/left/input/trigger/proximity", "/user/hand/left/input/trigger/proximity_fb", "/interaction_profiles/facebook/touch_controller_pro" }, + { XR_API_VERSION_1_1_0, "/user/hand/right/input/trigger/proximity", "/user/hand/right/input/trigger/proximity_fb", "/interaction_profiles/facebook/touch_controller_pro" }, + { XR_API_VERSION_1_1_0, "/user/hand/left/output/haptic_trigger", "/user/hand/left/output/haptic_trigger_fb", "/interaction_profiles/facebook/touch_controller_pro" }, + { XR_API_VERSION_1_1_0, "/user/hand/right/output/haptic_trigger", "/user/hand/right/output/haptic_trigger_fb", "/interaction_profiles/facebook/touch_controller_pro" }, + { XR_API_VERSION_1_1_0, "/user/hand/left/output/haptic_thumb", "/user/hand/left/output/haptic_thumb_fb", "/interaction_profiles/facebook/touch_controller_pro" }, + { XR_API_VERSION_1_1_0, "/user/hand/right/output/haptic_thumb", "/user/hand/right/output/haptic_thumb_fb", "/interaction_profiles/facebook/touch_controller_pro" }, + { XR_API_VERSION_1_1_0, "/user/hand/left/input/thumb_resting_surfaces/proximity", "/user/hand/left/input/thumb_fb/proximity_fb", "/interaction_profiles/facebook/touch_controller_pro" }, + { XR_API_VERSION_1_1_0, "/user/hand/right/input/thumb_resting_surfaces/proximity", "/user/hand/right/input/thumb_fb/proximity_fb", "/interaction_profiles/facebook/touch_controller_pro" }, + { XR_API_VERSION_1_1_0, "/user/hand/left/input/trigger_curl/value", "/user/hand/left/input/trigger/curl_fb", "/interaction_profiles/facebook/touch_controller_pro" }, + { XR_API_VERSION_1_1_0, "/user/hand/right/input/trigger_curl/value", "/user/hand/right/input/trigger/curl_fb", "/interaction_profiles/facebook/touch_controller_pro" }, + { XR_API_VERSION_1_1_0, "/user/hand/left/input/trigger_slide/value", "/user/hand/left/input/trigger/slide_fb", "/interaction_profiles/facebook/touch_controller_pro" }, + { XR_API_VERSION_1_1_0, "/user/hand/right/input/trigger_slide/value", "/user/hand/right/input/trigger/slide_fb", "/interaction_profiles/facebook/touch_controller_pro" }, + + // Specific renames for touch_controller_plus, note that we would have already renamed it to the old name. + { XR_API_VERSION_1_1_0, "/user/hand/left/input/trigger/proximity", "/user/hand/left/input/trigger/proximity_meta", "/interaction_profiles/facebook/touch_controller_plus" }, + { XR_API_VERSION_1_1_0, "/user/hand/right/input/trigger/proximity", "/user/hand/right/input/trigger/proximity_meta", "/interaction_profiles/facebook/touch_controller_plus" }, + { XR_API_VERSION_1_1_0, "/user/hand/left/input/thumb_resting_surfaces/proximity", "/user/hand/left/input/thumb_meta/proximity_meta", "/interaction_profiles/facebook/touch_controller_plus" }, + { XR_API_VERSION_1_1_0, "/user/hand/right/input/thumb_resting_surfaces/proximity", "/user/hand/right/input/thumb_meta/proximity_meta", "/interaction_profiles/facebook/touch_controller_plus" }, + { XR_API_VERSION_1_1_0, "/user/hand/left/input/trigger_curl/value", "/user/hand/left/input/trigger/curl_meta", "/interaction_profiles/facebook/touch_controller_plus" }, + { XR_API_VERSION_1_1_0, "/user/hand/right/input/trigger_curl/value", "/user/hand/right/input/trigger/curl_meta", "/interaction_profiles/facebook/touch_controller_plus" }, + { XR_API_VERSION_1_1_0, "/user/hand/left/input/trigger_slide/value", "/user/hand/left/input/trigger/slide_meta", "/interaction_profiles/facebook/touch_controller_plus" }, + { XR_API_VERSION_1_1_0, "/user/hand/right/input/trigger_slide/value", "/user/hand/right/input/trigger/slide_meta", "/interaction_profiles/facebook/touch_controller_plus" }, + }; + constexpr size_t length = sizeof(renames) / sizeof(renames[0]); + + for (size_t i = 0; i < length; i++) { + const RenameMap &rename = renames[i]; + + if (rename.before_version != 0 && openxr_version >= rename.before_version) { + // We're done, we are on a new version than this, no need to check further. + return p_path; + } + + if ((rename.profile == nullptr || p_interaction_profile_name == rename.profile) && strcmp(p_path, rename.from) == 0) { + return rename.to; + } + } + + return p_path; +} + int OpenXRAPI::interaction_profile_add_binding(RID p_interaction_profile, RID p_action, const String &p_path) { InteractionProfile *ip = interaction_profile_owner.get_or_null(p_interaction_profile); ERR_FAIL_NULL_V(ip, -1); @@ -3458,7 +3580,7 @@ int OpenXRAPI::interaction_profile_add_binding(RID p_interaction_profile, RID p_ binding.action = action->handle; - XrResult result = xrStringToPath(instance, p_path.utf8().get_data(), &binding.binding); + XrResult result = xrStringToPath(instance, check_profile_path(ip->internal_name, p_path.utf8().get_data()), &binding.binding); if (XR_FAILED(result)) { print_line("OpenXR: failed to get path for ", p_path, "! [", get_error_string(result), "]"); return -1; diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h index 043abfff423..f1733391ac1 100644 --- a/modules/openxr/openxr_api.h +++ b/modules/openxr/openxr_api.h @@ -46,6 +46,11 @@ #include +// Name we add to our extensions if OpenXR 1.1 context is available. +#define XR_OPENXR_1_1_NAME "OPENXR_1_1" + +#define XR_API_VERSION_1_1_0 XR_MAKE_VERSION(1, 1, 0) + // forward declarations, we don't want to include these fully class OpenXRInterface; @@ -91,7 +96,7 @@ private: // extensions LocalVector supported_extensions; - Vector enabled_extensions; + LocalVector enabled_extensions; // composition layer providers Vector composition_layer_providers; @@ -112,6 +117,7 @@ private: PackedInt64Array supported_swapchain_formats; // system info + XrVersion openxr_version; String runtime_name; String runtime_version; @@ -180,7 +186,13 @@ private: bool load_layer_properties(); bool load_supported_extensions(); bool is_extension_supported(const String &p_extension) const; - bool is_extension_enabled(const String &p_extension) const; + bool is_any_extension_enabled(const String &p_extensions) const; + + struct RequestExtension { + String name; + bool *enabled; + }; + XrResult attempt_create_instance(XrVersion p_version); bool openxr_loader_init(); bool resolve_instance_openxr_symbols(); @@ -299,6 +311,7 @@ private: struct InteractionProfile { // Interaction profiles define suggested bindings between the physical inputs on controller types and our actions String name; // Name of the interaction profile (i.e. "/interaction_profiles/valve/index_controller") + CharString internal_name; // Internal name of the interaction profile (translated if required) XrPath path; // OpenXR path for this profile Vector bindings; // OpenXR action bindings Vector modifiers; // Array of modifiers we'll add into XrBindingModificationsKHR @@ -307,6 +320,9 @@ private: RID get_interaction_profile_rid(XrPath p_path); XrPath get_interaction_profile_path(RID p_interaction_profile); + CharString get_interaction_profile_internal_name(const String &p_interaction_profile_name) const; + const char *check_profile_path(const CharString &p_interaction_profile_name, const char *p_path) const; + struct OrderedCompositionLayer { const XrCompositionLayerBaseHeader *composition_layer; int sort_order; @@ -436,6 +452,7 @@ public: rendering_server->call_on_render_thread(callable_mp_static(&OpenXRAPI::_update_main_swapchain_size_rt)); } + XrVersion get_openxr_version() const { return openxr_version; } XrInstance get_instance() const { return instance; } XrSystemId get_system_id() const { return system_id; } XrSession get_session() const { return session; } @@ -480,7 +497,7 @@ public: static const Vector &get_registered_extension_wrappers(); static void register_extension_metadata(); static void cleanup_extension_wrappers(); - static PackedStringArray get_all_requested_extensions(); + static PackedStringArray get_all_requested_extensions(XrVersion p_xr_version); void set_form_factor(XrFormFactor p_form_factor); XrFormFactor get_form_factor() const { return form_factor; } diff --git a/modules/openxr/openxr_api_extension.cpp b/modules/openxr/openxr_api_extension.cpp index 916a03e2724..750d9bb9ad5 100644 --- a/modules/openxr/openxr_api_extension.cpp +++ b/modules/openxr/openxr_api_extension.cpp @@ -34,6 +34,7 @@ #include "openxr_api_extension.compat.inc" void OpenXRAPIExtension::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_openxr_version"), &OpenXRAPIExtension::get_openxr_version); ClassDB::bind_method(D_METHOD("get_instance"), &OpenXRAPIExtension::get_instance); ClassDB::bind_method(D_METHOD("get_system_id"), &OpenXRAPIExtension::get_system_id); ClassDB::bind_method(D_METHOD("get_session"), &OpenXRAPIExtension::get_session); @@ -102,6 +103,11 @@ void OpenXRAPIExtension::_bind_methods() { BIND_ENUM_CONSTANT(OPENXR_ALPHA_BLEND_MODE_SUPPORT_EMULATING); } +uint64_t OpenXRAPIExtension::get_openxr_version() { + ERR_FAIL_NULL_V(OpenXRAPI::get_singleton(), 0); + return (uint64_t)OpenXRAPI::get_singleton()->get_openxr_version(); +} + uint64_t OpenXRAPIExtension::get_instance() { ERR_FAIL_NULL_V(OpenXRAPI::get_singleton(), 0); return (uint64_t)OpenXRAPI::get_singleton()->get_instance(); diff --git a/modules/openxr/openxr_api_extension.h b/modules/openxr/openxr_api_extension.h index 869839feee0..63dd1c2f1e6 100644 --- a/modules/openxr/openxr_api_extension.h +++ b/modules/openxr/openxr_api_extension.h @@ -56,6 +56,7 @@ protected: #endif public: + uint64_t get_openxr_version(); uint64_t get_instance(); uint64_t get_system_id(); uint64_t get_session();