summaryrefslogtreecommitdiffstats
path: root/modules/openxr
diff options
context:
space:
mode:
Diffstat (limited to 'modules/openxr')
-rw-r--r--modules/openxr/action_map/openxr_action_map.cpp8
-rw-r--r--modules/openxr/action_map/openxr_action_set.cpp2
-rw-r--r--modules/openxr/action_map/openxr_interaction_profile.cpp2
-rw-r--r--modules/openxr/doc_classes/OpenXRCompositionLayer.xml4
-rw-r--r--modules/openxr/editor/openxr_action_editor.cpp2
-rw-r--r--modules/openxr/editor/openxr_action_map_editor.cpp8
-rw-r--r--modules/openxr/editor/openxr_action_set_editor.cpp6
-rw-r--r--modules/openxr/editor/openxr_interaction_profile_editor.cpp4
-rw-r--r--modules/openxr/editor/openxr_select_action_dialog.cpp2
-rw-r--r--modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp2
-rw-r--r--modules/openxr/extensions/openxr_composition_layer_extension.cpp9
-rw-r--r--modules/openxr/openxr_api.cpp10
-rw-r--r--modules/openxr/openxr_interface.cpp2
-rw-r--r--modules/openxr/scene/openxr_composition_layer.cpp129
-rw-r--r--modules/openxr/scene/openxr_composition_layer.h10
-rw-r--r--modules/openxr/scene/openxr_composition_layer_cylinder.cpp7
-rw-r--r--modules/openxr/scene/openxr_composition_layer_cylinder.h1
-rw-r--r--modules/openxr/scene/openxr_composition_layer_equirect.cpp7
-rw-r--r--modules/openxr/scene/openxr_composition_layer_equirect.h1
-rw-r--r--modules/openxr/scene/openxr_composition_layer_quad.cpp7
-rw-r--r--modules/openxr/scene/openxr_composition_layer_quad.h1
21 files changed, 141 insertions, 83 deletions
diff --git a/modules/openxr/action_map/openxr_action_map.cpp b/modules/openxr/action_map/openxr_action_map.cpp
index ba0e4f6cdd..5430a41d6d 100644
--- a/modules/openxr/action_map/openxr_action_map.cpp
+++ b/modules/openxr/action_map/openxr_action_map.cpp
@@ -59,7 +59,7 @@ void OpenXRActionMap::set_action_sets(Array p_action_sets) {
for (int i = 0; i < p_action_sets.size(); i++) {
Ref<OpenXRActionSet> action_set = p_action_sets[i];
- if (action_set.is_valid() && action_sets.find(action_set) == -1) {
+ if (action_set.is_valid() && !action_sets.has(action_set)) {
action_sets.push_back(action_set);
}
}
@@ -93,7 +93,7 @@ Ref<OpenXRActionSet> OpenXRActionMap::get_action_set(int p_idx) const {
void OpenXRActionMap::add_action_set(Ref<OpenXRActionSet> p_action_set) {
ERR_FAIL_COND(p_action_set.is_null());
- if (action_sets.find(p_action_set) == -1) {
+ if (!action_sets.has(p_action_set)) {
action_sets.push_back(p_action_set);
emit_changed();
}
@@ -112,7 +112,7 @@ void OpenXRActionMap::set_interaction_profiles(Array p_interaction_profiles) {
for (int i = 0; i < p_interaction_profiles.size(); i++) {
Ref<OpenXRInteractionProfile> interaction_profile = p_interaction_profiles[i];
- if (interaction_profile.is_valid() && interaction_profiles.find(interaction_profile) == -1) {
+ if (interaction_profile.is_valid() && !interaction_profiles.has(interaction_profile)) {
interaction_profiles.push_back(interaction_profile);
}
}
@@ -146,7 +146,7 @@ Ref<OpenXRInteractionProfile> OpenXRActionMap::get_interaction_profile(int p_idx
void OpenXRActionMap::add_interaction_profile(Ref<OpenXRInteractionProfile> p_interaction_profile) {
ERR_FAIL_COND(p_interaction_profile.is_null());
- if (interaction_profiles.find(p_interaction_profile) == -1) {
+ if (!interaction_profiles.has(p_interaction_profile)) {
interaction_profiles.push_back(p_interaction_profile);
emit_changed();
}
diff --git a/modules/openxr/action_map/openxr_action_set.cpp b/modules/openxr/action_map/openxr_action_set.cpp
index 4855f9e4b7..d583af2b2f 100644
--- a/modules/openxr/action_map/openxr_action_set.cpp
+++ b/modules/openxr/action_map/openxr_action_set.cpp
@@ -124,7 +124,7 @@ Ref<OpenXRAction> OpenXRActionSet::get_action(const String p_name) const {
void OpenXRActionSet::add_action(Ref<OpenXRAction> p_action) {
ERR_FAIL_COND(p_action.is_null());
- if (actions.find(p_action) == -1) {
+ if (!actions.has(p_action)) {
if (p_action->action_set && p_action->action_set != this) {
// action should only relate to our action set
p_action->action_set->remove_action(p_action);
diff --git a/modules/openxr/action_map/openxr_interaction_profile.cpp b/modules/openxr/action_map/openxr_interaction_profile.cpp
index 65ee652732..2579697d05 100644
--- a/modules/openxr/action_map/openxr_interaction_profile.cpp
+++ b/modules/openxr/action_map/openxr_interaction_profile.cpp
@@ -172,7 +172,7 @@ Ref<OpenXRIPBinding> OpenXRInteractionProfile::get_binding_for_action(const Ref<
void OpenXRInteractionProfile::add_binding(Ref<OpenXRIPBinding> p_binding) {
ERR_FAIL_COND(p_binding.is_null());
- if (bindings.find(p_binding) == -1) {
+ 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");
bindings.push_back(p_binding);
diff --git a/modules/openxr/doc_classes/OpenXRCompositionLayer.xml b/modules/openxr/doc_classes/OpenXRCompositionLayer.xml
index b9c69075e1..6f4ac00f3e 100644
--- a/modules/openxr/doc_classes/OpenXRCompositionLayer.xml
+++ b/modules/openxr/doc_classes/OpenXRCompositionLayer.xml
@@ -32,6 +32,10 @@
Enables the blending the layer using its alpha channel.
Can be combined with [member Viewport.transparent_bg] to give the layer a transparent background.
</member>
+ <member name="enable_hole_punch" type="bool" setter="set_enable_hole_punch" getter="get_enable_hole_punch" default="false">
+ Enables a technique called "hole punching", which allows putting the composition layer behind the main projection layer (i.e. setting [member sort_order] to a negative value) while "punching a hole" through everything rendered by Godot so that the layer is still visible.
+ This can be used to create the illusion that the composition layer exists in the same 3D space as everything rendered by Godot, allowing objects to appear to pass both behind or in front of the composition layer.
+ </member>
<member name="layer_viewport" type="SubViewport" setter="set_layer_viewport" getter="get_layer_viewport">
The [SubViewport] to render on the composition layer.
</member>
diff --git a/modules/openxr/editor/openxr_action_editor.cpp b/modules/openxr/editor/openxr_action_editor.cpp
index 4b188471a0..06d2e8dcc9 100644
--- a/modules/openxr/editor/openxr_action_editor.cpp
+++ b/modules/openxr/editor/openxr_action_editor.cpp
@@ -159,7 +159,7 @@ OpenXRActionEditor::OpenXRActionEditor(Ref<OpenXRAction> p_action) {
rem_action = memnew(Button);
rem_action->set_tooltip_text(TTR("Remove action"));
- rem_action->connect("pressed", callable_mp(this, &OpenXRActionEditor::_on_remove_action));
+ rem_action->connect(SceneStringName(pressed), callable_mp(this, &OpenXRActionEditor::_on_remove_action));
rem_action->set_flat(true);
add_child(rem_action);
}
diff --git a/modules/openxr/editor/openxr_action_map_editor.cpp b/modules/openxr/editor/openxr_action_map_editor.cpp
index 5dd737756a..62b4a427b9 100644
--- a/modules/openxr/editor/openxr_action_map_editor.cpp
+++ b/modules/openxr/editor/openxr_action_map_editor.cpp
@@ -402,13 +402,13 @@ OpenXRActionMapEditor::OpenXRActionMapEditor() {
add_action_set = memnew(Button);
add_action_set->set_text(TTR("Add Action Set"));
add_action_set->set_tooltip_text(TTR("Add an action set."));
- add_action_set->connect("pressed", callable_mp(this, &OpenXRActionMapEditor::_on_add_action_set));
+ add_action_set->connect(SceneStringName(pressed), callable_mp(this, &OpenXRActionMapEditor::_on_add_action_set));
top_hb->add_child(add_action_set);
add_interaction_profile = memnew(Button);
add_interaction_profile->set_text(TTR("Add profile"));
add_interaction_profile->set_tooltip_text(TTR("Add an interaction profile."));
- add_interaction_profile->connect("pressed", callable_mp(this, &OpenXRActionMapEditor::_on_add_interaction_profile));
+ add_interaction_profile->connect(SceneStringName(pressed), callable_mp(this, &OpenXRActionMapEditor::_on_add_interaction_profile));
top_hb->add_child(add_interaction_profile);
VSeparator *vseparator = memnew(VSeparator);
@@ -417,13 +417,13 @@ OpenXRActionMapEditor::OpenXRActionMapEditor() {
save_as = memnew(Button);
save_as->set_text(TTR("Save"));
save_as->set_tooltip_text(TTR("Save this OpenXR action map."));
- save_as->connect("pressed", callable_mp(this, &OpenXRActionMapEditor::_on_save_action_map));
+ save_as->connect(SceneStringName(pressed), callable_mp(this, &OpenXRActionMapEditor::_on_save_action_map));
top_hb->add_child(save_as);
_default = memnew(Button);
_default->set_text(TTR("Reset to Default"));
_default->set_tooltip_text(TTR("Reset to default OpenXR action map."));
- _default->connect("pressed", callable_mp(this, &OpenXRActionMapEditor::_on_reset_to_default_layout));
+ _default->connect(SceneStringName(pressed), callable_mp(this, &OpenXRActionMapEditor::_on_reset_to_default_layout));
top_hb->add_child(_default);
tabs = memnew(TabContainer);
diff --git a/modules/openxr/editor/openxr_action_set_editor.cpp b/modules/openxr/editor/openxr_action_set_editor.cpp
index 8b4a0e989c..5d9a3155fb 100644
--- a/modules/openxr/editor/openxr_action_set_editor.cpp
+++ b/modules/openxr/editor/openxr_action_set_editor.cpp
@@ -229,7 +229,7 @@ OpenXRActionSetEditor::OpenXRActionSetEditor(Ref<OpenXRActionMap> p_action_map,
fold_btn = memnew(Button);
fold_btn->set_v_size_flags(Control::SIZE_SHRINK_BEGIN);
- fold_btn->connect("pressed", callable_mp(this, &OpenXRActionSetEditor::_on_toggle_expand));
+ fold_btn->connect(SceneStringName(pressed), callable_mp(this, &OpenXRActionSetEditor::_on_toggle_expand));
fold_btn->set_flat(true);
panel_hb->add_child(fold_btn);
@@ -262,13 +262,13 @@ OpenXRActionSetEditor::OpenXRActionSetEditor(Ref<OpenXRActionMap> p_action_map,
add_action = memnew(Button);
add_action->set_tooltip_text(TTR("Add action."));
- add_action->connect("pressed", callable_mp(this, &OpenXRActionSetEditor::_on_add_action));
+ add_action->connect(SceneStringName(pressed), callable_mp(this, &OpenXRActionSetEditor::_on_add_action));
add_action->set_flat(true);
action_set_hb->add_child(add_action);
rem_action_set = memnew(Button);
rem_action_set->set_tooltip_text(TTR("Remove action set."));
- rem_action_set->connect("pressed", callable_mp(this, &OpenXRActionSetEditor::_on_remove_action_set));
+ rem_action_set->connect(SceneStringName(pressed), callable_mp(this, &OpenXRActionSetEditor::_on_remove_action_set));
rem_action_set->set_flat(true);
action_set_hb->add_child(rem_action_set);
diff --git a/modules/openxr/editor/openxr_interaction_profile_editor.cpp b/modules/openxr/editor/openxr_interaction_profile_editor.cpp
index da6a9eed70..ab36c0744e 100644
--- a/modules/openxr/editor/openxr_interaction_profile_editor.cpp
+++ b/modules/openxr/editor/openxr_interaction_profile_editor.cpp
@@ -222,7 +222,7 @@ void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, co
Button *path_add = memnew(Button);
path_add->set_icon(get_theme_icon(SNAME("Add"), EditorStringName(EditorIcons)));
path_add->set_flat(true);
- path_add->connect("pressed", callable_mp(this, &OpenXRInteractionProfileEditor::select_action_for).bind(String(p_io_path->openxr_path)));
+ 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);
if (interaction_profile.is_valid()) {
@@ -249,7 +249,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->connect("pressed", callable_mp((OpenXRInteractionProfileEditor *)this, &OpenXRInteractionProfileEditor::_on_remove_pressed).bind(action->get_name_with_set(), String(p_io_path->openxr_path)));
+ 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/editor/openxr_select_action_dialog.cpp b/modules/openxr/editor/openxr_select_action_dialog.cpp
index 8eec54be63..de0ab40f9e 100644
--- a/modules/openxr/editor/openxr_select_action_dialog.cpp
+++ b/modules/openxr/editor/openxr_select_action_dialog.cpp
@@ -97,7 +97,7 @@ void OpenXRSelectActionDialog::open() {
String action_name = action->get_name_with_set();
action_button->set_flat(true);
action_button->set_text(action->get_name() + ": " + action->get_localized_name());
- action_button->connect("pressed", callable_mp(this, &OpenXRSelectActionDialog::_on_select_action).bind(action_name));
+ action_button->connect(SceneStringName(pressed), callable_mp(this, &OpenXRSelectActionDialog::_on_select_action).bind(action_name));
action_hb->add_child(action_button);
action_buttons[action_name] = action_button->get_path();
diff --git a/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp b/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp
index 8fd66fac04..e6705d5c82 100644
--- a/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp
+++ b/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp
@@ -82,7 +82,7 @@ void OpenXRSelectInteractionProfileDialog::open(PackedStringArray p_do_not_inclu
Button *ip_button = memnew(Button);
ip_button->set_flat(true);
ip_button->set_text(OpenXRInteractionProfileMetadata::get_singleton()->get_profile(path)->display_name);
- ip_button->connect("pressed", callable_mp(this, &OpenXRSelectInteractionProfileDialog::_on_select_interaction_profile).bind(path));
+ ip_button->connect(SceneStringName(pressed), callable_mp(this, &OpenXRSelectInteractionProfileDialog::_on_select_interaction_profile).bind(path));
main_vb->add_child(ip_button);
ip_buttons[path] = ip_button->get_path();
diff --git a/modules/openxr/extensions/openxr_composition_layer_extension.cpp b/modules/openxr/extensions/openxr_composition_layer_extension.cpp
index 51f4a03d52..994b08af53 100644
--- a/modules/openxr/extensions/openxr_composition_layer_extension.cpp
+++ b/modules/openxr/extensions/openxr_composition_layer_extension.cpp
@@ -187,7 +187,7 @@ void OpenXRViewportCompositionLayerProvider::on_pre_render() {
XrCompositionLayerBaseHeader *OpenXRViewportCompositionLayerProvider::get_composition_layer() {
if (openxr_api == nullptr || composition_layer_extension == nullptr) {
- // OpenXR not initialised or we're in the editor?
+ // OpenXR not initialized or we're in the editor?
return nullptr;
}
@@ -209,6 +209,7 @@ XrCompositionLayerBaseHeader *OpenXRViewportCompositionLayerProvider::get_compos
switch (composition_layer->type) {
case XR_TYPE_COMPOSITION_LAYER_QUAD: {
XrCompositionLayerQuad *quad_layer = (XrCompositionLayerQuad *)composition_layer;
+ quad_layer->space = openxr_api->get_play_space();
quad_layer->subImage.swapchain = swapchain_info.get_swapchain();
quad_layer->subImage.imageArrayIndex = 0;
quad_layer->subImage.imageRect.offset.x = 0;
@@ -219,6 +220,7 @@ XrCompositionLayerBaseHeader *OpenXRViewportCompositionLayerProvider::get_compos
case XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR: {
XrCompositionLayerCylinderKHR *cylinder_layer = (XrCompositionLayerCylinderKHR *)composition_layer;
+ cylinder_layer->space = openxr_api->get_play_space();
cylinder_layer->subImage.swapchain = swapchain_info.get_swapchain();
cylinder_layer->subImage.imageArrayIndex = 0;
cylinder_layer->subImage.imageRect.offset.x = 0;
@@ -229,6 +231,7 @@ XrCompositionLayerBaseHeader *OpenXRViewportCompositionLayerProvider::get_compos
case XR_TYPE_COMPOSITION_LAYER_EQUIRECT2_KHR: {
XrCompositionLayerEquirect2KHR *equirect_layer = (XrCompositionLayerEquirect2KHR *)composition_layer;
+ equirect_layer->space = openxr_api->get_play_space();
equirect_layer->subImage.swapchain = swapchain_info.get_swapchain();
equirect_layer->subImage.imageArrayIndex = 0;
equirect_layer->subImage.imageRect.offset.x = 0;
@@ -260,7 +263,7 @@ XrCompositionLayerBaseHeader *OpenXRViewportCompositionLayerProvider::get_compos
bool OpenXRViewportCompositionLayerProvider::update_and_acquire_swapchain(bool p_static_image) {
if (openxr_api == nullptr || composition_layer_extension == nullptr) {
- // OpenXR not initialised or we're in the editor?
+ // OpenXR not initialized or we're in the editor?
return false;
}
if (!composition_layer_extension->is_available(composition_layer->type)) {
@@ -283,7 +286,7 @@ bool OpenXRViewportCompositionLayerProvider::update_and_acquire_swapchain(bool p
// Create our new swap chain
int64_t swapchain_format = openxr_api->get_color_swapchain_format();
- const uint32_t sample_count = 3;
+ const uint32_t sample_count = 1;
const uint32_t array_size = 1;
XrSwapchainCreateFlags create_flags = 0;
if (p_static_image) {
diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp
index 8731a36865..32512070d6 100644
--- a/modules/openxr/openxr_api.cpp
+++ b/modules/openxr/openxr_api.cpp
@@ -1335,8 +1335,8 @@ bool OpenXRAPI::on_state_synchronized() {
// Just in case, see if we already have active trackers...
List<RID> trackers;
tracker_owner.get_owned_list(&trackers);
- for (int i = 0; i < trackers.size(); i++) {
- tracker_check_profile(trackers[i]);
+ for (const RID &tracker : trackers) {
+ tracker_check_profile(tracker);
}
for (OpenXRExtensionWrapper *wrapper : registered_extension_wrappers) {
@@ -1963,8 +1963,8 @@ bool OpenXRAPI::poll_events() {
List<RID> trackers;
tracker_owner.get_owned_list(&trackers);
- for (int i = 0; i < trackers.size(); i++) {
- tracker_check_profile(trackers[i], event->session);
+ for (const RID &tracker : trackers) {
+ tracker_check_profile(tracker, event->session);
}
} break;
@@ -2302,7 +2302,7 @@ void OpenXRAPI::end_frame() {
};
result = xrEndFrame(session, &frame_end_info);
if (XR_FAILED(result)) {
- print_line("OpenXR: failed to end frame! [", get_error_string(result), "]");
+ print_line("OpenXR: rendering skipped and failed to end frame! [", get_error_string(result), "]");
return;
}
diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp
index b92d1edb90..fbbc61a91c 100644
--- a/modules/openxr/openxr_interface.cpp
+++ b/modules/openxr/openxr_interface.cpp
@@ -391,7 +391,7 @@ OpenXRInterface::Action *OpenXRInterface::create_action(ActionSet *p_action_set,
// we link our actions back to our trackers so we know which actions to check when we're processing our trackers
for (int i = 0; i < p_trackers.size(); i++) {
- if (p_trackers[i]->actions.find(action) == -1) {
+ if (!p_trackers[i]->actions.has(action)) {
p_trackers[i]->actions.push_back(action);
}
}
diff --git a/modules/openxr/scene/openxr_composition_layer.cpp b/modules/openxr/scene/openxr_composition_layer.cpp
index ce883b79b3..50cc7b9e7b 100644
--- a/modules/openxr/scene/openxr_composition_layer.cpp
+++ b/modules/openxr/scene/openxr_composition_layer.cpp
@@ -38,7 +38,14 @@
#include "scene/3d/xr_nodes.h"
#include "scene/main/viewport.h"
-HashSet<SubViewport *> OpenXRCompositionLayer::viewports_in_use;
+Vector<OpenXRCompositionLayer *> OpenXRCompositionLayer::composition_layer_nodes;
+
+static const char *HOLE_PUNCH_SHADER_CODE =
+ "shader_type spatial;\n"
+ "render_mode blend_mix, depth_draw_opaque, cull_back, shadow_to_opacity, shadows_disabled;\n"
+ "void fragment() {\n"
+ "\tALBEDO = vec3(0.0, 0.0, 0.0);\n"
+ "}\n";
OpenXRCompositionLayer::OpenXRCompositionLayer() {
openxr_api = OpenXRAPI::get_singleton();
@@ -66,9 +73,7 @@ OpenXRCompositionLayer::~OpenXRCompositionLayer() {
openxr_interface->disconnect("session_stopping", callable_mp(this, &OpenXRCompositionLayer::_on_openxr_session_stopping));
}
- if (layer_viewport) {
- viewports_in_use.erase(layer_viewport);
- }
+ composition_layer_nodes.erase(this);
if (openxr_layer_provider != nullptr) {
memdelete(openxr_layer_provider);
@@ -80,6 +85,9 @@ void OpenXRCompositionLayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_layer_viewport", "viewport"), &OpenXRCompositionLayer::set_layer_viewport);
ClassDB::bind_method(D_METHOD("get_layer_viewport"), &OpenXRCompositionLayer::get_layer_viewport);
+ ClassDB::bind_method(D_METHOD("set_enable_hole_punch", "enable"), &OpenXRCompositionLayer::set_enable_hole_punch);
+ ClassDB::bind_method(D_METHOD("get_enable_hole_punch"), &OpenXRCompositionLayer::get_enable_hole_punch);
+
ClassDB::bind_method(D_METHOD("set_sort_order", "order"), &OpenXRCompositionLayer::set_sort_order);
ClassDB::bind_method(D_METHOD("get_sort_order"), &OpenXRCompositionLayer::get_sort_order);
@@ -93,6 +101,16 @@ void OpenXRCompositionLayer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "layer_viewport", PROPERTY_HINT_NODE_TYPE, "SubViewport"), "set_layer_viewport", "get_layer_viewport");
ADD_PROPERTY(PropertyInfo(Variant::INT, "sort_order", PROPERTY_HINT_NONE, ""), "set_sort_order", "get_sort_order");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "alpha_blend", PROPERTY_HINT_NONE, ""), "set_alpha_blend", "get_alpha_blend");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enable_hole_punch", PROPERTY_HINT_NONE, ""), "set_enable_hole_punch", "get_enable_hole_punch");
+}
+
+bool OpenXRCompositionLayer::_should_use_fallback_node() {
+ if (Engine::get_singleton()->is_editor_hint()) {
+ return true;
+ } else if (openxr_session_running) {
+ return enable_hole_punch || !is_natively_supported();
+ }
+ return false;
}
void OpenXRCompositionLayer::_create_fallback_node() {
@@ -103,21 +121,27 @@ void OpenXRCompositionLayer::_create_fallback_node() {
should_update_fallback_mesh = true;
}
+void OpenXRCompositionLayer::_remove_fallback_node() {
+ ERR_FAIL_COND(fallback != nullptr);
+ remove_child(fallback);
+ fallback->queue_free();
+ fallback = nullptr;
+}
+
void OpenXRCompositionLayer::_on_openxr_session_begun() {
- if (!is_natively_supported()) {
- if (!fallback) {
- _create_fallback_node();
- }
- } else if (layer_viewport && is_visible() && is_inside_tree()) {
+ openxr_session_running = true;
+ if (layer_viewport && is_natively_supported() && is_visible() && is_inside_tree()) {
openxr_layer_provider->set_viewport(layer_viewport->get_viewport_rid(), layer_viewport->get_size());
}
+ if (!fallback && _should_use_fallback_node()) {
+ _create_fallback_node();
+ }
}
void OpenXRCompositionLayer::_on_openxr_session_stopping() {
- if (fallback && !Engine::get_singleton()->is_editor_hint()) {
- fallback->queue_free();
- remove_child(fallback);
- fallback = nullptr;
+ openxr_session_running = false;
+ if (fallback && !_should_use_fallback_node()) {
+ _remove_fallback_node();
} else {
openxr_layer_provider->set_viewport(RID(), Size2i());
}
@@ -127,22 +151,25 @@ void OpenXRCompositionLayer::update_fallback_mesh() {
should_update_fallback_mesh = true;
}
+bool OpenXRCompositionLayer::is_viewport_in_use(SubViewport *p_viewport) {
+ for (const OpenXRCompositionLayer *other_composition_layer : composition_layer_nodes) {
+ if (other_composition_layer != this && other_composition_layer->is_inside_tree() && other_composition_layer->get_layer_viewport() == p_viewport) {
+ return true;
+ }
+ }
+ return false;
+}
+
void OpenXRCompositionLayer::set_layer_viewport(SubViewport *p_viewport) {
if (layer_viewport == p_viewport) {
return;
}
- ERR_FAIL_COND_EDMSG(viewports_in_use.has(p_viewport), RTR("Cannot use the same SubViewport with multiple OpenXR composition layers. Clear it from its current layer first."));
-
- if (layer_viewport) {
- viewports_in_use.erase(layer_viewport);
- }
+ ERR_FAIL_COND_EDMSG(is_viewport_in_use(p_viewport), RTR("Cannot use the same SubViewport with multiple OpenXR composition layers. Clear it from its current layer first."));
layer_viewport = p_viewport;
if (layer_viewport) {
- viewports_in_use.insert(layer_viewport);
-
SubViewport::UpdateMode update_mode = layer_viewport->get_update_mode();
if (update_mode == SubViewport::UPDATE_WHEN_VISIBLE || update_mode == SubViewport::UPDATE_WHEN_PARENT_VISIBLE) {
WARN_PRINT_ONCE("OpenXR composition layers cannot use SubViewports with UPDATE_WHEN_VISIBLE or UPDATE_WHEN_PARENT_VISIBLE. Switching to UPDATE_ALWAYS.");
@@ -152,7 +179,7 @@ void OpenXRCompositionLayer::set_layer_viewport(SubViewport *p_viewport) {
if (fallback) {
_reset_fallback_material();
- } else if (openxr_api && openxr_api->is_running() && is_visible() && is_inside_tree()) {
+ } else if (openxr_session_running && is_visible() && is_inside_tree()) {
if (layer_viewport) {
openxr_layer_provider->set_viewport(layer_viewport->get_viewport_rid(), layer_viewport->get_size());
} else {
@@ -165,9 +192,33 @@ SubViewport *OpenXRCompositionLayer::get_layer_viewport() const {
return layer_viewport;
}
+void OpenXRCompositionLayer::set_enable_hole_punch(bool p_enable) {
+ if (enable_hole_punch == p_enable) {
+ return;
+ }
+
+ enable_hole_punch = p_enable;
+ if (_should_use_fallback_node()) {
+ if (fallback) {
+ _reset_fallback_material();
+ } else {
+ _create_fallback_node();
+ }
+ } else if (fallback) {
+ _remove_fallback_node();
+ }
+
+ update_configuration_warnings();
+}
+
+bool OpenXRCompositionLayer::get_enable_hole_punch() const {
+ return enable_hole_punch;
+}
+
void OpenXRCompositionLayer::set_sort_order(int p_order) {
if (openxr_layer_provider) {
openxr_layer_provider->set_sort_order(p_order);
+ update_configuration_warnings();
}
}
@@ -212,15 +263,28 @@ void OpenXRCompositionLayer::_reset_fallback_material() {
return;
}
- if (layer_viewport) {
+ if (enable_hole_punch && !Engine::get_singleton()->is_editor_hint() && is_natively_supported()) {
+ Ref<ShaderMaterial> material = fallback->get_surface_override_material(0);
+ if (material.is_null()) {
+ Ref<Shader> shader;
+ shader.instantiate();
+ shader->set_code(HOLE_PUNCH_SHADER_CODE);
+
+ material.instantiate();
+ material->set_shader(shader);
+
+ fallback->set_surface_override_material(0, material);
+ }
+ } else if (layer_viewport) {
Ref<StandardMaterial3D> material = fallback->get_surface_override_material(0);
if (material.is_null()) {
material.instantiate();
material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
- material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true);
material->set_local_to_scene(true);
fallback->set_surface_override_material(0, material);
}
+
+ material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, !enable_hole_punch);
material->set_transparency(get_alpha_blend() ? StandardMaterial3D::TRANSPARENCY_ALPHA : StandardMaterial3D::TRANSPARENCY_DISABLED);
Ref<ViewportTexture> texture = material->get_texture(StandardMaterial3D::TEXTURE_ALBEDO);
@@ -243,6 +307,8 @@ void OpenXRCompositionLayer::_reset_fallback_material() {
void OpenXRCompositionLayer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_POSTINITIALIZE: {
+ composition_layer_nodes.push_back(this);
+
if (openxr_layer_provider) {
for (OpenXRExtensionWrapper *extension : OpenXRAPI::get_registered_extension_wrappers()) {
extension_property_values.merge(extension->get_viewport_composition_layer_extension_property_defaults());
@@ -260,7 +326,7 @@ void OpenXRCompositionLayer::_notification(int p_what) {
}
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
- if (!fallback && openxr_api && openxr_api->is_running() && is_inside_tree()) {
+ if (!fallback && openxr_session_running && is_inside_tree()) {
if (layer_viewport && is_visible()) {
openxr_layer_provider->set_viewport(layer_viewport->get_viewport_rid(), layer_viewport->get_size());
} else {
@@ -277,7 +343,9 @@ void OpenXRCompositionLayer::_notification(int p_what) {
composition_layer_extension->register_viewport_composition_layer_provider(openxr_layer_provider);
}
- if (!fallback && layer_viewport && openxr_api && openxr_api->is_running() && is_visible()) {
+ if (is_viewport_in_use(layer_viewport)) {
+ set_layer_viewport(nullptr);
+ } else if (!fallback && layer_viewport && openxr_session_running && is_visible()) {
openxr_layer_provider->set_viewport(layer_viewport->get_viewport_rid(), layer_viewport->get_size());
}
} break;
@@ -286,12 +354,7 @@ void OpenXRCompositionLayer::_notification(int p_what) {
composition_layer_extension->unregister_viewport_composition_layer_provider(openxr_layer_provider);
}
- // When a node is removed in the editor, we need to clear the layer viewport, because otherwise
- // there will be issues with the tracking in viewports_in_use, since nodes deleted in the editor
- // aren't really deleted in order to support undo.
- if (Engine::get_singleton()->is_editor_hint() && layer_viewport) {
- set_layer_viewport(nullptr);
- } else if (!fallback) {
+ if (!fallback) {
// This will clean up existing resources.
openxr_layer_provider->set_viewport(RID(), Size2i());
}
@@ -347,5 +410,9 @@ PackedStringArray OpenXRCompositionLayer::get_configuration_warnings() const {
warnings.push_back(RTR("OpenXR composition layers must have orthonormalized transforms (ie. no scale or shearing)."));
}
+ if (enable_hole_punch && get_sort_order() >= 0) {
+ warnings.push_back(RTR("Hole punching won't work as expected unless the sort order is less than zero."));
+ }
+
return warnings;
}
diff --git a/modules/openxr/scene/openxr_composition_layer.h b/modules/openxr/scene/openxr_composition_layer.h
index 9f064379d3..6792364295 100644
--- a/modules/openxr/scene/openxr_composition_layer.h
+++ b/modules/openxr/scene/openxr_composition_layer.h
@@ -46,13 +46,17 @@ class OpenXRCompositionLayer : public Node3D {
GDCLASS(OpenXRCompositionLayer, Node3D);
SubViewport *layer_viewport = nullptr;
+ bool enable_hole_punch = false;
MeshInstance3D *fallback = nullptr;
bool should_update_fallback_mesh = false;
+ bool openxr_session_running = false;
Dictionary extension_property_values;
+ bool _should_use_fallback_node();
void _create_fallback_node();
void _reset_fallback_material();
+ void _remove_fallback_node();
protected:
OpenXRAPI *openxr_api = nullptr;
@@ -73,12 +77,16 @@ protected:
void update_fallback_mesh();
- static HashSet<SubViewport *> viewports_in_use;
+ static Vector<OpenXRCompositionLayer *> composition_layer_nodes;
+ bool is_viewport_in_use(SubViewport *p_viewport);
public:
void set_layer_viewport(SubViewport *p_viewport);
SubViewport *get_layer_viewport() const;
+ void set_enable_hole_punch(bool p_enable);
+ bool get_enable_hole_punch() const;
+
void set_sort_order(int p_order);
int get_sort_order() const;
diff --git a/modules/openxr/scene/openxr_composition_layer_cylinder.cpp b/modules/openxr/scene/openxr_composition_layer_cylinder.cpp
index ae5a8da5f3..728ba71006 100644
--- a/modules/openxr/scene/openxr_composition_layer_cylinder.cpp
+++ b/modules/openxr/scene/openxr_composition_layer_cylinder.cpp
@@ -76,13 +76,6 @@ void OpenXRCompositionLayerCylinder::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "fallback_segments", PROPERTY_HINT_NONE, ""), "set_fallback_segments", "get_fallback_segments");
}
-void OpenXRCompositionLayerCylinder::_on_openxr_session_begun() {
- OpenXRCompositionLayer::_on_openxr_session_begun();
- if (openxr_api) {
- composition_layer.space = openxr_api->get_play_space();
- }
-}
-
Ref<Mesh> OpenXRCompositionLayerCylinder::_create_fallback_mesh() {
Ref<ArrayMesh> mesh;
mesh.instantiate();
diff --git a/modules/openxr/scene/openxr_composition_layer_cylinder.h b/modules/openxr/scene/openxr_composition_layer_cylinder.h
index aed0fabd78..bb1d242267 100644
--- a/modules/openxr/scene/openxr_composition_layer_cylinder.h
+++ b/modules/openxr/scene/openxr_composition_layer_cylinder.h
@@ -50,7 +50,6 @@ protected:
void _notification(int p_what);
- virtual void _on_openxr_session_begun() override;
virtual Ref<Mesh> _create_fallback_mesh() override;
public:
diff --git a/modules/openxr/scene/openxr_composition_layer_equirect.cpp b/modules/openxr/scene/openxr_composition_layer_equirect.cpp
index d67e71443c..14cfea8da6 100644
--- a/modules/openxr/scene/openxr_composition_layer_equirect.cpp
+++ b/modules/openxr/scene/openxr_composition_layer_equirect.cpp
@@ -81,13 +81,6 @@ void OpenXRCompositionLayerEquirect::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "fallback_segments", PROPERTY_HINT_NONE, ""), "set_fallback_segments", "get_fallback_segments");
}
-void OpenXRCompositionLayerEquirect::_on_openxr_session_begun() {
- OpenXRCompositionLayer::_on_openxr_session_begun();
- if (openxr_api) {
- composition_layer.space = openxr_api->get_play_space();
- }
-}
-
Ref<Mesh> OpenXRCompositionLayerEquirect::_create_fallback_mesh() {
Ref<ArrayMesh> mesh;
mesh.instantiate();
diff --git a/modules/openxr/scene/openxr_composition_layer_equirect.h b/modules/openxr/scene/openxr_composition_layer_equirect.h
index 7a002a48dc..66f8b0a91c 100644
--- a/modules/openxr/scene/openxr_composition_layer_equirect.h
+++ b/modules/openxr/scene/openxr_composition_layer_equirect.h
@@ -51,7 +51,6 @@ protected:
void _notification(int p_what);
- virtual void _on_openxr_session_begun() override;
virtual Ref<Mesh> _create_fallback_mesh() override;
public:
diff --git a/modules/openxr/scene/openxr_composition_layer_quad.cpp b/modules/openxr/scene/openxr_composition_layer_quad.cpp
index 17d57851e4..8c5b8ec26b 100644
--- a/modules/openxr/scene/openxr_composition_layer_quad.cpp
+++ b/modules/openxr/scene/openxr_composition_layer_quad.cpp
@@ -62,13 +62,6 @@ void OpenXRCompositionLayerQuad::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "quad_size", PROPERTY_HINT_NONE, ""), "set_quad_size", "get_quad_size");
}
-void OpenXRCompositionLayerQuad::_on_openxr_session_begun() {
- OpenXRCompositionLayer::_on_openxr_session_begun();
- if (openxr_api) {
- composition_layer.space = openxr_api->get_play_space();
- }
-}
-
Ref<Mesh> OpenXRCompositionLayerQuad::_create_fallback_mesh() {
Ref<QuadMesh> mesh;
mesh.instantiate();
diff --git a/modules/openxr/scene/openxr_composition_layer_quad.h b/modules/openxr/scene/openxr_composition_layer_quad.h
index d88b596984..21bb9b2d85 100644
--- a/modules/openxr/scene/openxr_composition_layer_quad.h
+++ b/modules/openxr/scene/openxr_composition_layer_quad.h
@@ -47,7 +47,6 @@ protected:
void _notification(int p_what);
- virtual void _on_openxr_session_begun() override;
virtual Ref<Mesh> _create_fallback_mesh() override;
public: