diff options
Diffstat (limited to 'modules/openxr')
23 files changed, 259 insertions, 131 deletions
diff --git a/modules/openxr/SCsub b/modules/openxr/SCsub index dd6a921440..48c87bcd59 100644 --- a/modules/openxr/SCsub +++ b/modules/openxr/SCsub @@ -26,7 +26,7 @@ elif env["platform"] == "linuxbsd": env_openxr.AppendUnique(CPPDEFINES=["XR_USE_PLATFORM_XLIB"]) if env["wayland"]: - env_openxr.AppendUnique(CPPDEFINES=["XR_USE_PLATFORM_WAYLAND"]) + env_openxr.AppendUnique(CPPDEFINES=["XR_USE_PLATFORM_EGL"]) # FIXME: Review what needs to be set for Android and macOS. env_openxr.AppendUnique(CPPDEFINES=["HAVE_SECURE_GETENV"]) diff --git a/modules/openxr/action_map/openxr_action_map.cpp b/modules/openxr/action_map/openxr_action_map.cpp index 5430a41d6d..f924386ecf 100644 --- a/modules/openxr/action_map/openxr_action_map.cpp +++ b/modules/openxr/action_map/openxr_action_map.cpp @@ -576,20 +576,15 @@ PackedStringArray OpenXRActionMap::get_top_level_paths(const Ref<OpenXRAction> p const OpenXRInteractionProfileMetadata::InteractionProfile *profile = OpenXRInteractionProfileMetadata::get_singleton()->get_profile(ip->get_interaction_profile_path()); if (profile != nullptr) { - for (int j = 0; j < ip->get_binding_count(); j++) { - Ref<OpenXRIPBinding> binding = ip->get_binding(j); - if (binding->get_action() == p_action) { - PackedStringArray paths = binding->get_paths(); - - for (int k = 0; k < paths.size(); k++) { - const OpenXRInteractionProfileMetadata::IOPath *io_path = profile->get_io_path(paths[k]); - if (io_path != nullptr) { - String top_path = io_path->top_level_path; - - if (!arr.has(top_path)) { - arr.push_back(top_path); - } - } + Vector<Ref<OpenXRIPBinding>> bindings = ip->get_bindings_for_action(p_action); + for (const Ref<OpenXRIPBinding> &binding : bindings) { + String binding_path = binding->get_binding_path(); + const OpenXRInteractionProfileMetadata::IOPath *io_path = profile->get_io_path(binding_path); + if (io_path != nullptr) { + String top_path = io_path->top_level_path; + + if (!arr.has(top_path)) { + arr.push_back(top_path); } } } diff --git a/modules/openxr/action_map/openxr_interaction_profile.cpp b/modules/openxr/action_map/openxr_interaction_profile.cpp index 1266457113..2aab55f6ec 100644 --- a/modules/openxr/action_map/openxr_interaction_profile.cpp +++ b/modules/openxr/action_map/openxr_interaction_profile.cpp @@ -35,23 +35,30 @@ void OpenXRIPBinding::_bind_methods() { ClassDB::bind_method(D_METHOD("get_action"), &OpenXRIPBinding::get_action); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "action", PROPERTY_HINT_RESOURCE_TYPE, "OpenXRAction"), "set_action", "get_action"); - ClassDB::bind_method(D_METHOD("get_path_count"), &OpenXRIPBinding::get_path_count); + ClassDB::bind_method(D_METHOD("set_binding_path", "binding_path"), &OpenXRIPBinding::set_binding_path); + ClassDB::bind_method(D_METHOD("get_binding_path"), &OpenXRIPBinding::get_binding_path); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "binding_path"), "set_binding_path", "get_binding_path"); + + // Deprecated +#ifndef DISABLE_DEPRECATED ClassDB::bind_method(D_METHOD("set_paths", "paths"), &OpenXRIPBinding::set_paths); ClassDB::bind_method(D_METHOD("get_paths"), &OpenXRIPBinding::get_paths); - ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "paths"), "set_paths", "get_paths"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "paths", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_paths", "get_paths"); + ClassDB::bind_method(D_METHOD("get_path_count"), &OpenXRIPBinding::get_path_count); ClassDB::bind_method(D_METHOD("has_path", "path"), &OpenXRIPBinding::has_path); ClassDB::bind_method(D_METHOD("add_path", "path"), &OpenXRIPBinding::add_path); ClassDB::bind_method(D_METHOD("remove_path", "path"), &OpenXRIPBinding::remove_path); +#endif // DISABLE_DEPRECATED } -Ref<OpenXRIPBinding> OpenXRIPBinding::new_binding(const Ref<OpenXRAction> p_action, const char *p_paths) { +Ref<OpenXRIPBinding> OpenXRIPBinding::new_binding(const Ref<OpenXRAction> p_action, const String &p_binding_path) { // This is a helper function to help build our default action sets Ref<OpenXRIPBinding> binding; binding.instantiate(); binding->set_action(p_action); - binding->parse_paths(String(p_paths)); + binding->set_binding_path(p_binding_path); return binding; } @@ -65,42 +72,68 @@ Ref<OpenXRAction> OpenXRIPBinding::get_action() const { return action; } -int OpenXRIPBinding::get_path_count() const { - return paths.size(); +void OpenXRIPBinding::set_binding_path(const String &path) { + binding_path = path; + emit_changed(); } -void OpenXRIPBinding::set_paths(const PackedStringArray p_paths) { - paths = p_paths; - emit_changed(); +String OpenXRIPBinding::get_binding_path() const { + return binding_path; } -PackedStringArray OpenXRIPBinding::get_paths() const { +#ifndef DISABLE_DEPRECATED + +void OpenXRIPBinding::set_paths(const PackedStringArray p_paths) { // Deprecated, but needed for loading old action maps. + // Fallback logic, this should ONLY be called when loading older action maps. + // We'll parse this momentarily and extract individual bindings. + binding_path = ""; + for (const String &path : p_paths) { + if (!binding_path.is_empty()) { + binding_path += ","; + } + binding_path += path; + } +} + +PackedStringArray OpenXRIPBinding::get_paths() const { // Deprecated, but needed for converting old action maps. + // Fallback logic, return an array. + // If we just loaded an old action map from disc, this will be a comma separated list of actions. + // Once parsed there should be only one path in our array. + PackedStringArray paths = binding_path.split(",", false); + return paths; } -void OpenXRIPBinding::parse_paths(const String p_paths) { - paths = p_paths.split(",", false); - emit_changed(); +int OpenXRIPBinding::get_path_count() const { // Deprecated. + // Fallback logic, we only have one entry. + return binding_path.is_empty() ? 0 : 1; } -bool OpenXRIPBinding::has_path(const String p_path) const { - return paths.has(p_path); +bool OpenXRIPBinding::has_path(const String p_path) const { // Deprecated. + // Fallback logic, return true if this is our path. + return binding_path == p_path; } -void OpenXRIPBinding::add_path(const String p_path) { - if (!paths.has(p_path)) { - paths.push_back(p_path); +void OpenXRIPBinding::add_path(const String p_path) { // Deprecated. + // Fallback logic, only assign first time this is called. + if (binding_path != p_path) { + ERR_FAIL_COND_MSG(!binding_path.is_empty(), "Method add_path has been deprecated. A binding path was already set, create separate binding resources for each path and use set_binding_path instead."); + + binding_path = p_path; emit_changed(); } } -void OpenXRIPBinding::remove_path(const String p_path) { - if (paths.has(p_path)) { - paths.erase(p_path); - emit_changed(); - } +void OpenXRIPBinding::remove_path(const String p_path) { // Deprecated. + ERR_FAIL_COND_MSG(binding_path != p_path, "Method remove_path has been deprecated. Attempt at removing a different binding path, remove the correct binding record from the interaction profile instead."); + + // Fallback logic, clear if this is our path. + binding_path = p_path; + emit_changed(); } +#endif // DISABLE_DEPRECATED + OpenXRIPBinding::~OpenXRIPBinding() { action.unref(); } @@ -151,9 +184,18 @@ Ref<OpenXRIPBinding> OpenXRInteractionProfile::get_binding(int p_index) const { } void OpenXRInteractionProfile::set_bindings(Array p_bindings) { - // TODO add check here that our bindings don't contain duplicate actions + bindings.clear(); + + for (Ref<OpenXRIPBinding> binding : p_bindings) { + String binding_path = binding->get_binding_path(); + if (binding_path.find_char(',') >= 0) { + // Convert old binding approach to new... + add_new_binding(binding->get_action(), binding_path); + } else { + add_binding(binding); + } + } - bindings = p_bindings; emit_changed(); } @@ -161,10 +203,9 @@ Array OpenXRInteractionProfile::get_bindings() const { return bindings; } -Ref<OpenXRIPBinding> OpenXRInteractionProfile::get_binding_for_action(const Ref<OpenXRAction> p_action) const { - for (int i = 0; i < bindings.size(); i++) { - Ref<OpenXRIPBinding> binding = bindings[i]; - if (binding->get_action() == p_action) { +Ref<OpenXRIPBinding> OpenXRInteractionProfile::find_binding(const Ref<OpenXRAction> p_action, const String &p_binding_path) const { + for (Ref<OpenXRIPBinding> binding : bindings) { + if (binding->get_action() == p_action && binding->get_binding_path() == p_binding_path) { return binding; } } @@ -172,11 +213,23 @@ Ref<OpenXRIPBinding> OpenXRInteractionProfile::get_binding_for_action(const Ref< return Ref<OpenXRIPBinding>(); } +Vector<Ref<OpenXRIPBinding>> OpenXRInteractionProfile::get_bindings_for_action(const Ref<OpenXRAction> p_action) const { + Vector<Ref<OpenXRIPBinding>> ret_bindings; + + for (Ref<OpenXRIPBinding> binding : bindings) { + if (binding->get_action() == p_action) { + ret_bindings.push_back(binding); + } + } + + return ret_bindings; +} + void OpenXRInteractionProfile::add_binding(Ref<OpenXRIPBinding> p_binding) { ERR_FAIL_COND(p_binding.is_null()); if (!bindings.has(p_binding)) { - ERR_FAIL_COND_MSG(get_binding_for_action(p_binding->get_action()).is_valid(), "There is already a binding for this action in this interaction profile"); + ERR_FAIL_COND_MSG(find_binding(p_binding->get_action(), p_binding->get_binding_path()).is_valid(), "There is already a binding for this action and binding path in this interaction profile."); bindings.push_back(p_binding); emit_changed(); @@ -191,11 +244,15 @@ void OpenXRInteractionProfile::remove_binding(Ref<OpenXRIPBinding> p_binding) { } } -void OpenXRInteractionProfile::add_new_binding(const Ref<OpenXRAction> p_action, const char *p_paths) { +void OpenXRInteractionProfile::add_new_binding(const Ref<OpenXRAction> p_action, const String &p_paths) { // This is a helper function to help build our default action sets - Ref<OpenXRIPBinding> binding = OpenXRIPBinding::new_binding(p_action, p_paths); - add_binding(binding); + PackedStringArray paths = p_paths.split(",", false); + + for (const String &path : paths) { + Ref<OpenXRIPBinding> binding = OpenXRIPBinding::new_binding(p_action, path); + add_binding(binding); + } } void OpenXRInteractionProfile::remove_binding_for_action(const Ref<OpenXRAction> p_action) { diff --git a/modules/openxr/action_map/openxr_interaction_profile.h b/modules/openxr/action_map/openxr_interaction_profile.h index 479cc3c527..952f87a09d 100644 --- a/modules/openxr/action_map/openxr_interaction_profile.h +++ b/modules/openxr/action_map/openxr_interaction_profile.h @@ -41,26 +41,29 @@ class OpenXRIPBinding : public Resource { private: Ref<OpenXRAction> action; - PackedStringArray paths; + String binding_path; protected: static void _bind_methods(); public: - static Ref<OpenXRIPBinding> new_binding(const Ref<OpenXRAction> p_action, const char *p_paths); // Helper function for adding a new binding + static Ref<OpenXRIPBinding> new_binding(const Ref<OpenXRAction> p_action, const String &p_binding_path); // Helper function for adding a new binding. - void set_action(const Ref<OpenXRAction> p_action); // Set the action for this binding - Ref<OpenXRAction> get_action() const; // Get the action for this binding + void set_action(const Ref<OpenXRAction> p_action); // Set the action for this binding. + Ref<OpenXRAction> get_action() const; // Get the action for this binding. - int get_path_count() const; // Get the number of io paths - void set_paths(const PackedStringArray p_paths); // Set our paths (for loading from resource) - PackedStringArray get_paths() const; // Get our paths (for saving to resource) + void set_binding_path(const String &path); + String get_binding_path() const; - void parse_paths(const String p_paths); // Parse a comma separated string of io paths. - - bool has_path(const String p_path) const; // Has this io path - void add_path(const String p_path); // Add an io path - void remove_path(const String p_path); // Remove an io path + // Deprecated. +#ifndef DISABLE_DEPRECATED + void set_paths(const PackedStringArray p_paths); // Set our paths (for loading from resource), needed for loading old action maps. + PackedStringArray get_paths() const; // Get our paths (for saving to resource), needed for converted old action maps. + int get_path_count() const; // Get the number of io paths. + bool has_path(const String p_path) const; // Has this io path. + void add_path(const String p_path); // Add an io path. + void remove_path(const String p_path); // Remove an io path. +#endif // DISABLE_DEPRECATED // TODO add validation that we can display in the interface that checks if no two paths belong to the same top level path @@ -88,11 +91,12 @@ public: void set_bindings(Array p_bindings); // Set the bindings (for loading from a resource) Array get_bindings() const; // Get the bindings (for saving to a resource) - Ref<OpenXRIPBinding> get_binding_for_action(const Ref<OpenXRAction> p_action) const; // Get our binding record for a given action + Ref<OpenXRIPBinding> find_binding(const Ref<OpenXRAction> p_action, const String &p_binding_path) const; // Get our binding record + Vector<Ref<OpenXRIPBinding>> get_bindings_for_action(const Ref<OpenXRAction> p_action) const; // Get our binding record for a given action void add_binding(Ref<OpenXRIPBinding> p_binding); // Add a binding object void remove_binding(Ref<OpenXRIPBinding> p_binding); // Remove a binding object - void add_new_binding(const Ref<OpenXRAction> p_action, const char *p_paths); // Create a new binding for this profile + void add_new_binding(const Ref<OpenXRAction> p_action, const String &p_paths); // Create a new binding for this profile void remove_binding_for_action(const Ref<OpenXRAction> p_action); // Remove all bindings for this action bool has_binding_for_action(const Ref<OpenXRAction> p_action); // Returns true if we have a binding for this action diff --git a/modules/openxr/doc_classes/OpenXRCompositionLayer.xml b/modules/openxr/doc_classes/OpenXRCompositionLayer.xml index 341b50065c..cfc7cd4d97 100644 --- a/modules/openxr/doc_classes/OpenXRCompositionLayer.xml +++ b/modules/openxr/doc_classes/OpenXRCompositionLayer.xml @@ -29,7 +29,7 @@ <method name="is_natively_supported" qualifiers="const"> <return type="bool" /> <description> - Returns true if the OpenXR runtime natively supports this composition layer type. + Returns [code]true[/code] if the OpenXR runtime natively supports this composition layer type. [b]Note:[/b] This will only return an accurate result after the OpenXR session has started. </description> </method> diff --git a/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml b/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml index 813c9d582e..182fe32f9c 100644 --- a/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml +++ b/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml @@ -90,6 +90,21 @@ Called right after the main swapchains are (re)created. </description> </method> + <method name="_on_post_draw_viewport" qualifiers="virtual"> + <return type="void" /> + <param index="0" name="viewport" type="RID" /> + <description> + Called right after the given viewport is rendered. + [b]Note:[/b] The draw commands might only be queued at this point, not executed. + </description> + </method> + <method name="_on_pre_draw_viewport" qualifiers="virtual"> + <return type="void" /> + <param index="0" name="viewport" type="RID" /> + <description> + Called right before the given viewport is rendered. + </description> + </method> <method name="_on_pre_render" qualifiers="virtual"> <return type="void" /> <description> diff --git a/modules/openxr/doc_classes/OpenXRIPBinding.xml b/modules/openxr/doc_classes/OpenXRIPBinding.xml index f274f0868e..ddd6fbe268 100644 --- a/modules/openxr/doc_classes/OpenXRIPBinding.xml +++ b/modules/openxr/doc_classes/OpenXRIPBinding.xml @@ -4,32 +4,32 @@ Defines a binding between an [OpenXRAction] and an XR input or output. </brief_description> <description> - This binding resource binds an [OpenXRAction] to inputs or outputs. As most controllers have left hand and right versions that are handled by the same interaction profile we can specify multiple bindings. For instance an action "Fire" could be bound to both "/user/hand/left/input/trigger" and "/user/hand/right/input/trigger". + This binding resource binds an [OpenXRAction] to an input or output. As most controllers have left hand and right versions that are handled by the same interaction profile we can specify multiple bindings. For instance an action "Fire" could be bound to both "/user/hand/left/input/trigger" and "/user/hand/right/input/trigger". This would require two binding entries. </description> <tutorials> </tutorials> <methods> - <method name="add_path"> + <method name="add_path" deprecated="Binding is for a single path."> <return type="void" /> <param index="0" name="path" type="String" /> <description> Add an input/output path to this binding. </description> </method> - <method name="get_path_count" qualifiers="const"> + <method name="get_path_count" qualifiers="const" deprecated="Binding is for a single path."> <return type="int" /> <description> Get the number of input/output paths in this binding. </description> </method> - <method name="has_path" qualifiers="const"> + <method name="has_path" qualifiers="const" deprecated="Binding is for a single path."> <return type="bool" /> <param index="0" name="path" type="String" /> <description> Returns [code]true[/code] if this input/output path is part of this binding. </description> </method> - <method name="remove_path"> + <method name="remove_path" deprecated="Binding is for a single path."> <return type="void" /> <param index="0" name="path" type="String" /> <description> @@ -39,9 +39,13 @@ </methods> <members> <member name="action" type="OpenXRAction" setter="set_action" getter="get_action"> - [OpenXRAction] that is bound to these paths. + [OpenXRAction] that is bound to [member binding_path]. </member> - <member name="paths" type="PackedStringArray" setter="set_paths" getter="get_paths" default="PackedStringArray()"> + <member name="binding_path" type="String" setter="set_binding_path" getter="get_binding_path" default=""""> + Binding path that defines the input or output bound to [member action]. + [b]Note:[/b] Binding paths are suggestions, an XR runtime may choose to bind the action to a different input or output emulating this input or output. + </member> + <member name="paths" type="PackedStringArray" setter="set_paths" getter="get_paths" deprecated="Use [member binding_path] instead."> Paths that define the inputs or outputs bound on the device. </member> </members> diff --git a/modules/openxr/editor/openxr_action_editor.cpp b/modules/openxr/editor/openxr_action_editor.cpp index 63162ba3dc..dd5f6378f4 100644 --- a/modules/openxr/editor/openxr_action_editor.cpp +++ b/modules/openxr/editor/openxr_action_editor.cpp @@ -41,7 +41,7 @@ void OpenXRActionEditor::_bind_methods() { } void OpenXRActionEditor::_theme_changed() { - rem_action->set_icon(get_theme_icon(SNAME("Remove"), EditorStringName(EditorIcons))); + rem_action->set_button_icon(get_theme_icon(SNAME("Remove"), EditorStringName(EditorIcons))); } void OpenXRActionEditor::_notification(int p_what) { diff --git a/modules/openxr/editor/openxr_action_editor.h b/modules/openxr/editor/openxr_action_editor.h index 11d1fd657a..b672fe7340 100644 --- a/modules/openxr/editor/openxr_action_editor.h +++ b/modules/openxr/editor/openxr_action_editor.h @@ -68,7 +68,7 @@ protected: void _do_set_action_type(OpenXRAction::ActionType p_action_type); public: - Ref<OpenXRAction> get_action() { return action; }; + Ref<OpenXRAction> get_action() { return action; } OpenXRActionEditor(Ref<OpenXRAction> p_action); }; diff --git a/modules/openxr/editor/openxr_action_set_editor.cpp b/modules/openxr/editor/openxr_action_set_editor.cpp index 0c55592707..e5e034ef08 100644 --- a/modules/openxr/editor/openxr_action_set_editor.cpp +++ b/modules/openxr/editor/openxr_action_set_editor.cpp @@ -46,16 +46,16 @@ void OpenXRActionSetEditor::_bind_methods() { void OpenXRActionSetEditor::_set_fold_icon() { if (is_expanded) { - fold_btn->set_icon(get_theme_icon(SNAME("GuiTreeArrowDown"), EditorStringName(EditorIcons))); + fold_btn->set_button_icon(get_theme_icon(SNAME("GuiTreeArrowDown"), EditorStringName(EditorIcons))); } else { - fold_btn->set_icon(get_theme_icon(SNAME("GuiTreeArrowRight"), EditorStringName(EditorIcons))); + fold_btn->set_button_icon(get_theme_icon(SNAME("GuiTreeArrowRight"), EditorStringName(EditorIcons))); } } void OpenXRActionSetEditor::_theme_changed() { _set_fold_icon(); - add_action->set_icon(get_theme_icon(SNAME("Add"), EditorStringName(EditorIcons))); - rem_action_set->set_icon(get_theme_icon(SNAME("Remove"), EditorStringName(EditorIcons))); + add_action->set_button_icon(get_theme_icon(SNAME("Add"), EditorStringName(EditorIcons))); + rem_action_set->set_button_icon(get_theme_icon(SNAME("Remove"), EditorStringName(EditorIcons))); } void OpenXRActionSetEditor::_notification(int p_what) { diff --git a/modules/openxr/editor/openxr_action_set_editor.h b/modules/openxr/editor/openxr_action_set_editor.h index 3261f3a29e..21437aa631 100644 --- a/modules/openxr/editor/openxr_action_set_editor.h +++ b/modules/openxr/editor/openxr_action_set_editor.h @@ -87,7 +87,7 @@ protected: void _do_remove_action_editor(OpenXRActionEditor *p_action_editor); public: - Ref<OpenXRActionSet> get_action_set() { return action_set; }; + Ref<OpenXRActionSet> get_action_set() { return action_set; } void set_focus_on_entry(); void remove_all_actions(); diff --git a/modules/openxr/editor/openxr_interaction_profile_editor.cpp b/modules/openxr/editor/openxr_interaction_profile_editor.cpp index 651171358c..a390919856 100644 --- a/modules/openxr/editor/openxr_interaction_profile_editor.cpp +++ b/modules/openxr/editor/openxr_interaction_profile_editor.cpp @@ -73,17 +73,19 @@ void OpenXRInteractionProfileEditorBase::_add_binding(const String p_action, con Ref<OpenXRAction> action = action_map->get_action(p_action); ERR_FAIL_COND(action.is_null()); - Ref<OpenXRIPBinding> binding = interaction_profile->get_binding_for_action(action); + Ref<OpenXRIPBinding> binding = interaction_profile->find_binding(action, p_path); if (binding.is_null()) { // create a new binding binding.instantiate(); binding->set_action(action); + binding->set_binding_path(p_path); + + // add it to our interaction profile interaction_profile->add_binding(binding); interaction_profile->set_edited(true); - } - binding->add_path(p_path); - binding->set_edited(true); + binding->set_edited(true); + } // Update our toplevel paths action->set_toplevel_paths(action_map->get_top_level_paths(action)); @@ -98,15 +100,10 @@ void OpenXRInteractionProfileEditorBase::_remove_binding(const String p_action, Ref<OpenXRAction> action = action_map->get_action(p_action); ERR_FAIL_COND(action.is_null()); - Ref<OpenXRIPBinding> binding = interaction_profile->get_binding_for_action(action); + Ref<OpenXRIPBinding> binding = interaction_profile->find_binding(action, p_path); if (binding.is_valid()) { - binding->remove_path(p_path); - binding->set_edited(true); - - if (binding->get_path_count() == 0) { - interaction_profile->remove_binding(binding); - interaction_profile->set_edited(true); - } + interaction_profile->remove_binding(binding); + interaction_profile->set_edited(true); // Update our toplevel paths action->set_toplevel_paths(action_map->get_top_level_paths(action)); @@ -116,21 +113,22 @@ void OpenXRInteractionProfileEditorBase::_remove_binding(const String p_action, } void OpenXRInteractionProfileEditorBase::remove_all_bindings_for_action(Ref<OpenXRAction> p_action) { - Ref<OpenXRIPBinding> binding = interaction_profile->get_binding_for_action(p_action); - if (binding.is_valid()) { + Vector<Ref<OpenXRIPBinding>> bindings = interaction_profile->get_bindings_for_action(p_action); + if (bindings.size() > 0) { String action_name = p_action->get_name_with_set(); // for our undo/redo we process all paths undo_redo->create_action(TTR("Remove action from interaction profile")); - PackedStringArray paths = binding->get_paths(); - for (const String &path : paths) { - undo_redo->add_do_method(this, "_remove_binding", action_name, path); - undo_redo->add_undo_method(this, "_add_binding", action_name, path); + for (const Ref<OpenXRIPBinding> &binding : bindings) { + undo_redo->add_do_method(this, "_remove_binding", action_name, binding->get_binding_path()); + undo_redo->add_undo_method(this, "_add_binding", action_name, binding->get_binding_path()); } undo_redo->commit_action(false); // but we take a shortcut here :) - interaction_profile->remove_binding(binding); + for (const Ref<OpenXRIPBinding> &binding : bindings) { + interaction_profile->remove_binding(binding); + } interaction_profile->set_edited(true); // Update our toplevel paths @@ -220,7 +218,7 @@ void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, co path_hb->add_child(type_label); Button *path_add = memnew(Button); - path_add->set_icon(get_theme_icon(SNAME("Add"), EditorStringName(EditorIcons))); + path_add->set_button_icon(get_theme_icon(SNAME("Add"), EditorStringName(EditorIcons))); path_add->set_flat(true); path_add->connect(SceneStringName(pressed), callable_mp(this, &OpenXRInteractionProfileEditor::select_action_for).bind(String(p_io_path->openxr_path))); path_hb->add_child(path_add); @@ -228,9 +226,8 @@ void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, co if (interaction_profile.is_valid()) { String io_path = String(p_io_path->openxr_path); Array bindings = interaction_profile->get_bindings(); - for (int i = 0; i < bindings.size(); i++) { - Ref<OpenXRIPBinding> binding = bindings[i]; - if (binding->has_path(io_path)) { + for (Ref<OpenXRIPBinding> binding : bindings) { + if (binding->get_binding_path() == io_path) { Ref<OpenXRAction> action = binding->get_action(); HBoxContainer *action_hb = memnew(HBoxContainer); @@ -248,7 +245,7 @@ void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, co Button *action_rem = memnew(Button); action_rem->set_flat(true); - action_rem->set_icon(get_theme_icon(SNAME("Remove"), EditorStringName(EditorIcons))); + action_rem->set_button_icon(get_theme_icon(SNAME("Remove"), EditorStringName(EditorIcons))); action_rem->connect(SceneStringName(pressed), callable_mp((OpenXRInteractionProfileEditor *)this, &OpenXRInteractionProfileEditor::_on_remove_pressed).bind(action->get_name_with_set(), String(p_io_path->openxr_path))); action_hb->add_child(action_rem); } diff --git a/modules/openxr/extensions/openxr_composition_layer_extension.cpp b/modules/openxr/extensions/openxr_composition_layer_extension.cpp index dc30b95b27..1e3490d1ed 100644 --- a/modules/openxr/extensions/openxr_composition_layer_extension.cpp +++ b/modules/openxr/extensions/openxr_composition_layer_extension.cpp @@ -281,7 +281,7 @@ void OpenXRViewportCompositionLayerProvider::create_android_surface() { composition_layer_extension->create_android_surface_swapchain(&info, &android_surface.swapchain, &surface); if (surface) { - android_surface.surface = Ref<JavaObject>(memnew(JavaObject(JavaClassWrapper::get_singleton()->wrap("android.view.Surface"), surface))); + android_surface.surface.instantiate(JavaClassWrapper::get_singleton()->wrap("android.view.Surface"), surface); } } #endif @@ -341,7 +341,7 @@ XrCompositionLayerBaseHeader *OpenXRViewportCompositionLayerProvider::get_compos } XrSwapchainSubImage subimage = { - 0, // swapchain + 0, // swapchain // NOLINT(modernize-use-nullptr) - 32-bit uses non-pointer uint64 { { 0, 0 }, { 0, 0 } }, // imageRect 0, // imageArrayIndex }; diff --git a/modules/openxr/extensions/openxr_debug_utils_extension.cpp b/modules/openxr/extensions/openxr_debug_utils_extension.cpp index 10dbe629f7..cb7f72d02d 100644 --- a/modules/openxr/extensions/openxr_debug_utils_extension.cpp +++ b/modules/openxr/extensions/openxr_debug_utils_extension.cpp @@ -173,7 +173,7 @@ void OpenXRDebugUtilsExtension::begin_debug_label_region(const char *p_label_nam const XrDebugUtilsLabelEXT session_active_region_label = { XR_TYPE_DEBUG_UTILS_LABEL_EXT, // type - NULL, // next + nullptr, // next p_label_name, // labelName }; @@ -199,7 +199,7 @@ void OpenXRDebugUtilsExtension::insert_debug_label(const char *p_label_name) { const XrDebugUtilsLabelEXT session_active_region_label = { XR_TYPE_DEBUG_UTILS_LABEL_EXT, // type - NULL, // next + nullptr, // next p_label_name, // labelName }; diff --git a/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp b/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp index 07ca476421..fb8d1b9d69 100644 --- a/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp +++ b/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp @@ -51,6 +51,8 @@ void OpenXRExtensionWrapperExtension::_bind_methods() { GDVIRTUAL_BIND(_on_process); GDVIRTUAL_BIND(_on_pre_render); GDVIRTUAL_BIND(_on_main_swapchains_created); + GDVIRTUAL_BIND(_on_pre_draw_viewport, "viewport"); + GDVIRTUAL_BIND(_on_post_draw_viewport, "viewport"); GDVIRTUAL_BIND(_on_session_destroyed); GDVIRTUAL_BIND(_on_state_idle); GDVIRTUAL_BIND(_on_state_ready); @@ -208,6 +210,14 @@ void OpenXRExtensionWrapperExtension::on_session_destroyed() { GDVIRTUAL_CALL(_on_session_destroyed); } +void OpenXRExtensionWrapperExtension::on_pre_draw_viewport(RID p_render_target) { + GDVIRTUAL_CALL(_on_pre_draw_viewport, p_render_target); +} + +void OpenXRExtensionWrapperExtension::on_post_draw_viewport(RID p_render_target) { + GDVIRTUAL_CALL(_on_post_draw_viewport, p_render_target); +} + void OpenXRExtensionWrapperExtension::on_state_idle() { GDVIRTUAL_CALL(_on_state_idle); } @@ -298,8 +308,7 @@ void OpenXRExtensionWrapperExtension::register_extension_wrapper() { OpenXRAPI::register_extension_wrapper(this); } -OpenXRExtensionWrapperExtension::OpenXRExtensionWrapperExtension() : - Object(), OpenXRExtensionWrapper() { +OpenXRExtensionWrapperExtension::OpenXRExtensionWrapperExtension() { openxr_api.instantiate(); } diff --git a/modules/openxr/extensions/openxr_extension_wrapper_extension.h b/modules/openxr/extensions/openxr_extension_wrapper_extension.h index 5cdf288c93..8fc6511277 100644 --- a/modules/openxr/extensions/openxr_extension_wrapper_extension.h +++ b/modules/openxr/extensions/openxr_extension_wrapper_extension.h @@ -88,6 +88,8 @@ public: virtual void on_pre_render() override; virtual void on_main_swapchains_created() override; virtual void on_session_destroyed() override; + virtual void on_pre_draw_viewport(RID p_render_target) override; + virtual void on_post_draw_viewport(RID p_render_target) override; GDVIRTUAL0(_on_register_metadata); GDVIRTUAL0(_on_before_instance_created); @@ -98,6 +100,8 @@ public: GDVIRTUAL0(_on_pre_render); GDVIRTUAL0(_on_main_swapchains_created); GDVIRTUAL0(_on_session_destroyed); + GDVIRTUAL1(_on_pre_draw_viewport, RID); + GDVIRTUAL1(_on_post_draw_viewport, RID); virtual void on_state_idle() override; virtual void on_state_ready() override; diff --git a/modules/openxr/extensions/platform/openxr_opengl_extension.cpp b/modules/openxr/extensions/platform/openxr_opengl_extension.cpp index caded14ca7..4fcb3f7b75 100644 --- a/modules/openxr/extensions/platform/openxr_opengl_extension.cpp +++ b/modules/openxr/extensions/platform/openxr_opengl_extension.cpp @@ -64,6 +64,9 @@ HashMap<String, bool *> OpenXROpenGLExtension::get_requested_extensions() { #else request_extensions[XR_KHR_OPENGL_ENABLE_EXTENSION_NAME] = nullptr; #endif +#if defined(LINUXBSD_ENABLED) && defined(EGL_ENABLED) && defined(WAYLAND_ENABLED) + request_extensions[XR_MNDX_EGL_ENABLE_EXTENSION_NAME] = &egl_extension_enabled; +#endif return request_extensions; } @@ -128,9 +131,14 @@ bool OpenXROpenGLExtension::check_graphics_api_support(XrVersion p_desired_versi XrGraphicsBindingOpenGLWin32KHR OpenXROpenGLExtension::graphics_binding_gl; #elif defined(ANDROID_ENABLED) XrGraphicsBindingOpenGLESAndroidKHR OpenXROpenGLExtension::graphics_binding_gl; -#elif defined(X11_ENABLED) +#elif defined(LINUXBSD_ENABLED) +#ifdef X11_ENABLED XrGraphicsBindingOpenGLXlibKHR OpenXROpenGLExtension::graphics_binding_gl; #endif +#if defined(EGL_ENABLED) && defined(WAYLAND_ENABLED) +XrGraphicsBindingEGLMNDX OpenXROpenGLExtension::graphics_binding_egl; +#endif +#endif void *OpenXROpenGLExtension::set_session_create_and_get_next_pointer(void *p_next_pointer) { XrVersion desired_version = XR_MAKE_VERSION(3, 3, 0); @@ -142,10 +150,6 @@ void *OpenXROpenGLExtension::set_session_create_and_get_next_pointer(void *p_nex DisplayServer *display_server = DisplayServer::get_singleton(); -#ifdef WAYLAND_ENABLED - ERR_FAIL_COND_V_MSG(display_server->get_name() == "Wayland", p_next_pointer, "OpenXR is not yet supported on OpenGL Wayland."); -#endif - #ifdef WIN32 graphics_binding_gl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR, graphics_binding_gl.next = p_next_pointer; @@ -159,7 +163,23 @@ void *OpenXROpenGLExtension::set_session_create_and_get_next_pointer(void *p_nex graphics_binding_gl.display = (void *)display_server->window_get_native_handle(DisplayServer::DISPLAY_HANDLE); graphics_binding_gl.config = (EGLConfig)0; // https://github.com/KhronosGroup/OpenXR-SDK-Source/blob/master/src/tests/hello_xr/graphicsplugin_opengles.cpp#L122 graphics_binding_gl.context = (void *)display_server->window_get_native_handle(DisplayServer::OPENGL_CONTEXT); -#elif defined(X11_ENABLED) +#else +#if defined(EGL_ENABLED) && defined(WAYLAND_ENABLED) + if (display_server->get_name() == "Wayland") { + ERR_FAIL_COND_V_MSG(!egl_extension_enabled, p_next_pointer, "OpenXR cannot initialize on Wayland without the XR_MNDX_egl_enable extension."); + + graphics_binding_egl.type = XR_TYPE_GRAPHICS_BINDING_EGL_MNDX; + graphics_binding_egl.next = p_next_pointer; + + graphics_binding_egl.getProcAddress = eglGetProcAddress; + graphics_binding_egl.display = (void *)display_server->window_get_native_handle(DisplayServer::EGL_DISPLAY); + graphics_binding_egl.config = (void *)display_server->window_get_native_handle(DisplayServer::EGL_CONFIG); + graphics_binding_egl.context = (void *)display_server->window_get_native_handle(DisplayServer::OPENGL_CONTEXT); + + return &graphics_binding_egl; + } +#endif +#if defined(X11_ENABLED) graphics_binding_gl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR; graphics_binding_gl.next = p_next_pointer; @@ -173,10 +193,15 @@ void *OpenXROpenGLExtension::set_session_create_and_get_next_pointer(void *p_nex // spec says to use proper values but runtimes don't care graphics_binding_gl.visualid = 0; - graphics_binding_gl.glxFBConfig = 0; + graphics_binding_gl.glxFBConfig = nullptr; +#endif #endif +#if defined(WIN32) || defined(ANDROID_ENABLED) || defined(X11_ENABLED) return &graphics_binding_gl; +#else + return p_next_pointer; +#endif } void OpenXROpenGLExtension::get_usable_swapchain_formats(Vector<int64_t> &p_usable_swap_chains) { diff --git a/modules/openxr/extensions/platform/openxr_opengl_extension.h b/modules/openxr/extensions/platform/openxr_opengl_extension.h index 8da3ca48f4..f4a73c667b 100644 --- a/modules/openxr/extensions/platform/openxr_opengl_extension.h +++ b/modules/openxr/extensions/platform/openxr_opengl_extension.h @@ -64,9 +64,18 @@ private: static XrGraphicsBindingOpenGLWin32KHR graphics_binding_gl; #elif defined(ANDROID_ENABLED) static XrGraphicsBindingOpenGLESAndroidKHR graphics_binding_gl; -#else // Linux/X11 +#elif defined(LINUXBSD_ENABLED) +#ifdef X11_ENABLED static XrGraphicsBindingOpenGLXlibKHR graphics_binding_gl; #endif +#if defined(EGL_ENABLED) && defined(WAYLAND_ENABLED) + static XrGraphicsBindingEGLMNDX graphics_binding_egl; + + bool egl_extension_enabled = false; +#endif +#else +#error "OpenXR with OpenGL isn't supported on this platform" +#endif struct SwapchainGraphicsData { bool is_multiview; diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp index c67be5a2b3..a6fd727290 100644 --- a/modules/openxr/openxr_api.cpp +++ b/modules/openxr/openxr_api.cpp @@ -1294,7 +1294,7 @@ bool OpenXRAPI::create_main_swapchains(Size2i p_size) { } return true; -}; +} void OpenXRAPI::destroy_session() { // TODO need to figure out if we're still rendering our current frame @@ -2353,7 +2353,7 @@ void OpenXRAPI::post_draw_viewport(RID p_render_target) { for (OpenXRExtensionWrapper *wrapper : registered_extension_wrappers) { wrapper->on_post_draw_viewport(p_render_target); } -}; +} void OpenXRAPI::end_frame() { XrResult result; @@ -2752,8 +2752,9 @@ void OpenXRAPI::parse_velocities(const XrSpaceVelocity &p_velocity, Vector3 &r_l } bool OpenXRAPI::xr_result(XrResult result, const char *format, Array args) const { - if (XR_SUCCEEDED(result)) + if (XR_SUCCEEDED(result)) { return true; + } char resultString[XR_MAX_RESULT_STRING_SIZE]; xrResultToString(instance, result, resultString); diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h index 0d1e4eb414..ecffce1816 100644 --- a/modules/openxr/openxr_api.h +++ b/modules/openxr/openxr_api.h @@ -396,12 +396,12 @@ private: } public: - XrInstance get_instance() const { return instance; }; - XrSystemId get_system_id() const { return system_id; }; - XrSession get_session() const { return session; }; - OpenXRGraphicsExtensionWrapper *get_graphics_extension() const { return graphics_extension; }; - String get_runtime_name() const { return runtime_name; }; - String get_runtime_version() const { return runtime_version; }; + XrInstance get_instance() const { return instance; } + XrSystemId get_system_id() const { return system_id; } + XrSession get_session() const { return session; } + OpenXRGraphicsExtensionWrapper *get_graphics_extension() const { return graphics_extension; } + String get_runtime_name() const { return runtime_name; } + String get_runtime_version() const { return runtime_version; } // helper method to convert an XrPosef to a Transform3D Transform3D transform_from_pose(const XrPosef &p_pose); diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp index 73ac529537..8e0c672e58 100644 --- a/modules/openxr/openxr_interface.cpp +++ b/modules/openxr/openxr_interface.cpp @@ -160,11 +160,11 @@ void OpenXRInterface::_bind_methods() { StringName OpenXRInterface::get_name() const { return StringName("OpenXR"); -}; +} uint32_t OpenXRInterface::get_capabilities() const { return XRInterface::XR_VR + XRInterface::XR_STEREO; -}; +} PackedStringArray OpenXRInterface::get_suggested_tracker_names() const { // These are hardcoded in OpenXR, note that they will only be available if added to our action map @@ -300,10 +300,7 @@ void OpenXRInterface::_load_action_map() { continue; } - PackedStringArray paths = xr_binding->get_paths(); - for (int k = 0; k < paths.size(); k++) { - openxr_api->interaction_profile_add_binding(ip, action->action_rid, paths[k]); - } + openxr_api->interaction_profile_add_binding(ip, action->action_rid, xr_binding->get_binding_path()); } // Now submit our suggestions @@ -614,7 +611,7 @@ bool OpenXRInterface::initialize_on_startup() const { bool OpenXRInterface::is_initialized() const { return initialized; -}; +} bool OpenXRInterface::initialize() { XRServer *xr_server = XRServer::get_singleton(); diff --git a/modules/openxr/openxr_platform_inc.h b/modules/openxr/openxr_platform_inc.h index 957a87cbb2..09bc0c89a2 100644 --- a/modules/openxr/openxr_platform_inc.h +++ b/modules/openxr/openxr_platform_inc.h @@ -49,6 +49,13 @@ #else #define XR_USE_GRAPHICS_API_OPENGL #endif // ANDROID_ENABLED +#if defined(LINUXBSD_ENABLED) && defined(EGL_ENABLED) +#ifdef GLAD_ENABLED +#include "thirdparty/glad/glad/egl.h" +#else +#include <EGL/egl.h> +#endif // GLAD_ENABLED +#endif // defined(LINUXBSD_ENABLED) && defined(EGL_ENABLED) #ifdef X11_ENABLED #define GL_GLEXT_PROTOTYPES 1 #define GL3_PROTOTYPES 1 diff --git a/modules/openxr/scene/openxr_composition_layer.cpp b/modules/openxr/scene/openxr_composition_layer.cpp index 697369d516..bc429e4632 100644 --- a/modules/openxr/scene/openxr_composition_layer.cpp +++ b/modules/openxr/scene/openxr_composition_layer.cpp @@ -56,6 +56,10 @@ OpenXRCompositionLayer::OpenXRCompositionLayer(XrCompositionLayerBaseHeader *p_c openxr_api = OpenXRAPI::get_singleton(); composition_layer_extension = OpenXRCompositionLayerExtension::get_singleton(); + if (openxr_api) { + openxr_session_running = openxr_api->is_running(); + } + Ref<OpenXRInterface> openxr_interface = XRServer::get_singleton()->find_interface("OpenXR"); if (openxr_interface.is_valid()) { openxr_interface->connect("session_begun", callable_mp(this, &OpenXRCompositionLayer::_on_openxr_session_begun)); |