Merge pull request #90237 from dsnopek/openxr-composition-layers-extension-properties
Allow OpenXR extensions to add properties to the OpenXRCompositionLayer node
This commit is contained in:
commit
59cfa0ef75
|
@ -46,6 +46,18 @@
|
|||
Returns a [PackedStringArray] of positional tracker names that are used within the extension wrapper.
|
||||
</description>
|
||||
</method>
|
||||
<method name="_get_viewport_composition_layer_extension_properties" qualifiers="virtual">
|
||||
<return type="Dictionary[]" />
|
||||
<description>
|
||||
Gets an array of [Dictionary]s that represent properties, just like [method Object._get_property_list], that will be added to [OpenXRCompositionLayer] nodes.
|
||||
</description>
|
||||
</method>
|
||||
<method name="_get_viewport_composition_layer_extension_property_defaults" qualifiers="virtual">
|
||||
<return type="Dictionary" />
|
||||
<description>
|
||||
Gets a [Dictionary] containing the default values for the properties returned by [method _get_viewport_composition_layer_extension_properties].
|
||||
</description>
|
||||
</method>
|
||||
<method name="_on_before_instance_created" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<description>
|
||||
|
@ -152,6 +164,14 @@
|
|||
Called when the OpenXR session state is changed to visible. This means OpenXR is now ready to receive frames.
|
||||
</description>
|
||||
</method>
|
||||
<method name="_on_viewport_composition_layer_destroyed" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<param index="0" name="layer" type="const void*" />
|
||||
<description>
|
||||
Called when a composition layer created via [OpenXRCompositionLayer] is destroyed.
|
||||
[param layer] is a pointer to an [code]XrCompositionLayerBaseHeader[/code] struct.
|
||||
</description>
|
||||
</method>
|
||||
<method name="_set_hand_joint_locations_and_get_next_pointer" qualifiers="virtual">
|
||||
<return type="int" />
|
||||
<param index="0" name="hand_index" type="int" />
|
||||
|
@ -188,6 +208,17 @@
|
|||
Adds additional data structures when interogating OpenXR system abilities.
|
||||
</description>
|
||||
</method>
|
||||
<method name="_set_viewport_composition_layer_and_get_next_pointer" qualifiers="virtual">
|
||||
<return type="int" />
|
||||
<param index="0" name="layer" type="const void*" />
|
||||
<param index="1" name="property_values" type="Dictionary" />
|
||||
<param index="2" name="next_pointer" type="void*" />
|
||||
<description>
|
||||
Adds additional data structures to composition layers created by [OpenXRCompositionLayer].
|
||||
[param property_values] contains the values of the properties returned by [method _get_viewport_composition_layer_extension_properties].
|
||||
[param layer] is a pointer to an [code]XrCompositionLayerBaseHeader[/code] struct.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_openxr_api">
|
||||
<return type="OpenXRAPIExtension" />
|
||||
<description>
|
||||
|
|
|
@ -86,11 +86,11 @@ int OpenXRCompositionLayerExtension::get_composition_layer_order(int p_index) {
|
|||
return composition_layers[p_index]->get_sort_order();
|
||||
}
|
||||
|
||||
void OpenXRCompositionLayerExtension::register_composition_layer_provider(OpenXRViewportCompositionLayerProvider *p_composition_layer) {
|
||||
void OpenXRCompositionLayerExtension::register_viewport_composition_layer_provider(OpenXRViewportCompositionLayerProvider *p_composition_layer) {
|
||||
composition_layers.push_back(p_composition_layer);
|
||||
}
|
||||
|
||||
void OpenXRCompositionLayerExtension::unregister_composition_layer_provider(OpenXRViewportCompositionLayerProvider *p_composition_layer) {
|
||||
void OpenXRCompositionLayerExtension::unregister_viewport_composition_layer_provider(OpenXRViewportCompositionLayerProvider *p_composition_layer) {
|
||||
composition_layers.erase(p_composition_layer);
|
||||
}
|
||||
|
||||
|
@ -123,6 +123,10 @@ OpenXRViewportCompositionLayerProvider::OpenXRViewportCompositionLayerProvider(X
|
|||
}
|
||||
|
||||
OpenXRViewportCompositionLayerProvider::~OpenXRViewportCompositionLayerProvider() {
|
||||
for (OpenXRExtensionWrapper *extension : OpenXRAPI::get_registered_extension_wrappers()) {
|
||||
extension->on_viewport_composition_layer_destroyed(composition_layer);
|
||||
}
|
||||
|
||||
// This will reset the viewport and free the swapchain too.
|
||||
set_viewport(RID(), Size2i());
|
||||
}
|
||||
|
@ -159,6 +163,11 @@ void OpenXRViewportCompositionLayerProvider::set_viewport(RID p_viewport, Size2i
|
|||
}
|
||||
}
|
||||
|
||||
void OpenXRViewportCompositionLayerProvider::set_extension_property_values(const Dictionary &p_extension_property_values) {
|
||||
extension_property_values = p_extension_property_values;
|
||||
extension_property_values_changed = true;
|
||||
}
|
||||
|
||||
void OpenXRViewportCompositionLayerProvider::on_pre_render() {
|
||||
RenderingServer *rs = RenderingServer::get_singleton();
|
||||
ERR_FAIL_NULL(rs);
|
||||
|
@ -233,6 +242,19 @@ XrCompositionLayerBaseHeader *OpenXRViewportCompositionLayerProvider::get_compos
|
|||
} break;
|
||||
}
|
||||
|
||||
if (extension_property_values_changed) {
|
||||
extension_property_values_changed = false;
|
||||
|
||||
void *next_pointer = nullptr;
|
||||
for (OpenXRExtensionWrapper *extension : OpenXRAPI::get_registered_extension_wrappers()) {
|
||||
void *np = extension->set_viewport_composition_layer_and_get_next_pointer(composition_layer, extension_property_values, next_pointer);
|
||||
if (np) {
|
||||
next_pointer = np;
|
||||
}
|
||||
}
|
||||
composition_layer->next = next_pointer;
|
||||
}
|
||||
|
||||
return composition_layer;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,8 +57,8 @@ public:
|
|||
virtual XrCompositionLayerBaseHeader *get_composition_layer(int p_index) override;
|
||||
virtual int get_composition_layer_order(int p_index) override;
|
||||
|
||||
void register_composition_layer_provider(OpenXRViewportCompositionLayerProvider *p_composition_layer);
|
||||
void unregister_composition_layer_provider(OpenXRViewportCompositionLayerProvider *p_composition_layer);
|
||||
void register_viewport_composition_layer_provider(OpenXRViewportCompositionLayerProvider *p_composition_layer);
|
||||
void unregister_viewport_composition_layer_provider(OpenXRViewportCompositionLayerProvider *p_composition_layer);
|
||||
|
||||
bool is_available(XrStructureType p_which);
|
||||
|
||||
|
@ -75,6 +75,8 @@ class OpenXRViewportCompositionLayerProvider {
|
|||
XrCompositionLayerBaseHeader *composition_layer = nullptr;
|
||||
int sort_order = 1;
|
||||
bool alpha_blend = false;
|
||||
Dictionary extension_property_values;
|
||||
bool extension_property_values_changed = true;
|
||||
|
||||
RID viewport;
|
||||
Size2i viewport_size;
|
||||
|
@ -102,6 +104,8 @@ public:
|
|||
void set_viewport(RID p_viewport, Size2i p_size);
|
||||
RID get_viewport() const { return viewport; }
|
||||
|
||||
void set_extension_property_values(const Dictionary &p_property_values);
|
||||
|
||||
void on_pre_render();
|
||||
XrCompositionLayerBaseHeader *get_composition_layer();
|
||||
|
||||
|
|
|
@ -96,6 +96,11 @@ public:
|
|||
virtual void on_state_loss_pending() {} // `on_state_loss_pending` is called when the OpenXR session state is changed to loss pending.
|
||||
virtual void on_state_exiting() {} // `on_state_exiting` is called when the OpenXR session state is changed to exiting.
|
||||
|
||||
virtual void *set_viewport_composition_layer_and_get_next_pointer(const XrCompositionLayerBaseHeader *p_layer, Dictionary p_property_values, void *p_next_pointer) { return p_next_pointer; } // Add additional data structures to composition layers created via OpenXRCompositionLayer.
|
||||
virtual void on_viewport_composition_layer_destroyed(const XrCompositionLayerBaseHeader *p_layer) {} // `on_viewport_composition_layer_destroyed` is called when a composition layer created via OpenXRCompositionLayer is destroyed.
|
||||
virtual void get_viewport_composition_layer_extension_properties(List<PropertyInfo> *p_property_list) {} // Get additional property definitions for OpenXRCompositionLayer.
|
||||
virtual Dictionary get_viewport_composition_layer_extension_property_defaults() { return Dictionary(); } // Get the default values for the additional property definitions for OpenXRCompositionLayer.
|
||||
|
||||
// `on_event_polled` is called when there is an OpenXR event to process.
|
||||
// Should return true if the event was handled, false otherwise.
|
||||
virtual bool on_event_polled(const XrEventDataBuffer &event) {
|
||||
|
|
|
@ -60,6 +60,10 @@ void OpenXRExtensionWrapperExtension::_bind_methods() {
|
|||
GDVIRTUAL_BIND(_on_state_loss_pending);
|
||||
GDVIRTUAL_BIND(_on_state_exiting);
|
||||
GDVIRTUAL_BIND(_on_event_polled, "event");
|
||||
GDVIRTUAL_BIND(_set_viewport_composition_layer_and_get_next_pointer, "layer", "property_values", "next_pointer");
|
||||
GDVIRTUAL_BIND(_get_viewport_composition_layer_extension_properties, "layer");
|
||||
GDVIRTUAL_BIND(_get_viewport_composition_layer_extension_property_defaults, "layer");
|
||||
GDVIRTUAL_BIND(_on_viewport_composition_layer_destroyed, "layer");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_openxr_api"), &OpenXRExtensionWrapperExtension::get_openxr_api);
|
||||
ClassDB::bind_method(D_METHOD("register_extension_wrapper"), &OpenXRExtensionWrapperExtension::register_extension_wrapper);
|
||||
|
@ -240,6 +244,36 @@ bool OpenXRExtensionWrapperExtension::on_event_polled(const XrEventDataBuffer &p
|
|||
return false;
|
||||
}
|
||||
|
||||
void *OpenXRExtensionWrapperExtension::set_viewport_composition_layer_and_get_next_pointer(const XrCompositionLayerBaseHeader *p_layer, Dictionary p_property_values, void *p_next_pointer) {
|
||||
uint64_t pointer = 0;
|
||||
|
||||
if (GDVIRTUAL_CALL(_set_viewport_composition_layer_and_get_next_pointer, GDExtensionConstPtr<void>(p_layer), p_property_values, GDExtensionPtr<void>(p_next_pointer), pointer)) {
|
||||
return reinterpret_cast<void *>(pointer);
|
||||
}
|
||||
|
||||
return p_next_pointer;
|
||||
}
|
||||
|
||||
void OpenXRExtensionWrapperExtension::on_viewport_composition_layer_destroyed(const XrCompositionLayerBaseHeader *p_layer) {
|
||||
GDVIRTUAL_CALL(_on_viewport_composition_layer_destroyed, GDExtensionConstPtr<void>(p_layer));
|
||||
}
|
||||
|
||||
void OpenXRExtensionWrapperExtension::get_viewport_composition_layer_extension_properties(List<PropertyInfo> *p_property_list) {
|
||||
TypedArray<Dictionary> properties;
|
||||
|
||||
if (GDVIRTUAL_CALL(_get_viewport_composition_layer_extension_properties, properties)) {
|
||||
for (int i = 0; i < properties.size(); i++) {
|
||||
p_property_list->push_back(PropertyInfo::from_dict(properties[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary OpenXRExtensionWrapperExtension::get_viewport_composition_layer_extension_property_defaults() {
|
||||
Dictionary property_defaults;
|
||||
GDVIRTUAL_CALL(_get_viewport_composition_layer_extension_property_defaults, property_defaults);
|
||||
return property_defaults;
|
||||
}
|
||||
|
||||
Ref<OpenXRAPIExtension> OpenXRExtensionWrapperExtension::get_openxr_api() {
|
||||
return openxr_api;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "core/os/os.h"
|
||||
#include "core/os/thread_safe.h"
|
||||
#include "core/variant/native_ptr.h"
|
||||
#include "core/variant/typed_array.h"
|
||||
|
||||
class OpenXRExtensionWrapperExtension : public Object, public OpenXRExtensionWrapper, public OpenXRCompositionLayerProvider {
|
||||
GDCLASS(OpenXRExtensionWrapperExtension, Object);
|
||||
|
@ -59,6 +60,7 @@ public:
|
|||
virtual void *set_session_create_and_get_next_pointer(void *p_next_pointer) override;
|
||||
virtual void *set_swapchain_create_info_and_get_next_pointer(void *p_next_pointer) override;
|
||||
virtual void *set_hand_joint_locations_and_get_next_pointer(int p_hand_index, void *p_next_pointer) override;
|
||||
|
||||
virtual int get_composition_layer_count() override;
|
||||
virtual XrCompositionLayerBaseHeader *get_composition_layer(int p_index) override;
|
||||
virtual int get_composition_layer_order(int p_index) override;
|
||||
|
@ -117,6 +119,16 @@ public:
|
|||
|
||||
GDVIRTUAL1R(bool, _on_event_polled, GDExtensionConstPtr<void>);
|
||||
|
||||
virtual void *set_viewport_composition_layer_and_get_next_pointer(const XrCompositionLayerBaseHeader *p_layer, Dictionary p_property_values, void *p_next_pointer) override;
|
||||
virtual void on_viewport_composition_layer_destroyed(const XrCompositionLayerBaseHeader *p_layer) override;
|
||||
virtual void get_viewport_composition_layer_extension_properties(List<PropertyInfo> *p_property_list) override;
|
||||
virtual Dictionary get_viewport_composition_layer_extension_property_defaults() override;
|
||||
|
||||
GDVIRTUAL3R(uint64_t, _set_viewport_composition_layer_and_get_next_pointer, GDExtensionConstPtr<void>, Dictionary, GDExtensionPtr<void>);
|
||||
GDVIRTUAL1(_on_viewport_composition_layer_destroyed, GDExtensionConstPtr<void>);
|
||||
GDVIRTUAL0R(TypedArray<Dictionary>, _get_viewport_composition_layer_extension_properties);
|
||||
GDVIRTUAL0R(Dictionary, _get_viewport_composition_layer_extension_property_defaults);
|
||||
|
||||
Ref<OpenXRAPIExtension> get_openxr_api();
|
||||
|
||||
void register_extension_wrapper();
|
||||
|
|
|
@ -236,6 +236,14 @@ void OpenXRCompositionLayer::_reset_fallback_material() {
|
|||
|
||||
void OpenXRCompositionLayer::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_POSTINITIALIZE: {
|
||||
if (openxr_layer_provider) {
|
||||
for (OpenXRExtensionWrapper *extension : OpenXRAPI::get_registered_extension_wrappers()) {
|
||||
extension_property_values.merge(extension->get_viewport_composition_layer_extension_property_defaults());
|
||||
}
|
||||
openxr_layer_provider->set_extension_property_values(extension_property_values);
|
||||
}
|
||||
} break;
|
||||
case NOTIFICATION_INTERNAL_PROCESS: {
|
||||
if (fallback) {
|
||||
if (should_update_fallback_mesh) {
|
||||
|
@ -260,7 +268,7 @@ void OpenXRCompositionLayer::_notification(int p_what) {
|
|||
} break;
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
if (composition_layer_extension) {
|
||||
composition_layer_extension->register_composition_layer_provider(openxr_layer_provider);
|
||||
composition_layer_extension->register_viewport_composition_layer_provider(openxr_layer_provider);
|
||||
}
|
||||
|
||||
if (!fallback && layer_viewport && openxr_api && openxr_api->is_running() && is_visible()) {
|
||||
|
@ -269,7 +277,7 @@ void OpenXRCompositionLayer::_notification(int p_what) {
|
|||
} break;
|
||||
case NOTIFICATION_EXIT_TREE: {
|
||||
if (composition_layer_extension) {
|
||||
composition_layer_extension->unregister_composition_layer_provider(openxr_layer_provider);
|
||||
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
|
||||
|
@ -285,6 +293,40 @@ void OpenXRCompositionLayer::_notification(int p_what) {
|
|||
}
|
||||
}
|
||||
|
||||
void OpenXRCompositionLayer::_get_property_list(List<PropertyInfo> *p_property_list) const {
|
||||
List<PropertyInfo> extension_properties;
|
||||
for (OpenXRExtensionWrapper *extension : OpenXRAPI::get_registered_extension_wrappers()) {
|
||||
extension->get_viewport_composition_layer_extension_properties(&extension_properties);
|
||||
}
|
||||
|
||||
for (const PropertyInfo &pinfo : extension_properties) {
|
||||
StringName prop_name = pinfo.name;
|
||||
if (!String(prop_name).contains("/")) {
|
||||
WARN_PRINT_ONCE(vformat("Discarding OpenXRCompositionLayer property name '%s' from extension because it doesn't contain a '/'."));
|
||||
continue;
|
||||
}
|
||||
p_property_list->push_back(pinfo);
|
||||
}
|
||||
}
|
||||
|
||||
bool OpenXRCompositionLayer::_get(const StringName &p_property, Variant &r_value) const {
|
||||
if (extension_property_values.has(p_property)) {
|
||||
r_value = extension_property_values[p_property];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OpenXRCompositionLayer::_set(const StringName &p_property, const Variant &p_value) {
|
||||
extension_property_values[p_property] = p_value;
|
||||
|
||||
if (openxr_layer_provider) {
|
||||
openxr_layer_provider->set_extension_property_values(extension_property_values);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
PackedStringArray OpenXRCompositionLayer::get_configuration_warnings() const {
|
||||
PackedStringArray warnings = Node3D::get_configuration_warnings();
|
||||
|
||||
|
|
|
@ -49,6 +49,8 @@ class OpenXRCompositionLayer : public Node3D {
|
|||
MeshInstance3D *fallback = nullptr;
|
||||
bool should_update_fallback_mesh = false;
|
||||
|
||||
Dictionary extension_property_values;
|
||||
|
||||
void _create_fallback_node();
|
||||
void _reset_fallback_material();
|
||||
|
||||
|
@ -60,6 +62,9 @@ protected:
|
|||
static void _bind_methods();
|
||||
|
||||
void _notification(int p_what);
|
||||
void _get_property_list(List<PropertyInfo> *p_property_list) const;
|
||||
bool _get(const StringName &p_property, Variant &r_value) const;
|
||||
bool _set(const StringName &p_property, const Variant &p_value);
|
||||
|
||||
virtual void _on_openxr_session_begun();
|
||||
virtual void _on_openxr_session_stopping();
|
||||
|
|
Loading…
Reference in New Issue