Skip to content

Commit

Permalink
OpenXR: Add support for binding modifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
BastiaanOlij committed Sep 18, 2024
1 parent 660ba05 commit 092e77e
Show file tree
Hide file tree
Showing 12 changed files with 453 additions and 5 deletions.
4 changes: 4 additions & 0 deletions main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2561,6 +2561,10 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
GLOBAL_DEF_RST_BASIC("xr/openxr/extensions/hand_interaction_profile", false);
GLOBAL_DEF_BASIC("xr/openxr/extensions/eye_gaze_interaction", false);

// OpenXR Binding modifier settings
GLOBAL_DEF_BASIC("xr/openxr/binding_modifiers/analog_threshold", false);
GLOBAL_DEF_BASIC("xr/openxr/binding_modifiers/dpad_binding", false);

#ifdef TOOLS_ENABLED
// Disabled for now, using XR inside of the editor we'll be working on during the coming months.

Expand Down
34 changes: 34 additions & 0 deletions modules/openxr/action_map/openxr_binding_modifier.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**************************************************************************/
/* openxr_binding_modifier.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#include "openxr_binding_modifier.h"

void OpenXRBindingModifier::_bind_methods() {
}
50 changes: 50 additions & 0 deletions modules/openxr/action_map/openxr_binding_modifier.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**************************************************************************/
/* openxr_binding_modifier.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#ifndef OPENXR_BINDING_MODIFIER_H
#define OPENXR_BINDING_MODIFIER_H

#include "core/io/resource.h"

#include <openxr/openxr.h>

class OpenXRBindingModifier : public Resource {
GDCLASS(OpenXRBindingModifier, Resource);

private:
protected:
static void _bind_methods();

public:
virtual int get_binding_modification_struct_size() const = 0; // Return the size of the struct returned by get_binding_modification
virtual const XrBindingModificationBaseHeaderKHR *get_binding_modification() = 0; // Return the binding modifier struct used when calling xrSuggestInteractionProfileBindings
};

#endif // OPENXR_BINDING_MODIFIER_H
25 changes: 25 additions & 0 deletions modules/openxr/action_map/openxr_interaction_profile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,12 @@ void OpenXRInteractionProfile::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bindings", "bindings"), &OpenXRInteractionProfile::set_bindings);
ClassDB::bind_method(D_METHOD("get_bindings"), &OpenXRInteractionProfile::get_bindings);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "bindings", PROPERTY_HINT_RESOURCE_TYPE, "OpenXRIPBinding", PROPERTY_USAGE_NO_EDITOR), "set_bindings", "get_bindings");

ClassDB::bind_method(D_METHOD("get_binding_modifier_count"), &OpenXRInteractionProfile::get_binding_modifier_count);
ClassDB::bind_method(D_METHOD("get_binding_modifier", "index"), &OpenXRInteractionProfile::get_binding_modifier);
ClassDB::bind_method(D_METHOD("set_binding_modifiers", "binding_modifiers"), &OpenXRInteractionProfile::set_binding_modifiers);
ClassDB::bind_method(D_METHOD("get_binding_modifiers"), &OpenXRInteractionProfile::get_binding_modifiers);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "binding_modifiers", PROPERTY_HINT_RESOURCE_TYPE, "OpenXRBindingModifier", PROPERTY_USAGE_NO_EDITOR), "set_binding_modifiers", "get_binding_modifiers");
}

Ref<OpenXRInteractionProfile> OpenXRInteractionProfile::new_profile(const char *p_input_profile_path) {
Expand Down Expand Up @@ -218,6 +224,25 @@ bool OpenXRInteractionProfile::has_binding_for_action(const Ref<OpenXRAction> p_
return false;
}

int OpenXRInteractionProfile::get_binding_modifier_count() const {
return binding_modifiers.size();
}

Ref<OpenXRBindingModifier> OpenXRInteractionProfile::get_binding_modifier(int p_index) const {
ERR_FAIL_INDEX_V(p_index, binding_modifiers.size(), nullptr);

return binding_modifiers[p_index];
}

void OpenXRInteractionProfile::set_binding_modifiers(Array p_binding_modifiers) {
binding_modifiers = p_binding_modifiers;
emit_changed();
}

Array OpenXRInteractionProfile::get_binding_modifiers() const {
return binding_modifiers;
}

OpenXRInteractionProfile::~OpenXRInteractionProfile() {
bindings.clear();
}
7 changes: 7 additions & 0 deletions modules/openxr/action_map/openxr_interaction_profile.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#define OPENXR_INTERACTION_PROFILE_H

#include "openxr_action.h"
#include "openxr_binding_modifier.h"
#include "openxr_interaction_profile_metadata.h"

#include "core/io/resource.h"
Expand Down Expand Up @@ -73,6 +74,7 @@ class OpenXRInteractionProfile : public Resource {
private:
String interaction_profile_path;
Array bindings;
Array binding_modifiers;

protected:
static void _bind_methods();
Expand All @@ -96,6 +98,11 @@ class OpenXRInteractionProfile : public Resource {
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

int get_binding_modifier_count() const; // Retrieve the number of binding modifiers in this profile path
Ref<OpenXRBindingModifier> get_binding_modifier(int p_index) const;
void set_binding_modifiers(Array p_bindings); // Set the binding modifiers (for loading from a resource)
Array get_binding_modifiers() const; // Get the binding modifiers (for saving to a resource)

~OpenXRInteractionProfile();
};

Expand Down
45 changes: 45 additions & 0 deletions modules/openxr/extensions/openxr_dpad_binding_extension.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**************************************************************************/
/* openxr_dpad_binding_extension.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#include "openxr_dpad_binding_extension.h"

HashMap<String, bool *> OpenXRDPadBindingExtension::get_requested_extensions() {
HashMap<String, bool *> request_extensions;

// Note, we're dependent on the binding modifier extension, this may be requested by multiple extension wrappers.
request_extensions[XR_KHR_BINDING_MODIFICATION_EXTENSION_NAME] = &binding_modifier_ext;
request_extensions[XR_EXT_DPAD_BINDING_EXTENSION_NAME] = &dpad_binding_ext;

return request_extensions;
}

bool OpenXRDPadBindingExtension::is_available() {
return binding_modifier_ext && dpad_binding_ext;
}
48 changes: 48 additions & 0 deletions modules/openxr/extensions/openxr_dpad_binding_extension.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**************************************************************************/
/* openxr_dpad_binding_extension.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#ifndef OPENXR_DPAD_BINDING_EXTENSION_H
#define OPENXR_DPAD_BINDING_EXTENSION_H

#include "../util.h"
#include "openxr_extension_wrapper.h"

class OpenXRDPadBindingExtension : public OpenXRExtensionWrapper {
public:
virtual HashMap<String, bool *> get_requested_extensions() override;

bool is_available();

private:
bool binding_modifier_ext = false;
bool dpad_binding_ext = false;
};

#endif // OPENXR_DPAD_BINDING_EXTENSION_H
101 changes: 101 additions & 0 deletions modules/openxr/extensions/openxr_valve_analog_threshold_extension.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/**************************************************************************/
/* openxr_valve_analog_threshold_extension.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#include "openxr_valve_analog_threshold_extension.h"

///////////////////////////////////////////////////////////////////////////////////////////////////
// OpenXRValveAnalogThresholdExtension

OpenXRValveAnalogThresholdExtension *OpenXRValveAnalogThresholdExtension::singleton = nullptr;

OpenXRValveAnalogThresholdExtension *OpenXRValveAnalogThresholdExtension::get_singleton() {
return singleton;
}

OpenXRValveAnalogThresholdExtension::OpenXRValveAnalogThresholdExtension() {
singleton = this;
}

OpenXRValveAnalogThresholdExtension::~OpenXRValveAnalogThresholdExtension() {
singleton = nullptr;
}

HashMap<String, bool *> OpenXRValveAnalogThresholdExtension::get_requested_extensions() {
HashMap<String, bool *> request_extensions;

// Note, we're dependent on the binding modifier extension, this may be requested by multiple extension wrappers.
request_extensions[XR_KHR_BINDING_MODIFICATION_EXTENSION_NAME] = &binding_modifier_ext;
request_extensions[XR_VALVE_ANALOG_THRESHOLD_EXTENSION_NAME] = &threshold_ext;

return request_extensions;
}

bool OpenXRValveAnalogThresholdExtension::is_available() {
return binding_modifier_ext && threshold_ext;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// OpenXRAnalogThresholdModifier

void OpenXRAnalogThresholdModifier::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_action", "action"), &OpenXRAnalogThresholdModifier::set_action);
ClassDB::bind_method(D_METHOD("get_action"), &OpenXRAnalogThresholdModifier::get_action);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "action", PROPERTY_HINT_RESOURCE_TYPE, "OpenXRAction"), "set_action", "get_action");
}

void OpenXRAnalogThresholdModifier::set_action(const Ref<OpenXRAction> p_action) {
action = p_action;
emit_changed();
}

Ref<OpenXRAction> OpenXRAnalogThresholdModifier::get_action() const {
return action;
}

int OpenXRAnalogThresholdModifier::get_binding_modification_struct_size() const {
return sizeof(XrInteractionProfileAnalogThresholdVALVE);
}

const XrBindingModificationBaseHeaderKHR *OpenXRAnalogThresholdModifier::get_binding_modification() {
OpenXRValveAnalogThresholdExtension *analog_threshold_ext = OpenXRValveAnalogThresholdExtension::get_singleton();
if (!analog_threshold_ext || !analog_threshold_ext->is_available()) {
// Extension not enabled!
return nullptr;
}

OpenXRAPI *openxr_api = OpenXRAPI::get_singleton();
ERR_FAIL_NULL_V(openxr_api, nullptr);

analog_threshold.type = XR_TYPE_INTERACTION_PROFILE_ANALOG_THRESHOLD_VALVE;
analog_threshold.next = nullptr;
// analog_threshold.action = Need to look up

return (XrBindingModificationBaseHeaderKHR *)analog_threshold;
}
Loading

0 comments on commit 092e77e

Please sign in to comment.