summaryrefslogtreecommitdiff
path: root/modules/openxr/action_map
diff options
context:
space:
mode:
Diffstat (limited to 'modules/openxr/action_map')
-rw-r--r--modules/openxr/action_map/openxr_action.cpp91
-rw-r--r--modules/openxr/action_map/openxr_action.h74
-rw-r--r--modules/openxr/action_map/openxr_action_map.cpp261
-rw-r--r--modules/openxr/action_map/openxr_action_map.h68
-rw-r--r--modules/openxr/action_map/openxr_action_set.cpp111
-rw-r--r--modules/openxr/action_map/openxr_action_set.h70
-rw-r--r--modules/openxr/action_map/openxr_interaction_profile.cpp136
-rw-r--r--modules/openxr/action_map/openxr_interaction_profile.h89
8 files changed, 900 insertions, 0 deletions
diff --git a/modules/openxr/action_map/openxr_action.cpp b/modules/openxr/action_map/openxr_action.cpp
new file mode 100644
index 0000000000..59ee3f4292
--- /dev/null
+++ b/modules/openxr/action_map/openxr_action.cpp
@@ -0,0 +1,91 @@
+/*************************************************************************/
+/* openxr_action.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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_action.h"
+
+void OpenXRAction::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_localized_name", "localized_name"), &OpenXRAction::set_localized_name);
+ ClassDB::bind_method(D_METHOD("get_localized_name"), &OpenXRAction::get_localized_name);
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "localized_name"), "set_localized_name", "get_localized_name");
+
+ ClassDB::bind_method(D_METHOD("set_action_type", "action_type"), &OpenXRAction::set_action_type);
+ ClassDB::bind_method(D_METHOD("get_action_type"), &OpenXRAction::get_action_type);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "action_type", PROPERTY_HINT_ENUM, "bool,float,vector2,pose"), "set_action_type", "get_action_type");
+
+ ClassDB::bind_method(D_METHOD("set_toplevel_paths", "toplevel_paths"), &OpenXRAction::set_toplevel_paths);
+ ClassDB::bind_method(D_METHOD("get_toplevel_paths"), &OpenXRAction::get_toplevel_paths);
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "toplevel_paths", PROPERTY_HINT_ARRAY_TYPE, "STRING"), "set_toplevel_paths", "get_toplevel_paths");
+
+ BIND_ENUM_CONSTANT(OPENXR_ACTION_BOOL);
+ BIND_ENUM_CONSTANT(OPENXR_ACTION_FLOAT);
+ BIND_ENUM_CONSTANT(OPENXR_ACTION_VECTOR2);
+ BIND_ENUM_CONSTANT(OPENXR_ACTION_POSE);
+}
+
+Ref<OpenXRAction> OpenXRAction::new_action(const char *p_name, const char *p_localized_name, const ActionType p_action_type, const char *p_toplevel_paths) {
+ // This is a helper function to help build our default action sets
+
+ Ref<OpenXRAction> action;
+ action.instantiate();
+ action->set_name(String(p_name));
+ action->set_localized_name(String(p_localized_name));
+ action->set_action_type(p_action_type);
+ action->parse_toplevel_paths(String(p_toplevel_paths));
+
+ return action;
+}
+
+void OpenXRAction::set_localized_name(const String p_localized_name) {
+ localized_name = p_localized_name;
+}
+
+String OpenXRAction::get_localized_name() const {
+ return localized_name;
+}
+
+void OpenXRAction::set_action_type(const OpenXRAction::ActionType p_action_type) {
+ action_type = p_action_type;
+}
+
+OpenXRAction::ActionType OpenXRAction::get_action_type() const {
+ return action_type;
+}
+
+void OpenXRAction::set_toplevel_paths(const PackedStringArray p_toplevel_paths) {
+ toplevel_paths = p_toplevel_paths;
+}
+
+PackedStringArray OpenXRAction::get_toplevel_paths() const {
+ return toplevel_paths;
+}
+
+void OpenXRAction::parse_toplevel_paths(const String p_toplevel_paths) {
+ toplevel_paths = p_toplevel_paths.split(",", false);
+}
diff --git a/modules/openxr/action_map/openxr_action.h b/modules/openxr/action_map/openxr_action.h
new file mode 100644
index 0000000000..e2cfe79e64
--- /dev/null
+++ b/modules/openxr/action_map/openxr_action.h
@@ -0,0 +1,74 @@
+/*************************************************************************/
+/* openxr_action.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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_ACTION_H
+#define OPENXR_ACTION_H
+
+#include "core/io/resource.h"
+
+class OpenXRAction : public Resource {
+ GDCLASS(OpenXRAction, Resource);
+
+public:
+ enum ActionType {
+ OPENXR_ACTION_BOOL,
+ OPENXR_ACTION_FLOAT,
+ OPENXR_ACTION_VECTOR2,
+ OPENXR_ACTION_POSE,
+ OPENXR_ACTION_HAPTIC,
+ };
+
+private:
+ String localized_name;
+ ActionType action_type = OPENXR_ACTION_FLOAT;
+
+ PackedStringArray toplevel_paths;
+
+protected:
+ static void _bind_methods();
+
+public:
+ static Ref<OpenXRAction> new_action(const char *p_name, const char *p_localized_name, const ActionType p_action_type, const char *p_toplevel_paths);
+
+ void set_localized_name(const String p_localized_name);
+ String get_localized_name() const;
+
+ void set_action_type(const ActionType p_action_type);
+ ActionType get_action_type() const;
+
+ void set_toplevel_paths(const PackedStringArray p_toplevel_paths);
+ PackedStringArray get_toplevel_paths() const;
+
+ void parse_toplevel_paths(const String p_toplevel_paths);
+};
+
+VARIANT_ENUM_CAST(OpenXRAction::ActionType);
+
+#endif // !OPENXR_ACTION_H
diff --git a/modules/openxr/action_map/openxr_action_map.cpp b/modules/openxr/action_map/openxr_action_map.cpp
new file mode 100644
index 0000000000..5391f9569a
--- /dev/null
+++ b/modules/openxr/action_map/openxr_action_map.cpp
@@ -0,0 +1,261 @@
+/*************************************************************************/
+/* openxr_action_map.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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_action_map.h"
+
+void OpenXRActionMap::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_action_sets", "action_sets"), &OpenXRActionMap::set_action_sets);
+ ClassDB::bind_method(D_METHOD("get_action_sets"), &OpenXRActionMap::get_action_sets);
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "action_sets", PROPERTY_HINT_RESOURCE_TYPE, "OpenXRActionSet", PROPERTY_USAGE_NO_EDITOR), "set_action_sets", "get_action_sets");
+
+ ClassDB::bind_method(D_METHOD("add_action_set", "action_set"), &OpenXRActionMap::add_action_set);
+ ClassDB::bind_method(D_METHOD("remove_action_set", "action_set"), &OpenXRActionMap::remove_action_set);
+
+ ClassDB::bind_method(D_METHOD("set_interaction_profiles", "interaction_profiles"), &OpenXRActionMap::set_interaction_profiles);
+ ClassDB::bind_method(D_METHOD("get_interaction_profiles"), &OpenXRActionMap::get_interaction_profiles);
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "interaction_profiles", PROPERTY_HINT_RESOURCE_TYPE, "OpenXRInteractionProfile", PROPERTY_USAGE_NO_EDITOR), "set_interaction_profiles", "get_interaction_profiles");
+
+ ClassDB::bind_method(D_METHOD("add_interaction_profile", "interaction_profile"), &OpenXRActionMap::add_interaction_profile);
+ ClassDB::bind_method(D_METHOD("remove_interaction_profile", "interaction_profile"), &OpenXRActionMap::remove_interaction_profile);
+
+ ClassDB::bind_method(D_METHOD("create_default_action_sets"), &OpenXRActionMap::create_default_action_sets);
+}
+
+void OpenXRActionMap::set_action_sets(Array p_action_sets) {
+ action_sets = p_action_sets;
+}
+
+Array OpenXRActionMap::get_action_sets() const {
+ return action_sets;
+}
+
+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) {
+ action_sets.push_back(p_action_set);
+ }
+}
+
+void OpenXRActionMap::remove_action_set(Ref<OpenXRActionSet> p_action_set) {
+ int idx = action_sets.find(p_action_set);
+ if (idx != -1) {
+ action_sets.remove_at(idx);
+ }
+}
+
+void OpenXRActionMap::set_interaction_profiles(Array p_interaction_profiles) {
+ interaction_profiles = p_interaction_profiles;
+}
+
+Array OpenXRActionMap::get_interaction_profiles() const {
+ return interaction_profiles;
+}
+
+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) {
+ interaction_profiles.push_back(p_interaction_profile);
+ }
+}
+
+void OpenXRActionMap::remove_interaction_profile(Ref<OpenXRInteractionProfile> p_interaction_profile) {
+ int idx = interaction_profiles.find(p_interaction_profile);
+ if (idx != -1) {
+ interaction_profiles.remove_at(idx);
+ }
+}
+
+void OpenXRActionMap::create_default_action_sets() {
+ // Note, if you make changes here make sure to delete your default_action_map.tres file of it will load an old version.
+
+ // Create our Godot action set
+ Ref<OpenXRActionSet> action_set = OpenXRActionSet::new_action_set("godot", "Godot action set");
+ add_action_set(action_set);
+
+ // Create our actions
+ Ref<OpenXRAction> trigger = action_set->add_new_action("trigger", "Trigger", OpenXRAction::OPENXR_ACTION_FLOAT, "/user/hand/left,/user/hand/right");
+ Ref<OpenXRAction> trigger_click = action_set->add_new_action("trigger_click", "Trigger click", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
+ Ref<OpenXRAction> trigger_touch = action_set->add_new_action("trigger_touch", "Trigger touching", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
+ Ref<OpenXRAction> grip = action_set->add_new_action("grip", "Grip", OpenXRAction::OPENXR_ACTION_FLOAT, "/user/hand/left,/user/hand/right");
+ Ref<OpenXRAction> grip_click = action_set->add_new_action("grip_click", "Grip click", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
+ Ref<OpenXRAction> grip_touch = action_set->add_new_action("grip_touch", "Grip touching", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
+ Ref<OpenXRAction> primary = action_set->add_new_action("primary", "Primary joystick/thumbstick/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2, "/user/hand/left,/user/hand/right");
+ Ref<OpenXRAction> primary_click = action_set->add_new_action("primary_click", "Primary joystick/thumbstick/trackpad click", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
+ Ref<OpenXRAction> primary_touch = action_set->add_new_action("primary_touch", "Primary joystick/thumbstick/trackpad touching", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
+ Ref<OpenXRAction> secondary = action_set->add_new_action("secondary", "Secondary joystick/thumbstick/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2, "/user/hand/left,/user/hand/right");
+ Ref<OpenXRAction> secondary_click = action_set->add_new_action("secondary_click", "Secondary joystick/thumbstick/trackpad click", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
+ Ref<OpenXRAction> secondary_touch = action_set->add_new_action("secondary_touch", "Secondary joystick/thumbstick/trackpad touching", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
+ Ref<OpenXRAction> menu_button = action_set->add_new_action("menu_button", "Menu button", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
+ Ref<OpenXRAction> select_button = action_set->add_new_action("select_button", "Select button", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
+ Ref<OpenXRAction> ax_button = action_set->add_new_action("ax_button", "A/X button", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
+ Ref<OpenXRAction> ax_touch = action_set->add_new_action("ax_touch", "A/X touching", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
+ Ref<OpenXRAction> by_button = action_set->add_new_action("by_button", "B/Y button", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
+ Ref<OpenXRAction> by_touch = action_set->add_new_action("by_touch", "B/Y touching", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
+ Ref<OpenXRAction> default_pose = action_set->add_new_action("default_pose", "Default pose", OpenXRAction::OPENXR_ACTION_POSE, "/user/hand/left,/user/hand/right");
+ Ref<OpenXRAction> aim_pose = action_set->add_new_action("aim_pose", "Aim pose", OpenXRAction::OPENXR_ACTION_POSE, "/user/hand/left,/user/hand/right");
+ Ref<OpenXRAction> grip_pose = action_set->add_new_action("grip_pose", "Grip pose", OpenXRAction::OPENXR_ACTION_POSE, "/user/hand/left,/user/hand/right");
+ Ref<OpenXRAction> haptic = action_set->add_new_action("haptic", "Haptic", OpenXRAction::OPENXR_ACTION_HAPTIC, "/user/hand/left,/user/hand/right");
+
+ // Create our interaction profiles
+ Ref<OpenXRInteractionProfile> profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/khr/simple_controller");
+ profile->add_new_binding(default_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
+ profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/menu/click");
+ profile->add_new_binding(select_button, "/user/hand/left/input/select/click,/user/hand/right/input/select/click");
+ // generic has no support for triggers, grip, A/B buttons, nor joystick/trackpad inputs
+ profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
+ add_interaction_profile(profile);
+
+ // Create our Vive controller profile
+ profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/htc/vive_controller");
+ profile->add_new_binding(default_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
+ profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/menu/click");
+ profile->add_new_binding(select_button, "/user/hand/left/input/system/click,/user/hand/right/input/system/click");
+ // wmr controller has no a/b/x/y buttons
+ profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
+ profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/click,/user/hand/right/input/trigger/click");
+ profile->add_new_binding(grip, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click"); // OpenXR will convert bool to float
+ profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click");
+ // primary on our vive controller is our trackpad
+ profile->add_new_binding(primary, "/user/hand/left/input/trackpad,/user/hand/right/input/trackpad");
+ profile->add_new_binding(primary_click, "/user/hand/left/input/trackpad/click,/user/hand/right/input/trackpad/click");
+ profile->add_new_binding(primary_touch, "/user/hand/left/input/trackpad/touch,/user/hand/right/input/trackpad/touch");
+ // vive controllers have no secondary input
+ profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
+ add_interaction_profile(profile);
+
+ // Create our WMR controller profile
+ profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/microsoft/motion_controller");
+ profile->add_new_binding(default_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
+ profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ // wmr controllers have no select button we can use
+ profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/menu/click");
+ // wmr controller has no a/b/x/y buttons
+ profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
+ profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value"); // OpenXR will conver float to bool
+ profile->add_new_binding(grip, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click"); // OpenXR will convert bool to float
+ profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click");
+ // primary on our wmr controller is our thumbstick, no touch
+ profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick");
+ profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click");
+ // secondary on our wmr controller is our trackpad
+ profile->add_new_binding(secondary, "/user/hand/left/input/trackpad,/user/hand/right/input/trackpad");
+ profile->add_new_binding(secondary_click, "/user/hand/left/input/trackpad/click,/user/hand/right/input/trackpad/click");
+ profile->add_new_binding(secondary_touch, "/user/hand/left/input/trackpad/touch,/user/hand/right/input/trackpad/touch");
+ profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
+ add_interaction_profile(profile);
+
+ // Create our HP MR controller profile
+ profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/hp/mixed_reality_controller");
+ profile->add_new_binding(default_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
+ profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ // hpmr controllers have no select button we can use
+ profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/menu/click");
+ // hpmr controllers only register click, not touch, on our a/b/x/y buttons
+ profile->add_new_binding(ax_button, "/user/hand/left/input/x/click,/user/hand/right/input/a/click"); // x on left hand, a on right hand
+ profile->add_new_binding(by_button, "/user/hand/left/input/y/click,/user/hand/right/input/b/click"); // y on left hand, b on right hand
+ profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
+ profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
+ profile->add_new_binding(grip, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value");
+ profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value");
+ // primary on our hpmr controller is our thumbstick
+ profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick");
+ profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click");
+ // No secondary on our hpmr controller
+ profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
+ add_interaction_profile(profile);
+
+ // Create our Meta touch controller profile
+ profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/oculus/touch_controller");
+ profile->add_new_binding(default_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
+ profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ // touch controllers have no select button we can use
+ profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/system/click"); // right hand system click may not be available
+ profile->add_new_binding(ax_button, "/user/hand/left/input/x/click,/user/hand/right/input/a/click"); // x on left hand, a on right hand
+ profile->add_new_binding(ax_touch, "/user/hand/left/input/x/touch,/user/hand/right/input/a/touch");
+ profile->add_new_binding(by_button, "/user/hand/left/input/y/click,/user/hand/right/input/b/click"); // y on left hand, b on right hand
+ profile->add_new_binding(by_touch, "/user/hand/left/input/y/touch,/user/hand/right/input/b/touch");
+ profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
+ profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value"); // should be converted to boolean
+ profile->add_new_binding(trigger_touch, "/user/hand/left/input/trigger/touch,/user/hand/right/input/trigger/touch");
+ profile->add_new_binding(grip, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value"); // should be converted to boolean
+ profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value");
+ // primary on our touch controller is our thumbstick
+ profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick");
+ profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click");
+ profile->add_new_binding(primary_touch, "/user/hand/left/input/thumbstick/touch,/user/hand/right/input/thumbstick/touch");
+ // touch controller has no secondary input
+ profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
+ add_interaction_profile(profile);
+
+ // Create our Valve index controller profile
+ profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/valve/index_controller");
+ profile->add_new_binding(default_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
+ profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ // index controllers have no select button we can use
+ profile->add_new_binding(menu_button, "/user/hand/left/input/system/click,/user/hand/right/input/system/click");
+ profile->add_new_binding(ax_button, "/user/hand/left/input/a/click,/user/hand/right/input/a/click"); // a on both controllers
+ profile->add_new_binding(ax_touch, "/user/hand/left/input/a/touch,/user/hand/right/input/a/touch");
+ profile->add_new_binding(by_button, "/user/hand/left/input/b/click,/user/hand/right/input/b/click"); // b on both controllers
+ profile->add_new_binding(by_touch, "/user/hand/left/input/b/touch,/user/hand/right/input/b/touch");
+ profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
+ profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/click,/user/hand/right/input/trigger/click");
+ profile->add_new_binding(trigger_touch, "/user/hand/left/input/trigger/touch,/user/hand/right/input/trigger/touch");
+ profile->add_new_binding(grip, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value");
+ profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value"); // this should do a float to bool conversion
+ // primary on our index controller is our thumbstick
+ profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick");
+ profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click");
+ profile->add_new_binding(primary_touch, "/user/hand/left/input/thumbstick/touch,/user/hand/right/input/thumbstick/touch");
+ // secondary on our index controller is our trackpad
+ profile->add_new_binding(secondary, "/user/hand/left/input/trackpad,/user/hand/right/input/trackpad");
+ profile->add_new_binding(secondary_click, "/user/hand/left/input/trackpad/force,/user/hand/right/input/trackpad/force"); // not sure if this will work but doesn't seem to support click...
+ profile->add_new_binding(secondary_touch, "/user/hand/left/input/trackpad/touch,/user/hand/right/input/trackpad/touch");
+ profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
+ add_interaction_profile(profile);
+}
+
+void OpenXRActionMap::create_editor_action_sets() {
+ // TODO implement
+}
+
+OpenXRActionMap::~OpenXRActionMap() {
+ action_sets.clear();
+ interaction_profiles.clear();
+}
diff --git a/modules/openxr/action_map/openxr_action_map.h b/modules/openxr/action_map/openxr_action_map.h
new file mode 100644
index 0000000000..866e170468
--- /dev/null
+++ b/modules/openxr/action_map/openxr_action_map.h
@@ -0,0 +1,68 @@
+/*************************************************************************/
+/* openxr_action_map.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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_ACTION_SETS_H
+#define OPENXR_ACTION_SETS_H
+
+#include "core/io/resource.h"
+
+#include "openxr_action_set.h"
+#include "openxr_interaction_profile.h"
+
+class OpenXRActionMap : public Resource {
+ GDCLASS(OpenXRActionMap, Resource);
+
+private:
+ Array action_sets;
+ Array interaction_profiles;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_action_sets(Array p_action_sets);
+ Array get_action_sets() const;
+
+ void add_action_set(Ref<OpenXRActionSet> p_action_set);
+ void remove_action_set(Ref<OpenXRActionSet> p_action_set);
+
+ void set_interaction_profiles(Array p_interaction_profiles);
+ Array get_interaction_profiles() const;
+
+ void add_interaction_profile(Ref<OpenXRInteractionProfile> p_interaction_profile);
+ void remove_interaction_profile(Ref<OpenXRInteractionProfile> p_interaction_profile);
+
+ void create_default_action_sets();
+ void create_editor_action_sets();
+
+ ~OpenXRActionMap();
+};
+
+#endif // !OPENXR_ACTION_SETS_H
diff --git a/modules/openxr/action_map/openxr_action_set.cpp b/modules/openxr/action_map/openxr_action_set.cpp
new file mode 100644
index 0000000000..465a709b60
--- /dev/null
+++ b/modules/openxr/action_map/openxr_action_set.cpp
@@ -0,0 +1,111 @@
+/*************************************************************************/
+/* openxr_action_set.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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_action_set.h"
+
+void OpenXRActionSet::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_localized_name", "localized_name"), &OpenXRActionSet::set_localized_name);
+ ClassDB::bind_method(D_METHOD("get_localized_name"), &OpenXRActionSet::get_localized_name);
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "localized_name"), "set_localized_name", "get_localized_name");
+
+ ClassDB::bind_method(D_METHOD("set_priority", "priority"), &OpenXRActionSet::set_priority);
+ ClassDB::bind_method(D_METHOD("get_priority"), &OpenXRActionSet::get_priority);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "priority"), "set_priority", "get_priority");
+
+ ClassDB::bind_method(D_METHOD("set_actions", "actions"), &OpenXRActionSet::set_actions);
+ ClassDB::bind_method(D_METHOD("get_actions"), &OpenXRActionSet::get_actions);
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "actions", PROPERTY_HINT_RESOURCE_TYPE, "OpenXRAction", PROPERTY_USAGE_NO_EDITOR), "set_actions", "get_actions");
+
+ ClassDB::bind_method(D_METHOD("add_action", "action"), &OpenXRActionSet::add_action);
+ ClassDB::bind_method(D_METHOD("remove_action", "action"), &OpenXRActionSet::remove_action);
+}
+
+Ref<OpenXRActionSet> OpenXRActionSet::new_action_set(const char *p_name, const char *p_localized_name, const int p_priority) {
+ // This is a helper function to help build our default action sets
+
+ Ref<OpenXRActionSet> action_set;
+ action_set.instantiate();
+ action_set->set_name(String(p_name));
+ action_set->set_localized_name(p_localized_name);
+ action_set->set_priority(p_priority);
+
+ return action_set;
+}
+
+void OpenXRActionSet::set_localized_name(const String p_localized_name) {
+ localized_name = p_localized_name;
+}
+
+String OpenXRActionSet::get_localized_name() const {
+ return localized_name;
+}
+
+void OpenXRActionSet::set_priority(const int p_priority) {
+ priority = p_priority;
+}
+
+int OpenXRActionSet::get_priority() const {
+ return priority;
+}
+
+void OpenXRActionSet::set_actions(Array p_actions) {
+ actions = p_actions;
+}
+
+Array OpenXRActionSet::get_actions() const {
+ return actions;
+}
+
+void OpenXRActionSet::add_action(Ref<OpenXRAction> p_action) {
+ ERR_FAIL_COND(p_action.is_null());
+
+ if (actions.find(p_action) == -1) {
+ actions.push_back(p_action);
+ }
+}
+
+void OpenXRActionSet::remove_action(Ref<OpenXRAction> p_action) {
+ int idx = actions.find(p_action);
+ if (idx != -1) {
+ actions.remove_at(idx);
+ }
+}
+
+Ref<OpenXRAction> OpenXRActionSet::add_new_action(const char *p_name, const char *p_localized_name, const OpenXRAction::ActionType p_action_type, const char *p_toplevel_paths) {
+ // This is a helper function to help build our default action sets
+
+ Ref<OpenXRAction> new_action = OpenXRAction::new_action(p_name, p_localized_name, p_action_type, p_toplevel_paths);
+ add_action(new_action);
+ return new_action;
+}
+
+OpenXRActionSet::~OpenXRActionSet() {
+ actions.clear();
+}
diff --git a/modules/openxr/action_map/openxr_action_set.h b/modules/openxr/action_map/openxr_action_set.h
new file mode 100644
index 0000000000..012a088b1c
--- /dev/null
+++ b/modules/openxr/action_map/openxr_action_set.h
@@ -0,0 +1,70 @@
+/*************************************************************************/
+/* openxr_action_set.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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_ACTION_SET_H
+#define OPENXR_ACTION_SET_H
+
+#include "core/io/resource.h"
+
+#include "openxr_action.h"
+
+class OpenXRActionSet : public Resource {
+ GDCLASS(OpenXRActionSet, Resource);
+
+private:
+ String localized_name;
+ int priority = 0;
+
+ Array actions;
+
+protected:
+ static void _bind_methods();
+
+public:
+ static Ref<OpenXRActionSet> new_action_set(const char *p_name, const char *p_localized_name, const int p_priority = 0);
+
+ void set_localized_name(const String p_localized_name);
+ String get_localized_name() const;
+
+ void set_priority(const int p_priority);
+ int get_priority() const;
+
+ void set_actions(Array p_actions);
+ Array get_actions() const;
+
+ void add_action(Ref<OpenXRAction> p_action);
+ void remove_action(Ref<OpenXRAction> p_action);
+
+ Ref<OpenXRAction> add_new_action(const char *p_name, const char *p_localized_name, const OpenXRAction::ActionType p_action_type, const char *p_toplevel_paths);
+
+ ~OpenXRActionSet();
+};
+
+#endif // !OPENXR_ACTION_SET_H
diff --git a/modules/openxr/action_map/openxr_interaction_profile.cpp b/modules/openxr/action_map/openxr_interaction_profile.cpp
new file mode 100644
index 0000000000..bc33814f17
--- /dev/null
+++ b/modules/openxr/action_map/openxr_interaction_profile.cpp
@@ -0,0 +1,136 @@
+/*************************************************************************/
+/* openxr_interaction_profile.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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_interaction_profile.h"
+
+void OpenXRIPBinding::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_action", "action"), &OpenXRIPBinding::set_action);
+ 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("set_paths", "paths"), &OpenXRIPBinding::set_paths);
+ ClassDB::bind_method(D_METHOD("get_paths"), &OpenXRIPBinding::get_paths);
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "paths", PROPERTY_HINT_ARRAY_TYPE, "STRING"), "set_paths", "get_paths");
+}
+
+Ref<OpenXRIPBinding> OpenXRIPBinding::new_binding(const Ref<OpenXRAction> p_action, const char *p_paths) {
+ // 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));
+
+ return binding;
+}
+
+void OpenXRIPBinding::set_action(const Ref<OpenXRAction> p_action) {
+ action = p_action;
+}
+
+Ref<OpenXRAction> OpenXRIPBinding::get_action() const {
+ return action;
+}
+
+void OpenXRIPBinding::set_paths(const PackedStringArray p_paths) {
+ paths = p_paths;
+}
+
+PackedStringArray OpenXRIPBinding::get_paths() const {
+ return paths;
+}
+
+void OpenXRIPBinding::parse_paths(const String p_paths) {
+ paths = p_paths.split(",", false);
+}
+
+OpenXRIPBinding::~OpenXRIPBinding() {
+ action.unref();
+}
+
+void OpenXRInteractionProfile::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_interaction_profile_path", "interaction_profile_path"), &OpenXRInteractionProfile::set_interaction_profile_path);
+ ClassDB::bind_method(D_METHOD("get_interaction_profile_path"), &OpenXRInteractionProfile::get_interaction_profile_path);
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "interaction_profile_path"), "set_interaction_profile_path", "get_interaction_profile_path");
+
+ 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");
+}
+
+Ref<OpenXRInteractionProfile> OpenXRInteractionProfile::new_profile(const char *p_input_profile_path) {
+ Ref<OpenXRInteractionProfile> profile;
+ profile.instantiate();
+ profile->set_interaction_profile_path(String(p_input_profile_path));
+
+ return profile;
+}
+
+void OpenXRInteractionProfile::set_interaction_profile_path(const String p_input_profile_path) {
+ interaction_profile_path = p_input_profile_path;
+}
+
+String OpenXRInteractionProfile::get_interaction_profile_path() const {
+ return interaction_profile_path;
+}
+
+void OpenXRInteractionProfile::set_bindings(Array p_bindings) {
+ bindings = p_bindings;
+}
+
+Array OpenXRInteractionProfile::get_bindings() const {
+ return bindings;
+}
+
+void OpenXRInteractionProfile::add_binding(Ref<OpenXRIPBinding> p_binding) {
+ ERR_FAIL_COND(p_binding.is_null());
+
+ if (bindings.find(p_binding) == -1) {
+ bindings.push_back(p_binding);
+ }
+}
+
+void OpenXRInteractionProfile::remove_binding(Ref<OpenXRIPBinding> p_binding) {
+ int idx = bindings.find(p_binding);
+ if (idx != -1) {
+ bindings.remove_at(idx);
+ }
+}
+
+void OpenXRInteractionProfile::add_new_binding(const Ref<OpenXRAction> p_action, const char *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);
+}
+
+OpenXRInteractionProfile::~OpenXRInteractionProfile() {
+ bindings.clear();
+}
diff --git a/modules/openxr/action_map/openxr_interaction_profile.h b/modules/openxr/action_map/openxr_interaction_profile.h
new file mode 100644
index 0000000000..abbc429e7d
--- /dev/null
+++ b/modules/openxr/action_map/openxr_interaction_profile.h
@@ -0,0 +1,89 @@
+/*************************************************************************/
+/* openxr_interaction_profile.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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_INTERACTION_PROFILE_H
+#define OPENXR_INTERACTION_PROFILE_H
+
+#include "core/io/resource.h"
+
+#include "openxr_action.h"
+
+class OpenXRIPBinding : public Resource {
+ GDCLASS(OpenXRIPBinding, Resource);
+
+private:
+ Ref<OpenXRAction> action;
+ PackedStringArray paths;
+
+protected:
+ static void _bind_methods();
+
+public:
+ static Ref<OpenXRIPBinding> new_binding(const Ref<OpenXRAction> p_action, const char *p_paths);
+
+ void set_action(const Ref<OpenXRAction> p_action);
+ Ref<OpenXRAction> get_action() const;
+
+ void set_paths(const PackedStringArray p_paths);
+ PackedStringArray get_paths() const;
+
+ void parse_paths(const String p_paths);
+
+ ~OpenXRIPBinding();
+};
+
+class OpenXRInteractionProfile : public Resource {
+ GDCLASS(OpenXRInteractionProfile, Resource);
+
+private:
+ String interaction_profile_path;
+ Array bindings;
+
+protected:
+ static void _bind_methods();
+
+public:
+ static Ref<OpenXRInteractionProfile> new_profile(const char *p_input_profile_path);
+
+ void set_interaction_profile_path(const String p_input_profile_path);
+ String get_interaction_profile_path() const;
+
+ void set_bindings(Array p_bindings);
+ Array get_bindings() const;
+
+ void add_binding(Ref<OpenXRIPBinding> p_binding);
+ void remove_binding(Ref<OpenXRIPBinding> p_binding);
+
+ void add_new_binding(const Ref<OpenXRAction> p_action, const char *p_paths);
+
+ ~OpenXRInteractionProfile();
+};
+
+#endif // !OPENXR_INTERACTION_PROFILE_H