initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
This commit is contained in:
11
modules/openxr/action_map/SCsub
Normal file
11
modules/openxr/action_map/SCsub
Normal file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
Import("env_openxr")
|
||||
|
||||
module_obj = []
|
||||
|
||||
env_openxr.add_source_files(module_obj, "*.cpp")
|
||||
|
||||
env.modules_sources += module_obj
|
121
modules/openxr/action_map/openxr_action.cpp
Normal file
121
modules/openxr/action_map/openxr_action.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
/**************************************************************************/
|
||||
/* openxr_action.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_action.h"
|
||||
|
||||
#include "openxr_action_set.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::PACKED_STRING_ARRAY, "toplevel_paths"), "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;
|
||||
}
|
||||
|
||||
String OpenXRAction::get_name_with_set() const {
|
||||
String action_name = get_name();
|
||||
|
||||
if (action_set != nullptr) {
|
||||
action_name = action_set->get_name() + "/" + action_name;
|
||||
}
|
||||
|
||||
return action_name;
|
||||
}
|
||||
|
||||
void OpenXRAction::set_localized_name(const String p_localized_name) {
|
||||
localized_name = p_localized_name;
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
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;
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
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;
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
PackedStringArray OpenXRAction::get_toplevel_paths() const {
|
||||
return toplevel_paths;
|
||||
}
|
||||
|
||||
void OpenXRAction::add_toplevel_path(const String p_toplevel_path) {
|
||||
if (!toplevel_paths.has(p_toplevel_path)) {
|
||||
toplevel_paths.push_back(p_toplevel_path);
|
||||
emit_changed();
|
||||
}
|
||||
}
|
||||
|
||||
void OpenXRAction::rem_toplevel_path(const String p_toplevel_path) {
|
||||
if (toplevel_paths.has(p_toplevel_path)) {
|
||||
toplevel_paths.erase(p_toplevel_path);
|
||||
emit_changed();
|
||||
}
|
||||
}
|
||||
|
||||
void OpenXRAction::parse_toplevel_paths(const String p_toplevel_paths) {
|
||||
toplevel_paths = p_toplevel_paths.split(",", false);
|
||||
emit_changed();
|
||||
}
|
84
modules/openxr/action_map/openxr_action.h
Normal file
84
modules/openxr/action_map/openxr_action.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/**************************************************************************/
|
||||
/* openxr_action.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/io/resource.h"
|
||||
|
||||
class OpenXRActionSet;
|
||||
|
||||
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,
|
||||
OPENXR_ACTION_MAX
|
||||
};
|
||||
|
||||
private:
|
||||
String localized_name;
|
||||
ActionType action_type = OPENXR_ACTION_FLOAT;
|
||||
|
||||
PackedStringArray toplevel_paths;
|
||||
|
||||
protected:
|
||||
friend class OpenXRActionSet;
|
||||
|
||||
OpenXRActionSet *action_set = nullptr; // action belongs to this action set.
|
||||
|
||||
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); // Helper function to add and configure an action
|
||||
OpenXRActionSet *get_action_set() const { return action_set; } // Get the action set this action belongs to
|
||||
|
||||
String get_name_with_set() const; // Retrieve the name of this action as <action_set>/<action>
|
||||
|
||||
void set_localized_name(const String p_localized_name); // Set the localized name of this action
|
||||
String get_localized_name() const; // Get the localized name of this action
|
||||
|
||||
void set_action_type(const ActionType p_action_type); // Set the type of this action
|
||||
ActionType get_action_type() const; // Get the type of this action
|
||||
|
||||
void set_toplevel_paths(const PackedStringArray p_toplevel_paths); // Set the toplevel paths of this action
|
||||
PackedStringArray get_toplevel_paths() const; // Get the toplevel paths of this action
|
||||
|
||||
void add_toplevel_path(const String p_toplevel_path); // Add a top level path to this action
|
||||
void rem_toplevel_path(const String p_toplevel_path); // Remove a toplevel path from this action
|
||||
|
||||
void parse_toplevel_paths(const String p_toplevel_paths); // Parse and set the top level paths from a comma separated string
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(OpenXRAction::ActionType);
|
636
modules/openxr/action_map/openxr_action_map.cpp
Normal file
636
modules/openxr/action_map/openxr_action_map.cpp
Normal file
@@ -0,0 +1,636 @@
|
||||
/**************************************************************************/
|
||||
/* openxr_action_map.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_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("get_action_set_count"), &OpenXRActionMap::get_action_set_count);
|
||||
ClassDB::bind_method(D_METHOD("find_action_set", "name"), &OpenXRActionMap::find_action_set);
|
||||
ClassDB::bind_method(D_METHOD("get_action_set", "idx"), &OpenXRActionMap::get_action_set);
|
||||
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("get_interaction_profile_count"), &OpenXRActionMap::get_interaction_profile_count);
|
||||
ClassDB::bind_method(D_METHOD("find_interaction_profile", "name"), &OpenXRActionMap::find_interaction_profile);
|
||||
ClassDB::bind_method(D_METHOD("get_interaction_profile", "idx"), &OpenXRActionMap::get_interaction_profile);
|
||||
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.clear();
|
||||
|
||||
for (int i = 0; i < p_action_sets.size(); i++) {
|
||||
Ref<OpenXRActionSet> action_set = p_action_sets[i];
|
||||
if (action_set.is_valid() && !action_sets.has(action_set)) {
|
||||
action_sets.push_back(action_set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Array OpenXRActionMap::get_action_sets() const {
|
||||
return action_sets;
|
||||
}
|
||||
|
||||
int OpenXRActionMap::get_action_set_count() const {
|
||||
return action_sets.size();
|
||||
}
|
||||
|
||||
Ref<OpenXRActionSet> OpenXRActionMap::find_action_set(String p_name) const {
|
||||
for (int i = 0; i < action_sets.size(); i++) {
|
||||
Ref<OpenXRActionSet> action_set = action_sets[i];
|
||||
if (action_set->get_name() == p_name) {
|
||||
return action_set;
|
||||
}
|
||||
}
|
||||
|
||||
return Ref<OpenXRActionSet>();
|
||||
}
|
||||
|
||||
Ref<OpenXRActionSet> OpenXRActionMap::get_action_set(int p_idx) const {
|
||||
ERR_FAIL_INDEX_V(p_idx, action_sets.size(), Ref<OpenXRActionSet>());
|
||||
|
||||
return action_sets[p_idx];
|
||||
}
|
||||
|
||||
void OpenXRActionMap::add_action_set(Ref<OpenXRActionSet> p_action_set) {
|
||||
ERR_FAIL_COND(p_action_set.is_null());
|
||||
|
||||
if (!action_sets.has(p_action_set)) {
|
||||
action_sets.push_back(p_action_set);
|
||||
emit_changed();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
emit_changed();
|
||||
}
|
||||
}
|
||||
|
||||
void OpenXRActionMap::clear_interaction_profiles() {
|
||||
if (interaction_profiles.is_empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
Array OpenXRActionMap::get_interaction_profiles() const {
|
||||
return interaction_profiles;
|
||||
}
|
||||
|
||||
int OpenXRActionMap::get_interaction_profile_count() const {
|
||||
return interaction_profiles.size();
|
||||
}
|
||||
|
||||
Ref<OpenXRInteractionProfile> OpenXRActionMap::find_interaction_profile(String p_path) const {
|
||||
for (Ref<OpenXRInteractionProfile> interaction_profile : interaction_profiles) {
|
||||
if (interaction_profile->get_interaction_profile_path() == p_path) {
|
||||
return interaction_profile;
|
||||
}
|
||||
}
|
||||
|
||||
return Ref<OpenXRInteractionProfile>();
|
||||
}
|
||||
|
||||
Ref<OpenXRInteractionProfile> OpenXRActionMap::get_interaction_profile(int p_idx) const {
|
||||
ERR_FAIL_INDEX_V(p_idx, interaction_profiles.size(), Ref<OpenXRInteractionProfile>());
|
||||
|
||||
return interaction_profiles[p_idx];
|
||||
}
|
||||
|
||||
void OpenXRActionMap::add_interaction_profile(Ref<OpenXRInteractionProfile> p_interaction_profile) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
// - our palm pose is only available if the relevant extension is supported,
|
||||
// we still want it to be part of our action map as we may deploy the same game to platforms that do and don't support it.
|
||||
// - the same applies for interaction profiles that are only supported if the relevant extension is supported.
|
||||
|
||||
// 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_force = action_set->add_new_action("grip_force", "Grip force", OpenXRAction::OPENXR_ACTION_FLOAT, "/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,"
|
||||
// "/user/vive_tracker_htcx/role/handheld_object," <-- getting errors on this one.
|
||||
"/user/vive_tracker_htcx/role/left_foot,"
|
||||
"/user/vive_tracker_htcx/role/right_foot,"
|
||||
"/user/vive_tracker_htcx/role/left_shoulder,"
|
||||
"/user/vive_tracker_htcx/role/right_shoulder,"
|
||||
"/user/vive_tracker_htcx/role/left_elbow,"
|
||||
"/user/vive_tracker_htcx/role/right_elbow,"
|
||||
"/user/vive_tracker_htcx/role/left_knee,"
|
||||
"/user/vive_tracker_htcx/role/right_knee,"
|
||||
"/user/vive_tracker_htcx/role/waist,"
|
||||
"/user/vive_tracker_htcx/role/chest,"
|
||||
"/user/vive_tracker_htcx/role/camera,"
|
||||
"/user/vive_tracker_htcx/role/keyboard,"
|
||||
"/user/vive_tracker_htcx/role/left_wrist,"
|
||||
"/user/vive_tracker_htcx/role/right_wrist,"
|
||||
"/user/vive_tracker_htcx/role/left_ankle,"
|
||||
"/user/vive_tracker_htcx/role/right_ankle,"
|
||||
"/user/eyes_ext");
|
||||
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> palm_pose = action_set->add_new_action("palm_pose", "Palm 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,"
|
||||
// "/user/vive_tracker_htcx/role/handheld_object," <-- getting errors on this one.
|
||||
"/user/vive_tracker_htcx/role/left_foot,"
|
||||
"/user/vive_tracker_htcx/role/right_foot,"
|
||||
"/user/vive_tracker_htcx/role/left_shoulder,"
|
||||
"/user/vive_tracker_htcx/role/right_shoulder,"
|
||||
"/user/vive_tracker_htcx/role/left_elbow,"
|
||||
"/user/vive_tracker_htcx/role/right_elbow,"
|
||||
"/user/vive_tracker_htcx/role/left_knee,"
|
||||
"/user/vive_tracker_htcx/role/right_knee,"
|
||||
"/user/vive_tracker_htcx/role/waist,"
|
||||
"/user/vive_tracker_htcx/role/chest,"
|
||||
"/user/vive_tracker_htcx/role/camera,"
|
||||
"/user/vive_tracker_htcx/role/keyboard,"
|
||||
"/user/vive_tracker_htcx/role/left_wrist,"
|
||||
"/user/vive_tracker_htcx/role/right_wrist,"
|
||||
"/user/vive_tracker_htcx/role/left_ankle,"
|
||||
"/user/vive_tracker_htcx/role/right_ankle");
|
||||
|
||||
// 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/aim/pose,/user/hand/right/input/aim/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(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/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/aim/pose,/user/hand/right/input/aim/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(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/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/aim/pose,/user/hand/right/input/aim/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(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/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 convert 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 Meta touch controller profile.
|
||||
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/oculus/touch_controller");
|
||||
profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/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(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/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 Pico 4 controller profile.
|
||||
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/bytedance/pico4_controller");
|
||||
profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/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(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
|
||||
profile->add_new_binding(select_button, "/user/hand/left/input/system/click,/user/hand/right/input/system/click"); // system click may not be available.
|
||||
profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click");
|
||||
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 pico 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");
|
||||
// pico 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/aim/pose,/user/hand/right/input/aim/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(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/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.
|
||||
profile->add_new_binding(grip_force, "/user/hand/left/input/squeeze/force,/user/hand/right/input/squeeze/force"); // grip force seems to be unique to the Valve Index.
|
||||
// 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);
|
||||
|
||||
// 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/aim/pose,/user/hand/right/input/aim/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(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/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 Samsung Odyssey controller profile,
|
||||
// Note that this controller is only identified specifically on WMR, on SteamVR this is identified as a normal WMR controller.
|
||||
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/samsung/odyssey_controller");
|
||||
profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/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(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
|
||||
// Odyssey 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");
|
||||
// Odyssey 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");
|
||||
profile->add_new_binding(grip, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click");
|
||||
profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click");
|
||||
// primary on our Odyssey 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 Odyssey 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 Vive Cosmos controller.
|
||||
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/htc/vive_cosmos_controller");
|
||||
profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/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(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
|
||||
profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click");
|
||||
profile->add_new_binding(select_button, "/user/hand/right/input/system/click"); // we'll map system to select.
|
||||
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/click,/user/hand/right/input/trigger/click");
|
||||
profile->add_new_binding(grip, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click");
|
||||
profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click");
|
||||
// primary on our Cosmos 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");
|
||||
// No secondary on our cosmos controller.
|
||||
profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
|
||||
add_interaction_profile(profile);
|
||||
|
||||
// Create our Vive Focus 3 controller.
|
||||
// Note, Vive Focus 3 currently is not yet supported as a stand alone device
|
||||
// however HTC currently has a beta OpenXR runtime in testing we may support in the near future.
|
||||
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/htc/vive_focus3_controller");
|
||||
profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/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(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
|
||||
profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click");
|
||||
profile->add_new_binding(select_button, "/user/hand/right/input/system/click"); // we'll map system to select.
|
||||
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/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/click,/user/hand/right/input/squeeze/click");
|
||||
// primary on our Focus 3 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");
|
||||
// We only have a thumb rest.
|
||||
profile->add_new_binding(secondary_touch, "/user/hand/left/input/thumbrest/touch,/user/hand/right/input/thumbrest/touch");
|
||||
profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
|
||||
add_interaction_profile(profile);
|
||||
|
||||
// Create our Huawei controller.
|
||||
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/huawei/controller");
|
||||
profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/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(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
|
||||
profile->add_new_binding(menu_button, "/user/hand/left/input/home/click,/user/hand/right/input/home/click");
|
||||
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");
|
||||
// primary on our Huawei 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");
|
||||
profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
|
||||
add_interaction_profile(profile);
|
||||
|
||||
// Create our HTC Vive tracker profile.
|
||||
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/htc/vive_tracker_htcx");
|
||||
profile->add_new_binding(default_pose,
|
||||
// "/user/vive_tracker_htcx/role/handheld_object/input/grip/pose," <-- getting errors on this one.
|
||||
"/user/vive_tracker_htcx/role/left_foot/input/grip/pose,"
|
||||
"/user/vive_tracker_htcx/role/right_foot/input/grip/pose,"
|
||||
"/user/vive_tracker_htcx/role/left_shoulder/input/grip/pose,"
|
||||
"/user/vive_tracker_htcx/role/right_shoulder/input/grip/pose,"
|
||||
"/user/vive_tracker_htcx/role/left_elbow/input/grip/pose,"
|
||||
"/user/vive_tracker_htcx/role/right_elbow/input/grip/pose,"
|
||||
"/user/vive_tracker_htcx/role/left_knee/input/grip/pose,"
|
||||
"/user/vive_tracker_htcx/role/right_knee/input/grip/pose,"
|
||||
"/user/vive_tracker_htcx/role/waist/input/grip/pose,"
|
||||
"/user/vive_tracker_htcx/role/chest/input/grip/pose,"
|
||||
"/user/vive_tracker_htcx/role/camera/input/grip/pose,"
|
||||
"/user/vive_tracker_htcx/role/keyboard/input/grip/pose,"
|
||||
"/user/vive_tracker_htcx/role/left_wrist/input/grip/pose,"
|
||||
"/user/vive_tracker_htcx/role/right_wrist/input/grip/pose,"
|
||||
"/user/vive_tracker_htcx/role/left_ankle/input/grip/pose,"
|
||||
"/user/vive_tracker_htcx/role/right_ankle/input/grip/pose");
|
||||
profile->add_new_binding(haptic,
|
||||
// "/user/vive_tracker_htcx/role/handheld_object/output/haptic," <-- getting errors on this one.
|
||||
"/user/vive_tracker_htcx/role/left_foot/output/haptic,"
|
||||
"/user/vive_tracker_htcx/role/right_foot/output/haptic,"
|
||||
"/user/vive_tracker_htcx/role/left_shoulder/output/haptic,"
|
||||
"/user/vive_tracker_htcx/role/right_shoulder/output/haptic,"
|
||||
"/user/vive_tracker_htcx/role/left_elbow/output/haptic,"
|
||||
"/user/vive_tracker_htcx/role/right_elbow/output/haptic,"
|
||||
"/user/vive_tracker_htcx/role/left_knee/output/haptic,"
|
||||
"/user/vive_tracker_htcx/role/right_knee/output/haptic,"
|
||||
"/user/vive_tracker_htcx/role/waist/output/haptic,"
|
||||
"/user/vive_tracker_htcx/role/chest/output/haptic,"
|
||||
"/user/vive_tracker_htcx/role/camera/output/haptic,"
|
||||
"/user/vive_tracker_htcx/role/keyboard/output/haptic,"
|
||||
"/user/vive_tracker_htcx/role/left_wrist/output/haptic,"
|
||||
"/user/vive_tracker_htcx/role/right_wrist/output/haptic,"
|
||||
"/user/vive_tracker_htcx/role/left_ankle/output/haptic,"
|
||||
"/user/vive_tracker_htcx/role/right_ankle/output/haptic");
|
||||
add_interaction_profile(profile);
|
||||
|
||||
// Create our eye gaze interaction profile.
|
||||
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/ext/eye_gaze_interaction");
|
||||
profile->add_new_binding(default_pose, "/user/eyes_ext/input/gaze_ext/pose");
|
||||
add_interaction_profile(profile);
|
||||
|
||||
// Create our hand interaction profile.
|
||||
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/ext/hand_interaction_ext");
|
||||
profile->add_new_binding(default_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/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(palm_pose, "/user/hand/left/input/palm_ext/pose,/user/hand/right/input/palm_ext/pose");
|
||||
|
||||
// Use pinch as primary.
|
||||
profile->add_new_binding(primary, "/user/hand/left/input/pinch_ext/value,/user/hand/right/input/pinch_ext/value");
|
||||
profile->add_new_binding(primary_click, "/user/hand/left/input/pinch_ext/ready_ext,/user/hand/right/input/pinch_ext/ready_ext");
|
||||
|
||||
// Use activation as secondary.
|
||||
profile->add_new_binding(secondary, "/user/hand/left/input/aim_activate_ext/value,/user/hand/right/input/aim_activate_ext/value");
|
||||
profile->add_new_binding(secondary_click, "/user/hand/left/input/aim_activate_ext/ready_ext,/user/hand/right/input/aim_activate_ext/ready_ext");
|
||||
|
||||
// We link grasp to our grip.
|
||||
profile->add_new_binding(grip, "/user/hand/left/input/grasp_ext/value,/user/hand/right/input/grasp_ext/value");
|
||||
profile->add_new_binding(grip_click, "/user/hand/left/input/grasp_ext/ready_ext,/user/hand/right/input/grasp_ext/ready_ext");
|
||||
add_interaction_profile(profile);
|
||||
}
|
||||
|
||||
void OpenXRActionMap::create_editor_action_sets() {
|
||||
// TODO implement
|
||||
}
|
||||
|
||||
Ref<OpenXRAction> OpenXRActionMap::get_action(const String p_path) const {
|
||||
PackedStringArray paths = p_path.split("/", false);
|
||||
ERR_FAIL_COND_V(paths.size() != 2, Ref<OpenXRAction>());
|
||||
|
||||
Ref<OpenXRActionSet> action_set = find_action_set(paths[0]);
|
||||
if (action_set.is_valid()) {
|
||||
return action_set->get_action(paths[1]);
|
||||
}
|
||||
|
||||
return Ref<OpenXRAction>();
|
||||
}
|
||||
|
||||
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 (Ref<OpenXRInteractionProfile> interaction_profile : interaction_profiles) {
|
||||
if (p_remove_interaction_profiles) {
|
||||
// Remove any bindings for this action
|
||||
interaction_profile->remove_binding_for_action(action);
|
||||
} else {
|
||||
ERR_FAIL_COND(interaction_profile->has_binding_for_action(action));
|
||||
}
|
||||
}
|
||||
|
||||
OpenXRActionSet *action_set = action->get_action_set();
|
||||
if (action_set != nullptr) {
|
||||
// Remove the action from this action set
|
||||
action_set->remove_action(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PackedStringArray OpenXRActionMap::get_top_level_paths(const Ref<OpenXRAction> p_action) {
|
||||
PackedStringArray arr;
|
||||
|
||||
for (Ref<OpenXRInteractionProfile> ip : interaction_profiles) {
|
||||
const OpenXRInteractionProfileMetadata::InteractionProfile *profile = OpenXRInteractionProfileMetadata::get_singleton()->get_profile(ip->get_interaction_profile_path());
|
||||
|
||||
if (profile != nullptr) {
|
||||
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;
|
||||
|
||||
if (!arr.has(top_path)) {
|
||||
arr.push_back(top_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// print_line("Toplevel paths for", p_action->get_name_with_set(), "are", arr);
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
OpenXRActionMap::~OpenXRActionMap() {
|
||||
action_sets.clear();
|
||||
clear_interaction_profiles();
|
||||
}
|
80
modules/openxr/action_map/openxr_action_map.h
Normal file
80
modules/openxr/action_map/openxr_action_map.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/**************************************************************************/
|
||||
/* openxr_action_map.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "openxr_action.h"
|
||||
#include "openxr_action_set.h"
|
||||
#include "openxr_interaction_profile.h"
|
||||
|
||||
#include "core/io/resource.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); // Set our actions sets by providing an array with action sets (for loading from resource)
|
||||
Array get_action_sets() const; // Get our action sets as an array (for saving to resource)
|
||||
|
||||
int get_action_set_count() const; // Retrieve the number of action sets we have
|
||||
Ref<OpenXRActionSet> find_action_set(String p_name) const; // Find an action set by name
|
||||
Ref<OpenXRActionSet> get_action_set(int p_idx) const; // Retrieve an action set by index
|
||||
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)
|
||||
|
||||
int get_interaction_profile_count() const; // Retrieve the number of interaction profiles we have
|
||||
Ref<OpenXRInteractionProfile> find_interaction_profile(String p_path) const; // Find an interaction profile by path
|
||||
Ref<OpenXRInteractionProfile> get_interaction_profile(int p_idx) const; // Retrieve an interaction profile by index
|
||||
void add_interaction_profile(Ref<OpenXRInteractionProfile> p_interaction_profile); // Add an interaction profile to our action map
|
||||
void remove_interaction_profile(Ref<OpenXRInteractionProfile> p_interaction_profile); // remove an interaction profile from our action map
|
||||
|
||||
void create_default_action_sets(); // Create our default action set for runtime
|
||||
void create_editor_action_sets(); // Create our action set for the editor
|
||||
|
||||
// Helper functions for editor
|
||||
Ref<OpenXRAction> get_action(const String p_path) const; // Retrieve an action using <action name>/<action> as our parameter
|
||||
void remove_action(const String p_path, bool p_remove_interaction_profiles = false); // Remove action from action set, also removes it from interaction profiles
|
||||
PackedStringArray get_top_level_paths(const Ref<OpenXRAction> p_action); // Determines the top level paths based on where an action is bound in interaction profiles
|
||||
|
||||
// TODO add validation to display in the interface that checks if we have action sets with the same name or if we have interaction profiles for the same path
|
||||
|
||||
~OpenXRActionMap();
|
||||
};
|
161
modules/openxr/action_map/openxr_action_set.cpp
Normal file
161
modules/openxr/action_map/openxr_action_set.cpp
Normal file
@@ -0,0 +1,161 @@
|
||||
/**************************************************************************/
|
||||
/* openxr_action_set.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_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("get_action_count"), &OpenXRActionSet::get_action_count);
|
||||
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;
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
String OpenXRActionSet::get_localized_name() const {
|
||||
return localized_name;
|
||||
}
|
||||
|
||||
void OpenXRActionSet::set_priority(const int p_priority) {
|
||||
priority = p_priority;
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
int OpenXRActionSet::get_priority() const {
|
||||
return priority;
|
||||
}
|
||||
|
||||
int OpenXRActionSet::get_action_count() const {
|
||||
return actions.size();
|
||||
}
|
||||
|
||||
void OpenXRActionSet::clear_actions() {
|
||||
// Actions held within our action set should be released and destroyed but just in case they are still used some where else
|
||||
if (actions.is_empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < actions.size(); i++) {
|
||||
Ref<OpenXRAction> action = actions[i];
|
||||
action->action_set = nullptr;
|
||||
}
|
||||
actions.clear();
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
void OpenXRActionSet::set_actions(Array p_actions) {
|
||||
// Any actions not retained in p_actions should be freed automatically, those held within our Array will have be relinked to our action set.
|
||||
clear_actions();
|
||||
|
||||
for (int i = 0; i < p_actions.size(); i++) {
|
||||
// add them anew so we verify our action_set pointer
|
||||
add_action(p_actions[i]);
|
||||
}
|
||||
}
|
||||
|
||||
Array OpenXRActionSet::get_actions() const {
|
||||
return actions;
|
||||
}
|
||||
|
||||
Ref<OpenXRAction> OpenXRActionSet::get_action(const String p_name) const {
|
||||
for (int i = 0; i < actions.size(); i++) {
|
||||
Ref<OpenXRAction> action = actions[i];
|
||||
if (action->get_name() == p_name) {
|
||||
return action;
|
||||
}
|
||||
}
|
||||
|
||||
return Ref<OpenXRAction>();
|
||||
}
|
||||
|
||||
void OpenXRActionSet::add_action(Ref<OpenXRAction> p_action) {
|
||||
ERR_FAIL_COND(p_action.is_null());
|
||||
|
||||
if (!actions.has(p_action)) {
|
||||
if (p_action->action_set && p_action->action_set != this) {
|
||||
// action should only relate to our action set
|
||||
p_action->action_set->remove_action(p_action);
|
||||
}
|
||||
|
||||
p_action->action_set = this;
|
||||
actions.push_back(p_action);
|
||||
emit_changed();
|
||||
}
|
||||
}
|
||||
|
||||
void OpenXRActionSet::remove_action(Ref<OpenXRAction> p_action) {
|
||||
int idx = actions.find(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!
|
||||
p_action->action_set = nullptr;
|
||||
|
||||
emit_changed();
|
||||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
clear_actions();
|
||||
}
|
72
modules/openxr/action_map/openxr_action_set.h
Normal file
72
modules/openxr/action_map/openxr_action_set.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/**************************************************************************/
|
||||
/* openxr_action_set.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "openxr_action.h"
|
||||
|
||||
#include "core/io/resource.h"
|
||||
|
||||
class OpenXRActionSet : public Resource {
|
||||
GDCLASS(OpenXRActionSet, Resource);
|
||||
|
||||
private:
|
||||
String localized_name;
|
||||
int priority = 0;
|
||||
|
||||
Array actions;
|
||||
void clear_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); // Helper function for adding and setting up an action set
|
||||
|
||||
void set_localized_name(const String p_localized_name); // Set the localized name of this action set
|
||||
String get_localized_name() const; // Get the localized name of this action set
|
||||
|
||||
void set_priority(const int p_priority); // Set the priority of this action set
|
||||
int get_priority() const; // Get the priority of this action set
|
||||
|
||||
int get_action_count() const; // Retrieve the number of actions in our action set
|
||||
void set_actions(Array p_actions); // Set our actions using an array of actions (for loading a resource)
|
||||
Array get_actions() const; // Get our actions as an array (for saving a resource)
|
||||
|
||||
Ref<OpenXRAction> get_action(const String p_name) const; // Retrieve an action by name
|
||||
void add_action(Ref<OpenXRAction> p_action); // Add a new action to our action set
|
||||
void remove_action(Ref<OpenXRAction> p_action); // remove a action from our action set
|
||||
|
||||
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); // Helper function for adding and setting up an action
|
||||
|
||||
// TODO add validation to display in the interface that checks if we have duplicate action names within our action set
|
||||
|
||||
~OpenXRActionSet();
|
||||
};
|
52
modules/openxr/action_map/openxr_binding_modifier.cpp
Normal file
52
modules/openxr/action_map/openxr_binding_modifier.cpp
Normal 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();
|
||||
}
|
78
modules/openxr/action_map/openxr_binding_modifier.h
Normal file
78
modules/openxr/action_map/openxr_binding_modifier.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/**************************************************************************/
|
||||
/* 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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#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; }
|
||||
};
|
93
modules/openxr/action_map/openxr_haptic_feedback.cpp
Normal file
93
modules/openxr/action_map/openxr_haptic_feedback.cpp
Normal 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;
|
||||
}
|
69
modules/openxr/action_map/openxr_haptic_feedback.h
Normal file
69
modules/openxr/action_map/openxr_haptic_feedback.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/**************************************************************************/
|
||||
/* 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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#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();
|
||||
};
|
431
modules/openxr/action_map/openxr_interaction_profile.cpp
Normal file
431
modules/openxr/action_map/openxr_interaction_profile.cpp
Normal file
@@ -0,0 +1,431 @@
|
||||
/**************************************************************************/
|
||||
/* openxr_interaction_profile.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_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_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", 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 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->set_binding_path(p_binding_path);
|
||||
|
||||
return binding;
|
||||
}
|
||||
|
||||
void OpenXRIPBinding::set_action(const Ref<OpenXRAction> &p_action) {
|
||||
action = p_action;
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
Ref<OpenXRAction> OpenXRIPBinding::get_action() const {
|
||||
return action;
|
||||
}
|
||||
|
||||
void OpenXRIPBinding::set_binding_path(const String &path) {
|
||||
binding_path = path;
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
#endif // DISABLE_DEPRECATED
|
||||
|
||||
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("get_binding_count"), &OpenXRInteractionProfile::get_binding_count);
|
||||
ClassDB::bind_method(D_METHOD("get_binding", "index"), &OpenXRInteractionProfile::get_binding);
|
||||
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) {
|
||||
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) {
|
||||
OpenXRInteractionProfileMetadata *pmd = OpenXRInteractionProfileMetadata::get_singleton();
|
||||
if (pmd) {
|
||||
interaction_profile_path = pmd->check_profile_name(p_input_profile_path);
|
||||
} else {
|
||||
// OpenXR module not enabled, ignore checks.
|
||||
interaction_profile_path = p_input_profile_path;
|
||||
}
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
String OpenXRInteractionProfile::get_interaction_profile_path() const {
|
||||
return interaction_profile_path;
|
||||
}
|
||||
|
||||
int OpenXRInteractionProfile::get_binding_count() const {
|
||||
return bindings.size();
|
||||
}
|
||||
|
||||
Ref<OpenXRIPBinding> OpenXRInteractionProfile::get_binding(int p_index) const {
|
||||
ERR_FAIL_INDEX_V(p_index, bindings.size(), Ref<OpenXRIPBinding>());
|
||||
|
||||
return bindings[p_index];
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
Array OpenXRInteractionProfile::get_bindings() const {
|
||||
return bindings;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return Ref<OpenXRIPBinding>();
|
||||
}
|
||||
|
||||
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(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(const Ref<OpenXRIPBinding> &p_binding) {
|
||||
int idx = bindings.find(p_binding);
|
||||
if (idx != -1) {
|
||||
bindings.remove_at(idx);
|
||||
emit_changed();
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
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) {
|
||||
for (int i = bindings.size() - 1; i >= 0; i--) {
|
||||
Ref<OpenXRIPBinding> binding = bindings[i];
|
||||
if (binding->get_action() == p_action) {
|
||||
remove_binding(binding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
138
modules/openxr/action_map/openxr_interaction_profile.h
Normal file
138
modules/openxr/action_map/openxr_interaction_profile.h
Normal file
@@ -0,0 +1,138 @@
|
||||
/**************************************************************************/
|
||||
/* openxr_interaction_profile.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#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;
|
||||
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 String &p_binding_path); // Helper function for adding a new binding.
|
||||
|
||||
OpenXRActionMap *get_action_map() { return action_map; } // Return the action map we're a part of.
|
||||
|
||||
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 set_binding_path(const String &path);
|
||||
String get_binding_path() const;
|
||||
|
||||
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
|
||||
|
||||
~OpenXRIPBinding();
|
||||
};
|
||||
|
||||
class OpenXRInteractionProfile : public Resource {
|
||||
GDCLASS(OpenXRInteractionProfile, 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(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> 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 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();
|
||||
};
|
@@ -0,0 +1,388 @@
|
||||
/**************************************************************************/
|
||||
/* openxr_interaction_profile_metadata.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_interaction_profile_metadata.h"
|
||||
|
||||
#include "../openxr_api.h"
|
||||
|
||||
OpenXRInteractionProfileMetadata *OpenXRInteractionProfileMetadata::singleton = nullptr;
|
||||
|
||||
OpenXRInteractionProfileMetadata::OpenXRInteractionProfileMetadata() {
|
||||
singleton = this;
|
||||
|
||||
_register_core_metadata();
|
||||
OpenXRAPI::register_extension_metadata();
|
||||
}
|
||||
|
||||
OpenXRInteractionProfileMetadata::~OpenXRInteractionProfileMetadata() {
|
||||
singleton = nullptr;
|
||||
}
|
||||
|
||||
void OpenXRInteractionProfileMetadata::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("register_profile_rename", "old_name", "new_name"), &OpenXRInteractionProfileMetadata::register_profile_rename);
|
||||
ClassDB::bind_method(D_METHOD("register_top_level_path", "display_name", "openxr_path", "openxr_extension_name"), &OpenXRInteractionProfileMetadata::register_top_level_path);
|
||||
ClassDB::bind_method(D_METHOD("register_interaction_profile", "display_name", "openxr_path", "openxr_extension_name"), &OpenXRInteractionProfileMetadata::register_interaction_profile);
|
||||
ClassDB::bind_method(D_METHOD("register_io_path", "interaction_profile", "display_name", "toplevel_path", "openxr_path", "openxr_extension_name", "action_type"), &OpenXRInteractionProfileMetadata::register_io_path);
|
||||
}
|
||||
|
||||
void OpenXRInteractionProfileMetadata::register_profile_rename(const String &p_old_name, const String &p_new_name) {
|
||||
ERR_FAIL_COND(profile_renames.has(p_old_name));
|
||||
|
||||
profile_renames[p_old_name] = p_new_name;
|
||||
}
|
||||
|
||||
String OpenXRInteractionProfileMetadata::check_profile_name(const String &p_name) const {
|
||||
if (profile_renames.has(p_name)) {
|
||||
return profile_renames[p_name];
|
||||
}
|
||||
|
||||
return p_name;
|
||||
}
|
||||
|
||||
void OpenXRInteractionProfileMetadata::register_top_level_path(const String &p_display_name, const String &p_openxr_path, const String &p_openxr_extension_name) {
|
||||
ERR_FAIL_COND_MSG(has_top_level_path(p_openxr_path), p_openxr_path + " had already been registered");
|
||||
|
||||
TopLevelPath new_toplevel_path = {
|
||||
p_display_name,
|
||||
p_openxr_path,
|
||||
p_openxr_extension_name
|
||||
};
|
||||
|
||||
top_level_paths.push_back(new_toplevel_path);
|
||||
}
|
||||
|
||||
void OpenXRInteractionProfileMetadata::register_interaction_profile(const String &p_display_name, const String &p_openxr_path, const String &p_openxr_extension_name) {
|
||||
ERR_FAIL_COND_MSG(has_interaction_profile(p_openxr_path), p_openxr_path + " has already been registered");
|
||||
|
||||
InteractionProfile new_profile;
|
||||
new_profile.display_name = p_display_name;
|
||||
new_profile.openxr_path = p_openxr_path;
|
||||
new_profile.openxr_extension_name = p_openxr_extension_name;
|
||||
|
||||
interaction_profiles.push_back(new_profile);
|
||||
}
|
||||
|
||||
void OpenXRInteractionProfileMetadata::register_io_path(const String &p_interaction_profile, const String &p_display_name, const String &p_toplevel_path, const String &p_openxr_path, const String &p_openxr_extension_name, OpenXRAction::ActionType p_action_type) {
|
||||
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 (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,
|
||||
p_toplevel_path,
|
||||
p_openxr_path,
|
||||
p_openxr_extension_name,
|
||||
p_action_type
|
||||
};
|
||||
|
||||
interaction_profile.io_paths.push_back(new_io_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool OpenXRInteractionProfileMetadata::has_top_level_path(const String p_openxr_path) const {
|
||||
for (int i = 0; i < top_level_paths.size(); i++) {
|
||||
if (top_level_paths[i].openxr_path == p_openxr_path) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
String OpenXRInteractionProfileMetadata::get_top_level_name(const String p_openxr_path) const {
|
||||
for (int i = 0; i < top_level_paths.size(); i++) {
|
||||
if (top_level_paths[i].openxr_path == p_openxr_path) {
|
||||
return top_level_paths[i].display_name;
|
||||
}
|
||||
}
|
||||
|
||||
return String();
|
||||
}
|
||||
|
||||
String OpenXRInteractionProfileMetadata::get_top_level_extension(const String p_openxr_path) const {
|
||||
for (int i = 0; i < top_level_paths.size(); i++) {
|
||||
if (top_level_paths[i].openxr_path == p_openxr_path) {
|
||||
return top_level_paths[i].openxr_extension_name;
|
||||
}
|
||||
}
|
||||
|
||||
return XR_PATH_UNSUPPORTED_NAME;
|
||||
}
|
||||
|
||||
bool OpenXRInteractionProfileMetadata::has_interaction_profile(const String p_openxr_path) const {
|
||||
for (const InteractionProfile &interaction_profile : interaction_profiles) {
|
||||
if (interaction_profile.openxr_path == p_openxr_path) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
String OpenXRInteractionProfileMetadata::get_interaction_profile_extension(const String p_openxr_path) const {
|
||||
for (const InteractionProfile &interaction_profile : interaction_profiles) {
|
||||
if (interaction_profile.openxr_path == p_openxr_path) {
|
||||
return interaction_profile.openxr_extension_name;
|
||||
}
|
||||
}
|
||||
|
||||
return XR_PATH_UNSUPPORTED_NAME;
|
||||
}
|
||||
|
||||
const OpenXRInteractionProfileMetadata::InteractionProfile *OpenXRInteractionProfileMetadata::get_profile(const String p_openxr_path) const {
|
||||
for (const InteractionProfile &interaction_profile : interaction_profiles) {
|
||||
if (interaction_profile.openxr_path == p_openxr_path) {
|
||||
return &interaction_profile;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool OpenXRInteractionProfileMetadata::InteractionProfile::has_io_path(const String p_io_path) const {
|
||||
for (int i = 0; i < io_paths.size(); i++) {
|
||||
if (io_paths[i].openxr_path == p_io_path) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const OpenXRInteractionProfileMetadata::IOPath *OpenXRInteractionProfileMetadata::InteractionProfile::get_io_path(const String p_io_path) const {
|
||||
for (int i = 0; i < io_paths.size(); i++) {
|
||||
if (io_paths[i].openxr_path == p_io_path) {
|
||||
return &io_paths[i];
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const OpenXRInteractionProfileMetadata::IOPath *OpenXRInteractionProfileMetadata::get_io_path(const String p_interaction_profile, const String p_io_path) const {
|
||||
const OpenXRInteractionProfileMetadata::InteractionProfile *profile = get_profile(p_interaction_profile);
|
||||
if (profile != nullptr) {
|
||||
return profile->get_io_path(p_io_path);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PackedStringArray OpenXRInteractionProfileMetadata::get_interaction_profile_paths() const {
|
||||
PackedStringArray arr;
|
||||
|
||||
for (const InteractionProfile &interaction_profile : interaction_profiles) {
|
||||
arr.push_back(interaction_profile.openxr_path);
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
void OpenXRInteractionProfileMetadata::_register_core_metadata() {
|
||||
// Note, currently we add definitions that belong in extensions.
|
||||
// Extensions are registered when our OpenXRAPI is instantiated
|
||||
// however this does not happen in the editor.
|
||||
// We are changing this in another PR, once that is accepted we
|
||||
// can make the changes to move code into extensions where needed.
|
||||
|
||||
// Note that we'll make an exception for XR_EXT_palm_pose, which is used everywhere
|
||||
|
||||
// Our core toplevel paths
|
||||
register_top_level_path("Left hand controller", "/user/hand/left", "");
|
||||
register_top_level_path("Right hand controller", "/user/hand/right", "");
|
||||
register_top_level_path("Head", "/user/head", "");
|
||||
register_top_level_path("Gamepad", "/user/gamepad", "");
|
||||
register_top_level_path("Treadmill", "/user/treadmill", "");
|
||||
|
||||
{ // 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(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(profile_path, "Haptic output", user_path, user_path + "/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
|
||||
}
|
||||
}
|
||||
|
||||
{ // 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(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(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, "Squeeze click", user_path, user_path + "/input/squeeze/click", "", 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(profile_path, "Haptic output", user_path, user_path + "/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
|
||||
}
|
||||
}
|
||||
|
||||
{ // 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(profile_path, "Menu click", user_path, user_path + "/input/menu/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(profile_path, "Squeeze click", user_path, user_path + "/input/squeeze/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(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(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)
|
||||
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(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(profile_path, "Squeeze", user_path, user_path + "/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT);
|
||||
|
||||
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(profile_path, "Thumbrest touch", user_path, user_path + "/input/thumbrest/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(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(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
|
||||
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(profile_path, "System click", user_path, user_path + "/input/system/click", "", 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(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(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(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(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(profile_path, "Haptic output", user_path, user_path + "/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC);
|
||||
}
|
||||
}
|
||||
}
|
122
modules/openxr/action_map/openxr_interaction_profile_metadata.h
Normal file
122
modules/openxr/action_map/openxr_interaction_profile_metadata.h
Normal file
@@ -0,0 +1,122 @@
|
||||
/**************************************************************************/
|
||||
/* openxr_interaction_profile_metadata.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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Stores available interaction profile metadata
|
||||
//
|
||||
// OpenXR defines and hardcodes all the supported input devices and their
|
||||
// paths as part of the OpenXR spec. When support for new devices is
|
||||
// introduced this often starts life as an extension that needs to be enabled
|
||||
// until it's adopted into the core. As there is no interface to
|
||||
// enumerate the possibly paths, and that any OpenXR runtime would likely
|
||||
// limit such enumeration to those input devices supported by that runtime
|
||||
// there is no other option than to hardcode this.
|
||||
//
|
||||
// Note that we need to include paths of our extensions in our action map
|
||||
// regardless of whether the developers machine supports the extension or
|
||||
// not. Unsupported paths are filtered out when the action map is submitted
|
||||
// to the OpenXR runtime.
|
||||
//
|
||||
// Note on action type that automatic conversions between boolean and float
|
||||
// are supported but otherwise action types should match between action and
|
||||
// input/output paths.
|
||||
|
||||
#include "openxr_action.h"
|
||||
|
||||
#include "core/object/object.h"
|
||||
#include "core/templates/hash_map.h"
|
||||
|
||||
#define XR_PATH_UNSUPPORTED_NAME "unsupported"
|
||||
|
||||
class OpenXRInteractionProfileMetadata : public Object {
|
||||
GDCLASS(OpenXRInteractionProfileMetadata, Object);
|
||||
|
||||
public:
|
||||
struct TopLevelPath {
|
||||
String display_name; // User friendly display name (i.e. Left controller)
|
||||
String openxr_path; // Path in OpenXR (i.e. /user/hand/left)
|
||||
String openxr_extension_name; // If set, only available if extension is enabled (i.e. XR_HTCX_vive_tracker_interaction)
|
||||
};
|
||||
|
||||
struct IOPath {
|
||||
String display_name; // User friendly display name (i.e. Grip pose (left controller))
|
||||
String top_level_path; // Top level path identifying the usage of the device in relation to this input/output
|
||||
String openxr_path; // Path in OpenXR (i.e. /user/hand/left/input/grip/pose)
|
||||
String openxr_extension_name; // If set, only available if extension is enabled (i.e. XR_EXT_palm_pose)
|
||||
OpenXRAction::ActionType action_type; // Type of input/output
|
||||
};
|
||||
|
||||
struct InteractionProfile {
|
||||
String display_name; // User friendly display name (i.e. Simple controller)
|
||||
String openxr_path; // Path in OpenXR (i.e. /interaction_profiles/khr/simple_controller)
|
||||
String openxr_extension_name; // If set, only available if extension is enabled (i.e. XR_HTCX_vive_tracker_interaction)
|
||||
Vector<IOPath> io_paths; // Inputs and outputs for this device
|
||||
|
||||
bool has_io_path(const String p_io_path) const;
|
||||
const IOPath *get_io_path(const String p_io_path) const;
|
||||
};
|
||||
|
||||
private:
|
||||
static OpenXRInteractionProfileMetadata *singleton;
|
||||
|
||||
HashMap<String, String> profile_renames;
|
||||
Vector<TopLevelPath> top_level_paths;
|
||||
Vector<InteractionProfile> interaction_profiles;
|
||||
|
||||
void _register_core_metadata();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
static OpenXRInteractionProfileMetadata *get_singleton() { return singleton; }
|
||||
|
||||
OpenXRInteractionProfileMetadata();
|
||||
~OpenXRInteractionProfileMetadata();
|
||||
|
||||
void register_profile_rename(const String &p_old_name, const String &p_new_name);
|
||||
String check_profile_name(const String &p_name) const;
|
||||
|
||||
void register_top_level_path(const String &p_display_name, const String &p_openxr_path, const String &p_openxr_extension_name);
|
||||
bool has_top_level_path(const String p_openxr_path) const;
|
||||
String get_top_level_name(const String p_openxr_path) const;
|
||||
String get_top_level_extension(const String p_openxr_path) const;
|
||||
|
||||
void register_interaction_profile(const String &p_display_name, const String &p_openxr_path, const String &p_openxr_extension_name);
|
||||
bool has_interaction_profile(const String p_openxr_path) const;
|
||||
String get_interaction_profile_extension(const String p_openxr_path) const;
|
||||
const InteractionProfile *get_profile(const String p_openxr_path) const;
|
||||
PackedStringArray get_interaction_profile_paths() const;
|
||||
|
||||
void register_io_path(const String &p_interaction_profile, const String &p_display_name, const String &p_toplevel_path, const String &p_openxr_path, const String &p_openxr_extension_name, OpenXRAction::ActionType p_action_type);
|
||||
const IOPath *get_io_path(const String p_interaction_profile, const String p_io_path) const;
|
||||
};
|
Reference in New Issue
Block a user