feat: updated engine version to 4.4-rc1

This commit is contained in:
Sara 2025-02-23 14:38:14 +01:00
parent ee00efde1f
commit 21ba8e33af
5459 changed files with 1128836 additions and 198305 deletions

View file

@ -1,4 +1,5 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")
Import("env_openxr")

View file

@ -107,14 +107,25 @@ void OpenXRActionMap::remove_action_set(Ref<OpenXRActionSet> p_action_set) {
}
}
void OpenXRActionMap::set_interaction_profiles(Array p_interaction_profiles) {
interaction_profiles.clear();
void OpenXRActionMap::clear_interaction_profiles() {
if (interaction_profiles.is_empty()) {
return;
}
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.has(interaction_profile)) {
interaction_profiles.push_back(interaction_profile);
}
// Interaction profiles held within our action map set should be released and destroyed but just in case they are still used some where else.
for (Ref<OpenXRInteractionProfile> interaction_profile : interaction_profiles) {
interaction_profile->action_map = nullptr;
}
interaction_profiles.clear();
emit_changed();
}
void OpenXRActionMap::set_interaction_profiles(Array p_interaction_profiles) {
clear_interaction_profiles();
for (const Variant &interaction_profile : p_interaction_profiles) {
// Add them anew so we verify our interaction profile pointer.
add_interaction_profile(interaction_profile);
}
}
@ -127,8 +138,7 @@ int OpenXRActionMap::get_interaction_profile_count() const {
}
Ref<OpenXRInteractionProfile> OpenXRActionMap::find_interaction_profile(String p_path) const {
for (int i = 0; i < interaction_profiles.size(); i++) {
Ref<OpenXRInteractionProfile> interaction_profile = interaction_profiles[i];
for (Ref<OpenXRInteractionProfile> interaction_profile : interaction_profiles) {
if (interaction_profile->get_interaction_profile_path() == p_path) {
return interaction_profile;
}
@ -147,6 +157,13 @@ void OpenXRActionMap::add_interaction_profile(Ref<OpenXRInteractionProfile> p_in
ERR_FAIL_COND(p_interaction_profile.is_null());
if (!interaction_profiles.has(p_interaction_profile)) {
if (p_interaction_profile->action_map && p_interaction_profile->action_map != this) {
// Interaction profiles should only relate to our action map.
p_interaction_profile->action_map->remove_interaction_profile(p_interaction_profile);
}
p_interaction_profile->action_map = this;
interaction_profiles.push_back(p_interaction_profile);
emit_changed();
}
@ -156,6 +173,10 @@ void OpenXRActionMap::remove_interaction_profile(Ref<OpenXRInteractionProfile> p
int idx = interaction_profiles.find(p_interaction_profile);
if (idx != -1) {
interaction_profiles.remove_at(idx);
ERR_FAIL_COND_MSG(p_interaction_profile->action_map != this, "Removing interaction profile that belongs to this action map but had incorrect action map pointer."); // This should never happen!
p_interaction_profile->action_map = nullptr;
emit_changed();
}
}
@ -549,9 +570,7 @@ Ref<OpenXRAction> OpenXRActionMap::get_action(const String p_path) const {
void OpenXRActionMap::remove_action(const String p_path, bool p_remove_interaction_profiles) {
Ref<OpenXRAction> action = get_action(p_path);
if (action.is_valid()) {
for (int i = 0; i < interaction_profiles.size(); i++) {
Ref<OpenXRInteractionProfile> interaction_profile = interaction_profiles[i];
for (Ref<OpenXRInteractionProfile> interaction_profile : interaction_profiles) {
if (p_remove_interaction_profiles) {
// Remove any bindings for this action
interaction_profile->remove_binding_for_action(action);
@ -571,25 +590,19 @@ void OpenXRActionMap::remove_action(const String p_path, bool p_remove_interacti
PackedStringArray OpenXRActionMap::get_top_level_paths(const Ref<OpenXRAction> p_action) {
PackedStringArray arr;
for (int i = 0; i < interaction_profiles.size(); i++) {
Ref<OpenXRInteractionProfile> ip = interaction_profiles[i];
for (Ref<OpenXRInteractionProfile> ip : interaction_profiles) {
const OpenXRInteractionProfileMetadata::InteractionProfile *profile = OpenXRInteractionProfileMetadata::get_singleton()->get_profile(ip->get_interaction_profile_path());
if (profile != nullptr) {
for (int j = 0; j < ip->get_binding_count(); j++) {
Ref<OpenXRIPBinding> binding = ip->get_binding(j);
if (binding->get_action() == p_action) {
PackedStringArray paths = binding->get_paths();
Vector<Ref<OpenXRIPBinding>> bindings = ip->get_bindings_for_action(p_action);
for (const Ref<OpenXRIPBinding> &binding : bindings) {
String binding_path = binding->get_binding_path();
const OpenXRInteractionProfileMetadata::IOPath *io_path = profile->get_io_path(binding_path);
if (io_path != nullptr) {
String top_path = io_path->top_level_path;
for (int k = 0; k < paths.size(); k++) {
const OpenXRInteractionProfileMetadata::IOPath *io_path = profile->get_io_path(paths[k]);
if (io_path != nullptr) {
String top_path = io_path->top_level_path;
if (!arr.has(top_path)) {
arr.push_back(top_path);
}
}
if (!arr.has(top_path)) {
arr.push_back(top_path);
}
}
}
@ -603,5 +616,5 @@ PackedStringArray OpenXRActionMap::get_top_level_paths(const Ref<OpenXRAction> p
OpenXRActionMap::~OpenXRActionMap() {
action_sets.clear();
interaction_profiles.clear();
clear_interaction_profiles();
}

View file

@ -57,6 +57,7 @@ public:
void add_action_set(Ref<OpenXRActionSet> p_action_set); // Add an action set to our action map
void remove_action_set(Ref<OpenXRActionSet> p_action_set); // Remove an action set from our action map
void clear_interaction_profiles(); // Remove all our interaction profiles
void set_interaction_profiles(Array p_interaction_profiles); // Set our interaction profiles by providing an array (for loading from resource)
Array get_interaction_profiles() const; // Get our interaction profiles as an array (for saving to resource)

View file

@ -141,7 +141,7 @@ void OpenXRActionSet::remove_action(Ref<OpenXRAction> p_action) {
if (idx != -1) {
actions.remove_at(idx);
ERR_FAIL_COND_MSG(p_action->action_set != this, "Removing action that belongs to this action set but had incorrect action set pointer."); // this should never happen!
ERR_FAIL_COND_MSG(p_action->action_set != this, "Removing action that belongs to this action set but had incorrect action set pointer."); // This should never happen!
p_action->action_set = nullptr;
emit_changed();

View file

@ -0,0 +1,52 @@
/**************************************************************************/
/* 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() {
GDVIRTUAL_BIND(_get_description);
GDVIRTUAL_BIND(_get_ip_modification);
}
String OpenXRBindingModifier::get_description() const {
String desc;
if (GDVIRTUAL_CALL(_get_description, desc)) {
return desc;
}
return "";
}
PackedByteArray OpenXRBindingModifier::get_ip_modification() {
PackedByteArray data;
if (GDVIRTUAL_CALL(_get_ip_modification, data)) {
return data;
}
return PackedByteArray();
}

View file

@ -0,0 +1,81 @@
/**************************************************************************/
/* 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 "../action_map/openxr_action.h"
#include "core/io/resource.h"
// Part of implementation for:
// https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#XR_KHR_binding_modification
class OpenXRInteractionProfile;
class OpenXRIPBinding;
class OpenXRBindingModifier : public Resource {
GDCLASS(OpenXRBindingModifier, Resource);
protected:
static void _bind_methods();
GDVIRTUAL0RC_REQUIRED(String, _get_description)
GDVIRTUAL0R_REQUIRED(PackedByteArray, _get_ip_modification)
public:
virtual String get_description() const; // Returns the description shown in the editor
virtual PackedByteArray get_ip_modification(); // Return the XrBindingModificationsKHR binding modifier struct data used when calling xrSuggestInteractionProfileBindings
};
class OpenXRIPBindingModifier : public OpenXRBindingModifier {
GDCLASS(OpenXRIPBindingModifier, OpenXRBindingModifier);
protected:
friend class OpenXRInteractionProfile;
OpenXRInteractionProfile *interaction_profile = nullptr; // action belongs to this interaction profile
public:
OpenXRInteractionProfile *get_interaction_profile() const { return interaction_profile; }
};
class OpenXRActionBindingModifier : public OpenXRBindingModifier {
GDCLASS(OpenXRActionBindingModifier, OpenXRBindingModifier);
protected:
friend class OpenXRIPBinding;
OpenXRIPBinding *ip_binding = nullptr; // action belongs to this binding
public:
OpenXRIPBinding *get_ip_binding() const { return ip_binding; }
};
#endif // OPENXR_BINDING_MODIFIER_H

View file

@ -0,0 +1,93 @@
/**************************************************************************/
/* openxr_haptic_feedback.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_haptic_feedback.h"
////////////////////////////////////////////////////////////////////////////
// OpenXRHapticBase
void OpenXRHapticBase::_bind_methods() {
}
////////////////////////////////////////////////////////////////////////////
// OpenXRHapticVibration
void OpenXRHapticVibration::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_duration", "duration"), &OpenXRHapticVibration::set_duration);
ClassDB::bind_method(D_METHOD("get_duration"), &OpenXRHapticVibration::get_duration);
ADD_PROPERTY(PropertyInfo(Variant::INT, "duration"), "set_duration", "get_duration");
ClassDB::bind_method(D_METHOD("set_frequency", "frequency"), &OpenXRHapticVibration::set_frequency);
ClassDB::bind_method(D_METHOD("get_frequency"), &OpenXRHapticVibration::get_frequency);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "frequency"), "set_frequency", "get_frequency");
ClassDB::bind_method(D_METHOD("set_amplitude", "amplitude"), &OpenXRHapticVibration::set_amplitude);
ClassDB::bind_method(D_METHOD("get_amplitude"), &OpenXRHapticVibration::get_amplitude);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "amplitude", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_amplitude", "get_amplitude");
}
void OpenXRHapticVibration::set_duration(int64_t p_duration) {
haptic_vibration.duration = p_duration;
emit_changed();
}
int64_t OpenXRHapticVibration::get_duration() const {
return haptic_vibration.duration;
}
void OpenXRHapticVibration::set_frequency(float p_frequency) {
haptic_vibration.frequency = p_frequency;
emit_changed();
}
float OpenXRHapticVibration::get_frequency() const {
return haptic_vibration.frequency;
}
void OpenXRHapticVibration::set_amplitude(float p_amplitude) {
haptic_vibration.amplitude = p_amplitude;
emit_changed();
}
float OpenXRHapticVibration::get_amplitude() const {
return haptic_vibration.amplitude;
}
const XrHapticBaseHeader *OpenXRHapticVibration::get_xr_structure() {
return (XrHapticBaseHeader *)&haptic_vibration;
}
OpenXRHapticVibration::OpenXRHapticVibration() {
haptic_vibration.type = XR_TYPE_HAPTIC_VIBRATION;
haptic_vibration.next = nullptr;
haptic_vibration.duration = -1;
haptic_vibration.frequency = 0.0;
haptic_vibration.amplitude = 1.0;
}

View file

@ -0,0 +1,72 @@
/**************************************************************************/
/* openxr_haptic_feedback.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_HAPTIC_FEEDBACK_H
#define OPENXR_HAPTIC_FEEDBACK_H
#include "core/io/resource.h"
#include <openxr/openxr.h>
class OpenXRHapticBase : public Resource {
GDCLASS(OpenXRHapticBase, Resource);
private:
protected:
static void _bind_methods();
public:
virtual const XrHapticBaseHeader *get_xr_structure() = 0;
};
class OpenXRHapticVibration : public OpenXRHapticBase {
GDCLASS(OpenXRHapticVibration, OpenXRHapticBase);
private:
XrHapticVibration haptic_vibration;
protected:
static void _bind_methods();
public:
void set_duration(int64_t p_duration);
int64_t get_duration() const;
void set_frequency(float p_frequency);
float get_frequency() const;
void set_amplitude(float p_amplitude);
float get_amplitude() const;
virtual const XrHapticBaseHeader *get_xr_structure() override;
OpenXRHapticVibration();
};
#endif // OPENXR_HAPTIC_FEEDBACK_H

View file

@ -35,28 +35,41 @@ void OpenXRIPBinding::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_action"), &OpenXRIPBinding::get_action);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "action", PROPERTY_HINT_RESOURCE_TYPE, "OpenXRAction"), "set_action", "get_action");
ClassDB::bind_method(D_METHOD("get_path_count"), &OpenXRIPBinding::get_path_count);
ClassDB::bind_method(D_METHOD("set_binding_path", "binding_path"), &OpenXRIPBinding::set_binding_path);
ClassDB::bind_method(D_METHOD("get_binding_path"), &OpenXRIPBinding::get_binding_path);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "binding_path"), "set_binding_path", "get_binding_path");
ClassDB::bind_method(D_METHOD("get_binding_modifier_count"), &OpenXRIPBinding::get_binding_modifier_count);
ClassDB::bind_method(D_METHOD("get_binding_modifier", "index"), &OpenXRIPBinding::get_binding_modifier);
ClassDB::bind_method(D_METHOD("set_binding_modifiers", "binding_modifiers"), &OpenXRIPBinding::set_binding_modifiers);
ClassDB::bind_method(D_METHOD("get_binding_modifiers"), &OpenXRIPBinding::get_binding_modifiers);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "binding_modifiers", PROPERTY_HINT_RESOURCE_TYPE, "OpenXRActionBindingModifier", PROPERTY_USAGE_NO_EDITOR), "set_binding_modifiers", "get_binding_modifiers");
// Deprecated
#ifndef DISABLE_DEPRECATED
ClassDB::bind_method(D_METHOD("set_paths", "paths"), &OpenXRIPBinding::set_paths);
ClassDB::bind_method(D_METHOD("get_paths"), &OpenXRIPBinding::get_paths);
ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "paths"), "set_paths", "get_paths");
ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "paths", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_paths", "get_paths");
ClassDB::bind_method(D_METHOD("get_path_count"), &OpenXRIPBinding::get_path_count);
ClassDB::bind_method(D_METHOD("has_path", "path"), &OpenXRIPBinding::has_path);
ClassDB::bind_method(D_METHOD("add_path", "path"), &OpenXRIPBinding::add_path);
ClassDB::bind_method(D_METHOD("remove_path", "path"), &OpenXRIPBinding::remove_path);
#endif // DISABLE_DEPRECATED
}
Ref<OpenXRIPBinding> OpenXRIPBinding::new_binding(const Ref<OpenXRAction> p_action, const char *p_paths) {
Ref<OpenXRIPBinding> OpenXRIPBinding::new_binding(const Ref<OpenXRAction> p_action, const String &p_binding_path) {
// This is a helper function to help build our default action sets
Ref<OpenXRIPBinding> binding;
binding.instantiate();
binding->set_action(p_action);
binding->parse_paths(String(p_paths));
binding->set_binding_path(p_binding_path);
return binding;
}
void OpenXRIPBinding::set_action(const Ref<OpenXRAction> p_action) {
void OpenXRIPBinding::set_action(const Ref<OpenXRAction> &p_action) {
action = p_action;
emit_changed();
}
@ -65,41 +78,136 @@ Ref<OpenXRAction> OpenXRIPBinding::get_action() const {
return action;
}
int OpenXRIPBinding::get_path_count() const {
return paths.size();
}
void OpenXRIPBinding::set_paths(const PackedStringArray p_paths) {
paths = p_paths;
void OpenXRIPBinding::set_binding_path(const String &path) {
binding_path = path;
emit_changed();
}
PackedStringArray OpenXRIPBinding::get_paths() const {
String OpenXRIPBinding::get_binding_path() const {
return binding_path;
}
int OpenXRIPBinding::get_binding_modifier_count() const {
return binding_modifiers.size();
}
Ref<OpenXRActionBindingModifier> OpenXRIPBinding::get_binding_modifier(int p_index) const {
ERR_FAIL_INDEX_V(p_index, binding_modifiers.size(), nullptr);
return binding_modifiers[p_index];
}
void OpenXRIPBinding::clear_binding_modifiers() {
// Binding modifiers held within our interaction profile set should be released and destroyed but just in case they are still used some where else.
if (binding_modifiers.is_empty()) {
return;
}
for (int i = 0; i < binding_modifiers.size(); i++) {
Ref<OpenXRActionBindingModifier> binding_modifier = binding_modifiers[i];
binding_modifier->ip_binding = nullptr;
}
binding_modifiers.clear();
emit_changed();
}
void OpenXRIPBinding::set_binding_modifiers(const Array &p_binding_modifiers) {
clear_binding_modifiers();
// Any binding modifier not retained in p_binding_modifiers should be freed automatically, those held within our Array will have be relinked to our interaction profile.
for (int i = 0; i < p_binding_modifiers.size(); i++) {
// Add them anew so we verify our binding modifier pointer.
add_binding_modifier(p_binding_modifiers[i]);
}
}
Array OpenXRIPBinding::get_binding_modifiers() const {
Array ret;
for (const Ref<OpenXRActionBindingModifier> &binding_modifier : binding_modifiers) {
ret.push_back(binding_modifier);
}
return ret;
}
void OpenXRIPBinding::add_binding_modifier(const Ref<OpenXRActionBindingModifier> &p_binding_modifier) {
ERR_FAIL_COND(p_binding_modifier.is_null());
if (!binding_modifiers.has(p_binding_modifier)) {
if (p_binding_modifier->ip_binding && p_binding_modifier->ip_binding != this) {
// Binding modifier should only relate to our binding.
p_binding_modifier->ip_binding->remove_binding_modifier(p_binding_modifier);
}
p_binding_modifier->ip_binding = this;
binding_modifiers.push_back(p_binding_modifier);
emit_changed();
}
}
void OpenXRIPBinding::remove_binding_modifier(const Ref<OpenXRActionBindingModifier> &p_binding_modifier) {
int idx = binding_modifiers.find(p_binding_modifier);
if (idx != -1) {
binding_modifiers.remove_at(idx);
ERR_FAIL_COND_MSG(p_binding_modifier->ip_binding != this, "Removing binding modifier that belongs to this binding but had incorrect binding pointer."); // This should never happen!
p_binding_modifier->ip_binding = nullptr;
emit_changed();
}
}
#ifndef DISABLE_DEPRECATED
void OpenXRIPBinding::set_paths(const PackedStringArray p_paths) { // Deprecated, but needed for loading old action maps.
// Fallback logic, this should ONLY be called when loading older action maps.
// We'll parse this momentarily and extract individual bindings.
binding_path = "";
for (const String &path : p_paths) {
if (!binding_path.is_empty()) {
binding_path += ",";
}
binding_path += path;
}
}
PackedStringArray OpenXRIPBinding::get_paths() const { // Deprecated, but needed for converting old action maps.
// Fallback logic, return an array.
// If we just loaded an old action map from disc, this will be a comma separated list of actions.
// Once parsed there should be only one path in our array.
PackedStringArray paths = binding_path.split(",", false);
return paths;
}
void OpenXRIPBinding::parse_paths(const String p_paths) {
paths = p_paths.split(",", false);
int OpenXRIPBinding::get_path_count() const { // Deprecated.
// Fallback logic, we only have one entry.
return binding_path.is_empty() ? 0 : 1;
}
bool OpenXRIPBinding::has_path(const String p_path) const { // Deprecated.
// Fallback logic, return true if this is our path.
return binding_path == p_path;
}
void OpenXRIPBinding::add_path(const String p_path) { // Deprecated.
// Fallback logic, only assign first time this is called.
if (binding_path != p_path) {
ERR_FAIL_COND_MSG(!binding_path.is_empty(), "Method add_path has been deprecated. A binding path was already set, create separate binding resources for each path and use set_binding_path instead.");
binding_path = p_path;
emit_changed();
}
}
void OpenXRIPBinding::remove_path(const String p_path) { // Deprecated.
ERR_FAIL_COND_MSG(binding_path != p_path, "Method remove_path has been deprecated. Attempt at removing a different binding path, remove the correct binding record from the interaction profile instead.");
// Fallback logic, clear if this is our path.
binding_path = p_path;
emit_changed();
}
bool OpenXRIPBinding::has_path(const String p_path) const {
return paths.has(p_path);
}
void OpenXRIPBinding::add_path(const String p_path) {
if (!paths.has(p_path)) {
paths.push_back(p_path);
emit_changed();
}
}
void OpenXRIPBinding::remove_path(const String p_path) {
if (paths.has(p_path)) {
paths.erase(p_path);
emit_changed();
}
}
#endif // DISABLE_DEPRECATED
OpenXRIPBinding::~OpenXRIPBinding() {
action.unref();
@ -115,6 +223,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, "OpenXRIPBindingModifier", PROPERTY_USAGE_NO_EDITOR), "set_binding_modifiers", "get_binding_modifiers");
}
Ref<OpenXRInteractionProfile> OpenXRInteractionProfile::new_profile(const char *p_input_profile_path) {
@ -150,10 +264,19 @@ Ref<OpenXRIPBinding> OpenXRInteractionProfile::get_binding(int p_index) const {
return bindings[p_index];
}
void OpenXRInteractionProfile::set_bindings(Array p_bindings) {
// TODO add check here that our bindings don't contain duplicate actions
void OpenXRInteractionProfile::set_bindings(const Array &p_bindings) {
bindings.clear();
for (Ref<OpenXRIPBinding> binding : p_bindings) {
String binding_path = binding->get_binding_path();
if (binding_path.find_char(',') >= 0) {
// Convert old binding approach to new...
add_new_binding(binding->get_action(), binding_path);
} else {
add_binding(binding);
}
}
bindings = p_bindings;
emit_changed();
}
@ -161,10 +284,9 @@ Array OpenXRInteractionProfile::get_bindings() const {
return bindings;
}
Ref<OpenXRIPBinding> OpenXRInteractionProfile::get_binding_for_action(const Ref<OpenXRAction> p_action) const {
for (int i = 0; i < bindings.size(); i++) {
Ref<OpenXRIPBinding> binding = bindings[i];
if (binding->get_action() == p_action) {
Ref<OpenXRIPBinding> OpenXRInteractionProfile::find_binding(const Ref<OpenXRAction> &p_action, const String &p_binding_path) const {
for (Ref<OpenXRIPBinding> binding : bindings) {
if (binding->get_action() == p_action && binding->get_binding_path() == p_binding_path) {
return binding;
}
}
@ -172,18 +294,30 @@ Ref<OpenXRIPBinding> OpenXRInteractionProfile::get_binding_for_action(const Ref<
return Ref<OpenXRIPBinding>();
}
void OpenXRInteractionProfile::add_binding(Ref<OpenXRIPBinding> p_binding) {
Vector<Ref<OpenXRIPBinding>> OpenXRInteractionProfile::get_bindings_for_action(const Ref<OpenXRAction> &p_action) const {
Vector<Ref<OpenXRIPBinding>> ret_bindings;
for (Ref<OpenXRIPBinding> binding : bindings) {
if (binding->get_action() == p_action) {
ret_bindings.push_back(binding);
}
}
return ret_bindings;
}
void OpenXRInteractionProfile::add_binding(const Ref<OpenXRIPBinding> &p_binding) {
ERR_FAIL_COND(p_binding.is_null());
if (!bindings.has(p_binding)) {
ERR_FAIL_COND_MSG(get_binding_for_action(p_binding->get_action()).is_valid(), "There is already a binding for this action in this interaction profile");
ERR_FAIL_COND_MSG(find_binding(p_binding->get_action(), p_binding->get_binding_path()).is_valid(), "There is already a binding for this action and binding path in this interaction profile.");
bindings.push_back(p_binding);
emit_changed();
}
}
void OpenXRInteractionProfile::remove_binding(Ref<OpenXRIPBinding> p_binding) {
void OpenXRInteractionProfile::remove_binding(const Ref<OpenXRIPBinding> &p_binding) {
int idx = bindings.find(p_binding);
if (idx != -1) {
bindings.remove_at(idx);
@ -191,14 +325,18 @@ void OpenXRInteractionProfile::remove_binding(Ref<OpenXRIPBinding> p_binding) {
}
}
void OpenXRInteractionProfile::add_new_binding(const Ref<OpenXRAction> p_action, const char *p_paths) {
void OpenXRInteractionProfile::add_new_binding(const Ref<OpenXRAction> &p_action, const String &p_paths) {
// This is a helper function to help build our default action sets
Ref<OpenXRIPBinding> binding = OpenXRIPBinding::new_binding(p_action, p_paths);
add_binding(binding);
PackedStringArray paths = p_paths.split(",", false);
for (const String &path : paths) {
Ref<OpenXRIPBinding> binding = OpenXRIPBinding::new_binding(p_action, path);
add_binding(binding);
}
}
void OpenXRInteractionProfile::remove_binding_for_action(const Ref<OpenXRAction> p_action) {
void OpenXRInteractionProfile::remove_binding_for_action(const Ref<OpenXRAction> &p_action) {
for (int i = bindings.size() - 1; i >= 0; i--) {
Ref<OpenXRIPBinding> binding = bindings[i];
if (binding->get_action() == p_action) {
@ -207,7 +345,7 @@ void OpenXRInteractionProfile::remove_binding_for_action(const Ref<OpenXRAction>
}
}
bool OpenXRInteractionProfile::has_binding_for_action(const Ref<OpenXRAction> p_action) {
bool OpenXRInteractionProfile::has_binding_for_action(const Ref<OpenXRAction> &p_action) {
for (int i = bindings.size() - 1; i >= 0; i--) {
Ref<OpenXRIPBinding> binding = bindings[i];
if (binding->get_action() == p_action) {
@ -218,6 +356,76 @@ bool OpenXRInteractionProfile::has_binding_for_action(const Ref<OpenXRAction> p_
return false;
}
int OpenXRInteractionProfile::get_binding_modifier_count() const {
return binding_modifiers.size();
}
Ref<OpenXRIPBindingModifier> 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::clear_binding_modifiers() {
// Binding modifiers held within our interaction profile set should be released and destroyed but just in case they are still used some where else.
if (binding_modifiers.is_empty()) {
return;
}
for (int i = 0; i < binding_modifiers.size(); i++) {
Ref<OpenXRIPBindingModifier> binding_modifier = binding_modifiers[i];
binding_modifier->interaction_profile = nullptr;
}
binding_modifiers.clear();
emit_changed();
}
void OpenXRInteractionProfile::set_binding_modifiers(const Array &p_binding_modifiers) {
clear_binding_modifiers();
// Any binding modifier not retained in p_binding_modifiers should be freed automatically, those held within our Array will have be relinked to our interaction profile.
for (int i = 0; i < p_binding_modifiers.size(); i++) {
// Add them anew so we verify our binding modifier pointer.
add_binding_modifier(p_binding_modifiers[i]);
}
}
Array OpenXRInteractionProfile::get_binding_modifiers() const {
Array ret;
for (const Ref<OpenXRIPBindingModifier> &binding_modifier : binding_modifiers) {
ret.push_back(binding_modifier);
}
return ret;
}
void OpenXRInteractionProfile::add_binding_modifier(const Ref<OpenXRIPBindingModifier> &p_binding_modifier) {
ERR_FAIL_COND(p_binding_modifier.is_null());
if (!binding_modifiers.has(p_binding_modifier)) {
if (p_binding_modifier->interaction_profile && p_binding_modifier->interaction_profile != this) {
// Binding modifier should only relate to our interaction profile.
p_binding_modifier->interaction_profile->remove_binding_modifier(p_binding_modifier);
}
p_binding_modifier->interaction_profile = this;
binding_modifiers.push_back(p_binding_modifier);
emit_changed();
}
}
void OpenXRInteractionProfile::remove_binding_modifier(const Ref<OpenXRIPBindingModifier> &p_binding_modifier) {
int idx = binding_modifiers.find(p_binding_modifier);
if (idx != -1) {
binding_modifiers.remove_at(idx);
ERR_FAIL_COND_MSG(p_binding_modifier->interaction_profile != this, "Removing binding modifier that belongs to this interaction profile but had incorrect interaction profile pointer."); // This should never happen!
p_binding_modifier->interaction_profile = nullptr;
emit_changed();
}
}
OpenXRInteractionProfile::~OpenXRInteractionProfile() {
bindings.clear();
clear_binding_modifiers();
}

View file

@ -32,35 +32,57 @@
#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"
class OpenXRActionMap;
class OpenXRIPBinding : public Resource {
GDCLASS(OpenXRIPBinding, Resource);
private:
Ref<OpenXRAction> action;
PackedStringArray paths;
String binding_path;
Vector<Ref<OpenXRActionBindingModifier>> binding_modifiers;
protected:
friend class OpenXRActionMap;
OpenXRActionMap *action_map = nullptr;
static void _bind_methods();
public:
static Ref<OpenXRIPBinding> new_binding(const Ref<OpenXRAction> p_action, const char *p_paths); // Helper function for adding a new binding
static Ref<OpenXRIPBinding> new_binding(const Ref<OpenXRAction> p_action, const String &p_binding_path); // Helper function for adding a new binding.
void set_action(const Ref<OpenXRAction> p_action); // Set the action for this binding
Ref<OpenXRAction> get_action() const; // Get the action for this binding
OpenXRActionMap *get_action_map() { return action_map; } // Return the action map we're a part of.
int get_path_count() const; // Get the number of io paths
void set_paths(const PackedStringArray p_paths); // Set our paths (for loading from resource)
PackedStringArray get_paths() const; // Get our paths (for saving to resource)
void set_action(const Ref<OpenXRAction> &p_action); // Set the action for this binding.
Ref<OpenXRAction> get_action() const; // Get the action for this binding.
void parse_paths(const String p_paths); // Parse a comma separated string of io paths.
void set_binding_path(const String &path);
String get_binding_path() const;
bool has_path(const String p_path) const; // Has this io path
void add_path(const String p_path); // Add an io path
void remove_path(const String p_path); // Remove an io path
int get_binding_modifier_count() const; // Retrieve the number of binding modifiers in this profile path
Ref<OpenXRActionBindingModifier> get_binding_modifier(int p_index) const;
void clear_binding_modifiers(); // Remove all binding modifiers
void set_binding_modifiers(const 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)
void add_binding_modifier(const Ref<OpenXRActionBindingModifier> &p_binding_modifier); // Add a binding modifier object
void remove_binding_modifier(const Ref<OpenXRActionBindingModifier> &p_binding_modifier); // Remove a binding modifier object
// Deprecated.
#ifndef DISABLE_DEPRECATED
void set_paths(const PackedStringArray p_paths); // Set our paths (for loading from resource), needed for loading old action maps.
PackedStringArray get_paths() const; // Get our paths (for saving to resource), needed for converted old action maps.
int get_path_count() const; // Get the number of io paths.
bool has_path(const String p_path) const; // Has this io path.
void add_path(const String p_path); // Add an io path.
void remove_path(const String p_path); // Remove an io path.
#endif // DISABLE_DEPRECATED
// TODO add validation that we can display in the interface that checks if no two paths belong to the same top level path
@ -73,28 +95,45 @@ class OpenXRInteractionProfile : public Resource {
private:
String interaction_profile_path;
Array bindings;
Vector<Ref<OpenXRIPBindingModifier>> binding_modifiers;
protected:
friend class OpenXRActionMap;
OpenXRActionMap *action_map = nullptr;
static void _bind_methods();
public:
static Ref<OpenXRInteractionProfile> new_profile(const char *p_input_profile_path); // Helper function to create a new interaction profile
OpenXRActionMap *get_action_map() { return action_map; }
void set_interaction_profile_path(const String p_input_profile_path); // Set our input profile path
String get_interaction_profile_path() const; // get our input profile path
int get_binding_count() const; // Retrieve the number of bindings in this profile path
Ref<OpenXRIPBinding> get_binding(int p_index) const;
void set_bindings(Array p_bindings); // Set the bindings (for loading from a resource)
void set_bindings(const Array &p_bindings); // Set the bindings (for loading from a resource)
Array get_bindings() const; // Get the bindings (for saving to a resource)
Ref<OpenXRIPBinding> get_binding_for_action(const Ref<OpenXRAction> p_action) const; // Get our binding record for a given action
void add_binding(Ref<OpenXRIPBinding> p_binding); // Add a binding object
void remove_binding(Ref<OpenXRIPBinding> p_binding); // Remove a binding object
Ref<OpenXRIPBinding> find_binding(const Ref<OpenXRAction> &p_action, const String &p_binding_path) const; // Get our binding record
Vector<Ref<OpenXRIPBinding>> get_bindings_for_action(const Ref<OpenXRAction> &p_action) const; // Get our binding record for a given action
void add_binding(const Ref<OpenXRIPBinding> &p_binding); // Add a binding object
void remove_binding(const Ref<OpenXRIPBinding> &p_binding); // Remove a binding object
void add_new_binding(const Ref<OpenXRAction> p_action, const char *p_paths); // Create a new binding for this profile
void 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
void add_new_binding(const Ref<OpenXRAction> &p_action, const String &p_paths); // Create a new binding for this profile
void remove_binding_for_action(const Ref<OpenXRAction> &p_action); // Remove all bindings for this action
bool has_binding_for_action(const Ref<OpenXRAction> &p_action); // Returns true if we have a binding for this action
int get_binding_modifier_count() const; // Retrieve the number of binding modifiers in this profile path
Ref<OpenXRIPBindingModifier> get_binding_modifier(int p_index) const;
void clear_binding_modifiers(); // Remove all binding modifiers
void set_binding_modifiers(const 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)
void add_binding_modifier(const Ref<OpenXRIPBindingModifier> &p_binding_modifier); // Add a binding modifier object
void remove_binding_modifier(const Ref<OpenXRIPBindingModifier> &p_binding_modifier); // Remove a binding modifier object
~OpenXRInteractionProfile();
};

View file

@ -93,9 +93,9 @@ void OpenXRInteractionProfileMetadata::register_io_path(const String &p_interact
ERR_FAIL_COND_MSG(!has_interaction_profile(p_interaction_profile), "Unknown interaction profile " + p_interaction_profile);
ERR_FAIL_COND_MSG(!has_top_level_path(p_toplevel_path), "Unknown top level path " + p_toplevel_path);
for (int i = 0; i < interaction_profiles.size(); i++) {
if (interaction_profiles[i].openxr_path == p_interaction_profile) {
ERR_FAIL_COND_MSG(interaction_profiles[i].has_io_path(p_openxr_path), p_interaction_profile + " already has io path " + p_openxr_path + " registered!");
for (InteractionProfile &interaction_profile : interaction_profiles) {
if (interaction_profile.openxr_path == p_interaction_profile) {
ERR_FAIL_COND_MSG(interaction_profile.has_io_path(p_openxr_path), p_interaction_profile + " already has io path " + p_openxr_path + " registered!");
IOPath new_io_path = {
p_display_name,
@ -105,7 +105,7 @@ void OpenXRInteractionProfileMetadata::register_io_path(const String &p_interact
p_action_type
};
interaction_profiles.ptrw()[i].io_paths.push_back(new_io_path);
interaction_profile.io_paths.push_back(new_io_path);
}
}
}
@ -141,8 +141,8 @@ String OpenXRInteractionProfileMetadata::get_top_level_extension(const String p_
}
bool OpenXRInteractionProfileMetadata::has_interaction_profile(const String p_openxr_path) const {
for (int i = 0; i < interaction_profiles.size(); i++) {
if (interaction_profiles[i].openxr_path == p_openxr_path) {
for (const InteractionProfile &interaction_profile : interaction_profiles) {
if (interaction_profile.openxr_path == p_openxr_path) {
return true;
}
}
@ -151,9 +151,9 @@ bool OpenXRInteractionProfileMetadata::has_interaction_profile(const String p_op
}
String OpenXRInteractionProfileMetadata::get_interaction_profile_extension(const String p_openxr_path) const {
for (int i = 0; i < interaction_profiles.size(); i++) {
if (interaction_profiles[i].openxr_path == p_openxr_path) {
return interaction_profiles[i].openxr_extension_name;
for (const InteractionProfile &interaction_profile : interaction_profiles) {
if (interaction_profile.openxr_path == p_openxr_path) {
return interaction_profile.openxr_extension_name;
}
}
@ -161,9 +161,9 @@ String OpenXRInteractionProfileMetadata::get_interaction_profile_extension(const
}
const OpenXRInteractionProfileMetadata::InteractionProfile *OpenXRInteractionProfileMetadata::get_profile(const String p_openxr_path) const {
for (int i = 0; i < interaction_profiles.size(); i++) {
if (interaction_profiles[i].openxr_path == p_openxr_path) {
return &interaction_profiles[i];
for (const InteractionProfile &interaction_profile : interaction_profiles) {
if (interaction_profile.openxr_path == p_openxr_path) {
return &interaction_profile;
}
}
@ -202,8 +202,8 @@ const OpenXRInteractionProfileMetadata::IOPath *OpenXRInteractionProfileMetadata
PackedStringArray OpenXRInteractionProfileMetadata::get_interaction_profile_paths() const {
PackedStringArray arr;
for (int i = 0; i < interaction_profiles.size(); i++) {
arr.push_back(interaction_profiles[i].openxr_path);
for (const InteractionProfile &interaction_profile : interaction_profiles) {
arr.push_back(interaction_profile.openxr_path);
}
return arr;
@ -225,179 +225,164 @@ void OpenXRInteractionProfileMetadata::_register_core_metadata() {
register_top_level_path("Gamepad", "/user/gamepad", "");
register_top_level_path("Treadmill", "/user/treadmill", "");
// Fallback Khronos simple controller
register_interaction_profile("Simple controller", "/interaction_profiles/khr/simple_controller", "");
register_io_path("/interaction_profiles/khr/simple_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/khr/simple_controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/khr/simple_controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/khr/simple_controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/khr/simple_controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/khr/simple_controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
{ // Fallback Khronos simple controller
const String profile_path = "/interaction_profiles/khr/simple_controller";
register_interaction_profile("Simple controller", profile_path, "");
for (const String user_path : { "/user/hand/left", "/user/hand/right" }) {
register_io_path(profile_path, "Grip pose", user_path, user_path + "/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path(profile_path, "Aim pose", user_path, user_path + "/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path(profile_path, "Palm pose", user_path, user_path + "/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/khr/simple_controller", "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/khr/simple_controller", "Menu click", "/user/hand/right", "/user/hand/right/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/khr/simple_controller", "Select click", "/user/hand/left", "/user/hand/left/input/select/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/khr/simple_controller", "Select click", "/user/hand/right", "/user/hand/right/input/select/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Menu click", user_path, user_path + "/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Select click", user_path, user_path + "/input/select/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/khr/simple_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
register_io_path("/interaction_profiles/khr/simple_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
register_io_path(profile_path, "Haptic output", user_path, user_path + "/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
}
}
// Original HTC Vive wands
register_interaction_profile("HTC Vive wand", "/interaction_profiles/htc/vive_controller", "");
register_io_path("/interaction_profiles/htc/vive_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/htc/vive_controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/htc/vive_controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/htc/vive_controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/htc/vive_controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/htc/vive_controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
{ // Original HTC Vive wands
const String profile_path = "/interaction_profiles/htc/vive_controller";
register_interaction_profile("HTC Vive wand", profile_path, "");
for (const String user_path : { "/user/hand/left", "/user/hand/right" }) {
register_io_path(profile_path, "Grip pose", user_path, user_path + "/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path(profile_path, "Aim pose", user_path, user_path + "/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path(profile_path, "Palm pose", user_path, user_path + "/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/htc/vive_controller", "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/htc/vive_controller", "Menu click", "/user/hand/right", "/user/hand/right/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/htc/vive_controller", "System click", "/user/hand/left", "/user/hand/left/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/htc/vive_controller", "System click", "/user/hand/right", "/user/hand/right/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Menu click", user_path, user_path + "/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "System click", user_path, user_path + "/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/htc/vive_controller", "Trigger", "/user/hand/left", "/user/hand/left/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
register_io_path("/interaction_profiles/htc/vive_controller", "Trigger click", "/user/hand/left", "/user/hand/left/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/htc/vive_controller", "Trigger", "/user/hand/right", "/user/hand/right/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
register_io_path("/interaction_profiles/htc/vive_controller", "Trigger click", "/user/hand/right", "/user/hand/right/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trigger", user_path, user_path + "/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
register_io_path(profile_path, "Trigger click", user_path, user_path + "/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/htc/vive_controller", "Squeeze click", "/user/hand/left", "/user/hand/left/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/htc/vive_controller", "Squeeze click", "/user/hand/right", "/user/hand/right/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Squeeze click", user_path, user_path + "/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/htc/vive_controller", "Trackpad", "/user/hand/left", "/user/hand/left/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
register_io_path("/interaction_profiles/htc/vive_controller", "Trackpad click", "/user/hand/left", "/user/hand/left/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/htc/vive_controller", "Trackpad touch", "/user/hand/left", "/user/hand/left/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/htc/vive_controller", "Trackpad", "/user/hand/right", "/user/hand/right/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
register_io_path("/interaction_profiles/htc/vive_controller", "Trackpad click", "/user/hand/right", "/user/hand/right/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/htc/vive_controller", "Trackpad touch", "/user/hand/right", "/user/hand/right/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trackpad", user_path, user_path + "/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
register_io_path(profile_path, "Trackpad click", user_path, user_path + "/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trackpad touch", user_path, user_path + "/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trackpad Dpad Up", user_path, user_path + "/input/trackpad/dpad_up", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trackpad Dpad Down", user_path, user_path + "/input/trackpad/dpad_down", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trackpad Dpad Left", user_path, user_path + "/input/trackpad/dpad_left", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trackpad Dpad Right", user_path, user_path + "/input/trackpad/dpad_right", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trackpad Dpad Center", user_path, user_path + "/input/trackpad/dpad_center", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/htc/vive_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
register_io_path("/interaction_profiles/htc/vive_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
register_io_path(profile_path, "Haptic output", user_path, user_path + "/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
}
}
// Microsoft motion controller (original WMR controllers)
register_interaction_profile("MS Motion controller", "/interaction_profiles/microsoft/motion_controller", "");
register_io_path("/interaction_profiles/microsoft/motion_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
{ // Microsoft motion controller (original WMR controllers)
const String profile_path = "/interaction_profiles/microsoft/motion_controller";
register_interaction_profile("MS Motion controller", profile_path, "");
for (const String user_path : { "/user/hand/left", "/user/hand/right" }) {
register_io_path(profile_path, "Grip pose", user_path, user_path + "/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path(profile_path, "Aim pose", user_path, user_path + "/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path(profile_path, "Palm pose", user_path, user_path + "/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Menu click", "/user/hand/right", "/user/hand/right/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Menu click", user_path, user_path + "/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Trigger", "/user/hand/left", "/user/hand/left/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Trigger click", "/user/hand/left", "/user/hand/left/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Trigger", "/user/hand/right", "/user/hand/right/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Trigger click", "/user/hand/right", "/user/hand/right/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trigger", user_path, user_path + "/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
register_io_path(profile_path, "Trigger click", user_path, user_path + "/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Squeeze click", "/user/hand/left", "/user/hand/left/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Squeeze click", "/user/hand/right", "/user/hand/right/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Squeeze click", user_path, user_path + "/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Thumbstick", "/user/hand/left", "/user/hand/left/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Thumbstick click", "/user/hand/left", "/user/hand/left/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Thumbstick", "/user/hand/right", "/user/hand/right/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Thumbstick click", "/user/hand/right", "/user/hand/right/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Thumbstick", user_path, user_path + "/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
register_io_path(profile_path, "Thumbstick click", user_path, user_path + "/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Thumbstick Dpad Up", user_path, user_path + "/input/thumbstick/dpad_up", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Thumbstick Dpad Down", user_path, user_path + "/input/thumbstick/dpad_down", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Thumbstick Dpad Left", user_path, user_path + "/input/thumbstick/dpad_left", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Thumbstick Dpad Right", user_path, user_path + "/input/thumbstick/dpad_right", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Trackpad", "/user/hand/left", "/user/hand/left/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Trackpad click", "/user/hand/left", "/user/hand/left/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Trackpad touch", "/user/hand/left", "/user/hand/left/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Trackpad", "/user/hand/right", "/user/hand/right/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Trackpad click", "/user/hand/right", "/user/hand/right/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Trackpad touch", "/user/hand/right", "/user/hand/right/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trackpad", user_path, user_path + "/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
register_io_path(profile_path, "Trackpad click", user_path, user_path + "/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trackpad touch", user_path, user_path + "/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trackpad Dpad Up", user_path, user_path + "/input/trackpad/dpad_up", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trackpad Dpad Down", user_path, user_path + "/input/trackpad/dpad_down", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trackpad Dpad Left", user_path, user_path + "/input/trackpad/dpad_left", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trackpad Dpad Right", user_path, user_path + "/input/trackpad/dpad_right", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trackpad Dpad Center", user_path, user_path + "/input/trackpad/dpad_center", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
register_io_path("/interaction_profiles/microsoft/motion_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
register_io_path(profile_path, "Haptic output", user_path, user_path + "/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
}
}
// Meta touch controller (original touch controllers, Quest 1 and Quest 2 controllers)
register_interaction_profile("Touch controller", "/interaction_profiles/oculus/touch_controller", "");
register_io_path("/interaction_profiles/oculus/touch_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/oculus/touch_controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/oculus/touch_controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/oculus/touch_controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/oculus/touch_controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/oculus/touch_controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
{ // Meta touch controller (original touch controllers, Quest 1 and Quest 2 controllers)
const String profile_path = "/interaction_profiles/oculus/touch_controller";
register_interaction_profile("Touch controller", profile_path, "");
for (const String user_path : { "/user/hand/left", "/user/hand/right" }) {
register_io_path(profile_path, "Grip pose", user_path, user_path + "/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path(profile_path, "Aim pose", user_path, user_path + "/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path(profile_path, "Palm pose", user_path, user_path + "/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/oculus/touch_controller", "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/oculus/touch_controller", "System click", "/user/hand/right", "/user/hand/right/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trigger", user_path, user_path + "/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
register_io_path(profile_path, "Trigger touch", user_path, user_path + "/input/trigger/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/oculus/touch_controller", "X click", "/user/hand/left", "/user/hand/left/input/x/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/oculus/touch_controller", "X touch", "/user/hand/left", "/user/hand/left/input/x/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/oculus/touch_controller", "Y click", "/user/hand/left", "/user/hand/left/input/y/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/oculus/touch_controller", "Y touch", "/user/hand/left", "/user/hand/left/input/y/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/oculus/touch_controller", "A click", "/user/hand/right", "/user/hand/right/input/a/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/oculus/touch_controller", "A touch", "/user/hand/right", "/user/hand/right/input/a/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/oculus/touch_controller", "B click", "/user/hand/right", "/user/hand/right/input/b/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/oculus/touch_controller", "B touch", "/user/hand/right", "/user/hand/right/input/b/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Squeeze", user_path, user_path + "/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
register_io_path("/interaction_profiles/oculus/touch_controller", "Trigger", "/user/hand/left", "/user/hand/left/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
register_io_path("/interaction_profiles/oculus/touch_controller", "Trigger touch", "/user/hand/left", "/user/hand/left/input/trigger/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/oculus/touch_controller", "Trigger", "/user/hand/right", "/user/hand/right/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
register_io_path("/interaction_profiles/oculus/touch_controller", "Trigger touch", "/user/hand/right", "/user/hand/right/input/trigger/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Thumbstick", user_path, user_path + "/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
register_io_path(profile_path, "Thumbstick click", user_path, user_path + "/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Thumbstick touch", user_path, user_path + "/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Thumbstick Dpad Up", user_path, user_path + "/input/thumbstick/dpad_up", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Thumbstick Dpad Down", user_path, user_path + "/input/thumbstick/dpad_down", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Thumbstick Dpad Left", user_path, user_path + "/input/thumbstick/dpad_left", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Thumbstick Dpad Right", user_path, user_path + "/input/thumbstick/dpad_right", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/oculus/touch_controller", "Squeeze", "/user/hand/left", "/user/hand/left/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
register_io_path("/interaction_profiles/oculus/touch_controller", "Squeeze", "/user/hand/right", "/user/hand/right/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
register_io_path(profile_path, "Thumbrest touch", user_path, user_path + "/input/thumbrest/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/oculus/touch_controller", "Thumbstick", "/user/hand/left", "/user/hand/left/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
register_io_path("/interaction_profiles/oculus/touch_controller", "Thumbstick click", "/user/hand/left", "/user/hand/left/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/oculus/touch_controller", "Thumbstick touch", "/user/hand/left", "/user/hand/left/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/oculus/touch_controller", "Thumbstick", "/user/hand/right", "/user/hand/right/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
register_io_path("/interaction_profiles/oculus/touch_controller", "Thumbstick click", "/user/hand/right", "/user/hand/right/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/oculus/touch_controller", "Thumbstick touch", "/user/hand/right", "/user/hand/right/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Haptic output", user_path, user_path + "/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
}
register_io_path("/interaction_profiles/oculus/touch_controller", "Thumbrest touch", "/user/hand/left", "/user/hand/left/input/thumbrest/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/oculus/touch_controller", "Thumbrest touch", "/user/hand/right", "/user/hand/right/input/thumbrest/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "System click", "/user/hand/right", "/user/hand/right/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/oculus/touch_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
register_io_path("/interaction_profiles/oculus/touch_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
register_io_path(profile_path, "X click", "/user/hand/left", "/user/hand/left/input/x/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "X touch", "/user/hand/left", "/user/hand/left/input/x/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Y click", "/user/hand/left", "/user/hand/left/input/y/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Y touch", "/user/hand/left", "/user/hand/left/input/y/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "A click", "/user/hand/right", "/user/hand/right/input/a/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "A touch", "/user/hand/right", "/user/hand/right/input/a/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "B click", "/user/hand/right", "/user/hand/right/input/b/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "B touch", "/user/hand/right", "/user/hand/right/input/b/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
}
// Valve Index controller
register_interaction_profile("Index controller", "/interaction_profiles/valve/index_controller", "");
register_io_path("/interaction_profiles/valve/index_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/valve/index_controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/valve/index_controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/valve/index_controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/valve/index_controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/valve/index_controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
{ // Valve Index controller
const String profile_path = "/interaction_profiles/valve/index_controller";
register_interaction_profile("Index controller", profile_path, "");
for (const String user_path : { "/user/hand/left", "/user/hand/right" }) {
register_io_path(profile_path, "Grip pose", user_path, user_path + "/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path(profile_path, "Aim pose", user_path, user_path + "/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
register_io_path(profile_path, "Palm pose", user_path, user_path + "/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE);
register_io_path("/interaction_profiles/valve/index_controller", "System click", "/user/hand/left", "/user/hand/left/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/valve/index_controller", "System click", "/user/hand/right", "/user/hand/right/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "System click", user_path, user_path + "/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/valve/index_controller", "A click", "/user/hand/left", "/user/hand/left/input/a/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/valve/index_controller", "A touch", "/user/hand/left", "/user/hand/left/input/a/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/valve/index_controller", "A click", "/user/hand/right", "/user/hand/right/input/a/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/valve/index_controller", "A touch", "/user/hand/right", "/user/hand/right/input/a/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/valve/index_controller", "B click", "/user/hand/left", "/user/hand/left/input/b/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/valve/index_controller", "B touch", "/user/hand/left", "/user/hand/left/input/b/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/valve/index_controller", "B click", "/user/hand/right", "/user/hand/right/input/b/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/valve/index_controller", "B touch", "/user/hand/right", "/user/hand/right/input/b/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "A click", user_path, user_path + "/input/a/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "A touch", user_path, user_path + "/input/a/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "B click", user_path, user_path + "/input/b/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "B touch", user_path, user_path + "/input/b/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/valve/index_controller", "Trigger", "/user/hand/left", "/user/hand/left/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
register_io_path("/interaction_profiles/valve/index_controller", "Trigger click", "/user/hand/left", "/user/hand/left/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/valve/index_controller", "Trigger touch", "/user/hand/left", "/user/hand/left/input/trigger/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/valve/index_controller", "Trigger", "/user/hand/right", "/user/hand/right/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
register_io_path("/interaction_profiles/valve/index_controller", "Trigger click", "/user/hand/right", "/user/hand/right/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/valve/index_controller", "Trigger touch", "/user/hand/right", "/user/hand/right/input/trigger/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trigger", user_path, user_path + "/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
register_io_path(profile_path, "Trigger click", user_path, user_path + "/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trigger touch", user_path, user_path + "/input/trigger/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/valve/index_controller", "Squeeze", "/user/hand/left", "/user/hand/left/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
register_io_path("/interaction_profiles/valve/index_controller", "Squeeze force", "/user/hand/left", "/user/hand/left/input/squeeze/force", "", OpenXRAction::OPENXR_ACTION_FLOAT);
register_io_path("/interaction_profiles/valve/index_controller", "Squeeze", "/user/hand/right", "/user/hand/right/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
register_io_path("/interaction_profiles/valve/index_controller", "Squeeze force", "/user/hand/right", "/user/hand/right/input/squeeze/force", "", OpenXRAction::OPENXR_ACTION_FLOAT);
register_io_path(profile_path, "Squeeze", user_path, user_path + "/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
register_io_path(profile_path, "Squeeze force", user_path, user_path + "/input/squeeze/force", "", OpenXRAction::OPENXR_ACTION_FLOAT);
register_io_path("/interaction_profiles/valve/index_controller", "Thumbstick", "/user/hand/left", "/user/hand/left/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
register_io_path("/interaction_profiles/valve/index_controller", "Thumbstick click", "/user/hand/left", "/user/hand/left/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/valve/index_controller", "Thumbstick touch", "/user/hand/left", "/user/hand/left/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/valve/index_controller", "Thumbstick", "/user/hand/right", "/user/hand/right/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
register_io_path("/interaction_profiles/valve/index_controller", "Thumbstick click", "/user/hand/right", "/user/hand/right/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/valve/index_controller", "Thumbstick touch", "/user/hand/right", "/user/hand/right/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Thumbstick", user_path, user_path + "/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
register_io_path(profile_path, "Thumbstick click", user_path, user_path + "/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Thumbstick touch", user_path, user_path + "/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Thumbstick Dpad Up", user_path, user_path + "/input/thumbstick/dpad_up", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Thumbstick Dpad Down", user_path, user_path + "/input/thumbstick/dpad_down", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Thumbstick Dpad Left", user_path, user_path + "/input/thumbstick/dpad_left", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Thumbstick Dpad Right", user_path, user_path + "/input/thumbstick/dpad_right", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/valve/index_controller", "Trackpad", "/user/hand/left", "/user/hand/left/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
register_io_path("/interaction_profiles/valve/index_controller", "Trackpad force", "/user/hand/left", "/user/hand/left/input/trackpad/force", "", OpenXRAction::OPENXR_ACTION_FLOAT);
register_io_path("/interaction_profiles/valve/index_controller", "Trackpad touch", "/user/hand/left", "/user/hand/left/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/valve/index_controller", "Trackpad", "/user/hand/right", "/user/hand/right/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
register_io_path("/interaction_profiles/valve/index_controller", "Trackpad force", "/user/hand/right", "/user/hand/right/input/trackpad/force", "", OpenXRAction::OPENXR_ACTION_FLOAT);
register_io_path("/interaction_profiles/valve/index_controller", "Trackpad touch", "/user/hand/right", "/user/hand/right/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trackpad", user_path, user_path + "/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2);
register_io_path(profile_path, "Trackpad force", user_path, user_path + "/input/trackpad/force", "", OpenXRAction::OPENXR_ACTION_FLOAT);
register_io_path(profile_path, "Trackpad touch", user_path, user_path + "/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trackpad Dpad Up", user_path, user_path + "/input/trackpad/dpad_up", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trackpad Dpad Down", user_path, user_path + "/input/trackpad/dpad_down", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trackpad Dpad Left", user_path, user_path + "/input/trackpad/dpad_left", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trackpad Dpad Right", user_path, user_path + "/input/trackpad/dpad_right", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path(profile_path, "Trackpad Dpad Center", user_path, user_path + "/input/trackpad/dpad_center", "XR_EXT_dpad_binding", OpenXRAction::OPENXR_ACTION_BOOL);
register_io_path("/interaction_profiles/valve/index_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
register_io_path("/interaction_profiles/valve/index_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
register_io_path(profile_path, "Haptic output", user_path, user_path + "/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
}
}
}