diff options
Diffstat (limited to 'modules')
70 files changed, 1640 insertions, 1150 deletions
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index b7feedaeaa..91f31174dd 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -701,6 +701,7 @@ bool GDScript::_update_exports(bool *r_err, bool p_recursive_call, PlaceHolderSc Variant default_value; if (member.variable->initializer && member.variable->initializer->is_constant) { default_value = member.variable->initializer->reduced_value; + GDScriptCompiler::convert_to_initializer_type(default_value, member.variable); } member_default_values_cache[member.variable->identifier->name] = default_value; } break; diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 103085bc3d..1149749ef7 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -1595,7 +1595,7 @@ void GDScriptAnalyzer::resolve_constant(GDScriptParser::ConstantNode *p_constant } if (p_constant->datatype_specifier != nullptr) { - if (!is_type_compatible(explicit_type, type)) { + if (!is_type_compatible(explicit_type, type, true)) { push_error(vformat(R"(Assigned value for constant "%s" has type %s which is not compatible with defined type %s.)", p_constant->identifier->name, type.to_string(), explicit_type.to_string()), p_constant->initializer); #ifdef DEBUG_ENABLED } else if (explicit_type.builtin_type == Variant::INT && type.builtin_type == Variant::FLOAT) { @@ -2171,7 +2171,7 @@ void GDScriptAnalyzer::reduce_binary_op(GDScriptParser::BinaryOpNode *p_binary_o GDScriptParser::DataType test_type = right_type; test_type.is_meta_type = false; - if (!is_type_compatible(test_type, p_binary_op->left_operand->get_datatype(), false)) { + if (!is_type_compatible(test_type, left_type, false)) { push_error(vformat(R"(Expression is of type "%s" so it can't be of type "%s".)"), p_binary_op->left_operand); p_binary_op->reduced_value = false; } else { @@ -2205,11 +2205,11 @@ void GDScriptAnalyzer::reduce_binary_op(GDScriptParser::BinaryOpNode *p_binary_o GDScriptParser::DataType test_type = right_type; test_type.is_meta_type = false; - if (!is_type_compatible(test_type, p_binary_op->left_operand->get_datatype(), false)) { + if (!is_type_compatible(test_type, left_type, false)) { // Test reverse as well to consider for subtypes. - if (!is_type_compatible(p_binary_op->left_operand->get_datatype(), test_type, false)) { - if (p_binary_op->left_operand->get_datatype().is_hard_type()) { - push_error(vformat(R"(Expression is of type "%s" so it can't be of type "%s".)", p_binary_op->left_operand->get_datatype().to_string(), test_type.to_string()), p_binary_op->left_operand); + if (!is_type_compatible(left_type, test_type, false)) { + if (left_type.is_hard_type()) { + push_error(vformat(R"(Expression is of type "%s" so it can't be of type "%s".)", left_type.to_string(), test_type.to_string()), p_binary_op->left_operand); } else { // TODO: Warning. mark_node_unsafe(p_binary_op); @@ -3640,6 +3640,7 @@ void GDScriptAnalyzer::reduce_ternary_op(GDScriptParser::TernaryOpNode *p_ternar void GDScriptAnalyzer::reduce_unary_op(GDScriptParser::UnaryOpNode *p_unary_op) { reduce_expression(p_unary_op->operand); + GDScriptParser::DataType operand_type = p_unary_op->operand->get_datatype(); GDScriptParser::DataType result; if (p_unary_op->operand == nullptr) { @@ -3652,15 +3653,17 @@ void GDScriptAnalyzer::reduce_unary_op(GDScriptParser::UnaryOpNode *p_unary_op) p_unary_op->is_constant = true; p_unary_op->reduced_value = Variant::evaluate(p_unary_op->variant_op, p_unary_op->operand->reduced_value, Variant()); result = type_from_variant(p_unary_op->reduced_value, p_unary_op); - } else if (p_unary_op->operand->get_datatype().is_variant()) { + } + + if (operand_type.is_variant()) { result.kind = GDScriptParser::DataType::VARIANT; mark_node_unsafe(p_unary_op); } else { bool valid = false; - result = get_operation_type(p_unary_op->variant_op, p_unary_op->operand->get_datatype(), valid, p_unary_op); + result = get_operation_type(p_unary_op->variant_op, operand_type, valid, p_unary_op); if (!valid) { - push_error(vformat(R"(Invalid operand of type "%s" for unary operator "%s".)", p_unary_op->operand->get_datatype().to_string(), Variant::get_operator_name(p_unary_op->variant_op)), p_unary_op->operand); + push_error(vformat(R"(Invalid operand of type "%s" for unary operator "%s".)", operand_type.to_string(), Variant::get_operator_name(p_unary_op->variant_op)), p_unary_op); } } @@ -4184,8 +4187,6 @@ bool GDScriptAnalyzer::is_type_compatible(const GDScriptParser::DataType &p_targ if (p_target.kind == GDScriptParser::DataType::BUILTIN) { bool valid = p_source.kind == GDScriptParser::DataType::BUILTIN && p_target.builtin_type == p_source.builtin_type; - valid |= p_source.builtin_type == Variant::STRING && p_target.builtin_type == Variant::STRING_NAME; - valid |= p_source.builtin_type == Variant::STRING_NAME && p_target.builtin_type == Variant::STRING; if (!valid && p_allow_implicit_conversion) { valid = Variant::can_convert_strict(p_source.builtin_type, p_target.builtin_type); } @@ -4201,7 +4202,7 @@ bool GDScriptAnalyzer::is_type_compatible(const GDScriptParser::DataType &p_targ // Variant array can't be appended to typed array. valid = false; } else { - valid = is_type_compatible(p_target.get_container_element_type(), p_source.get_container_element_type(), false); + valid = is_type_compatible(p_target.get_container_element_type(), p_source.get_container_element_type(), p_allow_implicit_conversion); } } } diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index c0539c7e45..2a98b856ce 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -2389,6 +2389,7 @@ Error GDScriptCompiler::_populate_class_members(GDScript *p_script, const GDScri #ifdef TOOLS_ENABLED if (variable->initializer != nullptr && variable->initializer->is_constant) { p_script->member_default_values[name] = variable->initializer->reduced_value; + GDScriptCompiler::convert_to_initializer_type(p_script->member_default_values[name], variable); } else { p_script->member_default_values.erase(name); } @@ -2646,6 +2647,20 @@ Error GDScriptCompiler::_compile_class(GDScript *p_script, const GDScriptParser: return OK; } +void GDScriptCompiler::convert_to_initializer_type(Variant &p_variant, const GDScriptParser::VariableNode *p_node) { + // Set p_variant to the value of p_node's initializer, with the type of p_node's variable. + GDScriptParser::DataType member_t = p_node->datatype; + GDScriptParser::DataType init_t = p_node->initializer->datatype; + if (member_t.is_hard_type() && init_t.is_hard_type() && + member_t.kind == GDScriptParser::DataType::BUILTIN && init_t.kind == GDScriptParser::DataType::BUILTIN) { + if (Variant::can_convert_strict(init_t.builtin_type, member_t.builtin_type)) { + Variant *v = &p_node->initializer->reduced_value; + Callable::CallError ce; + Variant::construct(member_t.builtin_type, p_variant, const_cast<const Variant **>(&v), 1, ce); + } + } +} + void GDScriptCompiler::make_scripts(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) { p_script->fully_qualified_name = p_class->fqcn; p_script->name = p_class->identifier ? p_class->identifier->name : ""; diff --git a/modules/gdscript/gdscript_compiler.h b/modules/gdscript/gdscript_compiler.h index cba585e5a5..fc5aa05190 100644 --- a/modules/gdscript/gdscript_compiler.h +++ b/modules/gdscript/gdscript_compiler.h @@ -140,6 +140,7 @@ class GDScriptCompiler { bool within_await = false; public: + static void convert_to_initializer_type(Variant &p_variant, const GDScriptParser::VariableNode *p_node); static void make_scripts(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state); Error compile(const GDScriptParser *p_parser, GDScript *p_script, bool p_keep_state = false); diff --git a/modules/gdscript/tests/scripts/analyzer/features/array_string_stringname_equivalent.gd b/modules/gdscript/tests/scripts/analyzer/features/array_string_stringname_equivalent.gd index 4511c3d10b..eb0003eed8 100644 --- a/modules/gdscript/tests/scripts/analyzer/features/array_string_stringname_equivalent.gd +++ b/modules/gdscript/tests/scripts/analyzer/features/array_string_stringname_equivalent.gd @@ -1,4 +1,11 @@ + +var m_string_array: Array[String] = [&"abc"] +var m_stringname_array: Array[StringName] = ["abc"] + func test(): + print(m_string_array) + print(m_stringname_array) + # Converted to String when initialized var string_array: Array[String] = [&"abc"] print(string_array) diff --git a/modules/gdscript/tests/scripts/analyzer/features/array_string_stringname_equivalent.out b/modules/gdscript/tests/scripts/analyzer/features/array_string_stringname_equivalent.out index 70dd01d88e..09c199bde1 100644 --- a/modules/gdscript/tests/scripts/analyzer/features/array_string_stringname_equivalent.out +++ b/modules/gdscript/tests/scripts/analyzer/features/array_string_stringname_equivalent.out @@ -1,3 +1,5 @@ GDTEST_OK ["abc"] [&"abc"] +["abc"] +[&"abc"] diff --git a/modules/gltf/doc_classes/GLTFDocumentExtension.xml b/modules/gltf/doc_classes/GLTFDocumentExtension.xml index ac638a8962..6004de32f1 100644 --- a/modules/gltf/doc_classes/GLTFDocumentExtension.xml +++ b/modules/gltf/doc_classes/GLTFDocumentExtension.xml @@ -42,7 +42,8 @@ </method> <method name="_export_preflight" qualifiers="virtual"> <return type="int" /> - <param index="0" name="root" type="Node" /> + <param index="0" name="state" type="GLTFState" /> + <param index="1" name="root" type="Node" /> <description> Part of the export process. This method is run first, before all other parts of the export process. The return value is used to determine if this [GLTFDocumentExtension] instance should be used for exporting a given GLTF file. If [constant OK], the export will use this [GLTFDocumentExtension] instance. If not overridden, [constant OK] is returned. diff --git a/modules/gltf/extensions/gltf_document_extension.cpp b/modules/gltf/extensions/gltf_document_extension.cpp index f997fe8f66..630a62ba5c 100644 --- a/modules/gltf/extensions/gltf_document_extension.cpp +++ b/modules/gltf/extensions/gltf_document_extension.cpp @@ -40,7 +40,7 @@ void GLTFDocumentExtension::_bind_methods() { GDVIRTUAL_BIND(_import_node, "state", "gltf_node", "json", "node"); GDVIRTUAL_BIND(_import_post, "state", "root"); // Export process. - GDVIRTUAL_BIND(_export_preflight, "root"); + GDVIRTUAL_BIND(_export_preflight, "state", "root"); GDVIRTUAL_BIND(_convert_scene_node, "state", "gltf_node", "scene_node"); GDVIRTUAL_BIND(_export_node, "state", "gltf_node", "json", "node"); GDVIRTUAL_BIND(_export_post, "state"); @@ -102,10 +102,10 @@ Error GLTFDocumentExtension::import_post(Ref<GLTFState> p_state, Node *p_root) { } // Export process. -Error GLTFDocumentExtension::export_preflight(Node *p_root) { +Error GLTFDocumentExtension::export_preflight(Ref<GLTFState> p_state, Node *p_root) { ERR_FAIL_NULL_V(p_root, ERR_INVALID_PARAMETER); int err = OK; - GDVIRTUAL_CALL(_export_preflight, p_root, err); + GDVIRTUAL_CALL(_export_preflight, p_state, p_root, err); return Error(err); } diff --git a/modules/gltf/extensions/gltf_document_extension.h b/modules/gltf/extensions/gltf_document_extension.h index 7cc9ca592f..66cb9a3c33 100644 --- a/modules/gltf/extensions/gltf_document_extension.h +++ b/modules/gltf/extensions/gltf_document_extension.h @@ -49,7 +49,7 @@ public: virtual Error import_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_json, Node *p_node); virtual Error import_post(Ref<GLTFState> p_state, Node *p_node); // Export process. - virtual Error export_preflight(Node *p_state); + virtual Error export_preflight(Ref<GLTFState> p_state, Node *p_root); virtual void convert_scene_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Node *p_scene_node); virtual Error export_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_json, Node *p_node); virtual Error export_post(Ref<GLTFState> p_state); @@ -63,7 +63,7 @@ public: GDVIRTUAL4R(int, _import_node, Ref<GLTFState>, Ref<GLTFNode>, Dictionary, Node *); GDVIRTUAL2R(int, _import_post, Ref<GLTFState>, Node *); // Export process. - GDVIRTUAL1R(int, _export_preflight, Node *); + GDVIRTUAL2R(int, _export_preflight, Ref<GLTFState>, Node *); GDVIRTUAL3(_convert_scene_node, Ref<GLTFState>, Ref<GLTFNode>, Node *); GDVIRTUAL4R(int, _export_node, Ref<GLTFState>, Ref<GLTFNode>, Dictionary, Node *); GDVIRTUAL1R(int, _export_post, Ref<GLTFState>); diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 2cb2d21854..f4db576b0c 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -6930,7 +6930,7 @@ Error GLTFDocument::append_from_scene(Node *p_node, Ref<GLTFState> p_state, uint document_extensions.clear(); for (Ref<GLTFDocumentExtension> ext : all_document_extensions) { ERR_CONTINUE(ext.is_null()); - Error err = ext->export_preflight(p_node); + Error err = ext->export_preflight(p_state, p_node); if (err == OK) { document_extensions.push_back(ext); } diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 137fd61a25..d0f52488bb 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -73,7 +73,7 @@ static bool _create_project_solution_if_needed() { CSharpLanguage *CSharpLanguage::singleton = nullptr; -GDNativeInstanceBindingCallbacks CSharpLanguage::_instance_binding_callbacks = { +GDExtensionInstanceBindingCallbacks CSharpLanguage::_instance_binding_callbacks = { &_instance_binding_create_callback, &_instance_binding_free_callback, &_instance_binding_reference_callback @@ -1293,7 +1293,7 @@ void CSharpLanguage::_instance_binding_free_callback(void *, void *, void *p_bin } } -GDNativeBool CSharpLanguage::_instance_binding_reference_callback(void *p_token, void *p_binding, GDNativeBool p_reference) { +GDExtensionBool CSharpLanguage::_instance_binding_reference_callback(void *p_token, void *p_binding, GDExtensionBool p_reference) { CRASH_COND(!p_binding); CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)p_binding)->get(); @@ -2202,7 +2202,7 @@ void CSharpScript::reload_registered_script(Ref<CSharpScript> p_script) { void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) { bool tool = false; - // TODO: Use GDNative godot_dictionary + // TODO: Use GDExtension godot_dictionary Array methods_array; methods_array.~Array(); Dictionary rpc_functions_dict; diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index e5e53acb07..68d374d262 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -352,9 +352,9 @@ class CSharpLanguage : public ScriptLanguage { static void *_instance_binding_create_callback(void *p_token, void *p_instance); static void _instance_binding_free_callback(void *p_token, void *p_instance, void *p_binding); - static GDNativeBool _instance_binding_reference_callback(void *p_token, void *p_binding, GDNativeBool p_reference); + static GDExtensionBool _instance_binding_reference_callback(void *p_token, void *p_binding, GDExtensionBool p_reference); - static GDNativeInstanceBindingCallbacks _instance_binding_callbacks; + static GDExtensionInstanceBindingCallbacks _instance_binding_callbacks; public: static void *get_instance_binding(Object *p_object); diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs index 9a46b7d164..ccaba4d727 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedFields.cs @@ -45,7 +45,7 @@ namespace Godot.SourceGenerators.Sample [Export] private Color field_Color = Colors.Aquamarine; [Export] private Plane field_Plane = Plane.PlaneXZ; [Export] private Callable field_Callable = new Callable(Engine.GetMainLoop(), "_process"); - [Export] private SignalInfo field_SignalInfo = new SignalInfo(Engine.GetMainLoop(), "property_list_changed"); + [Export] private Signal field_Signal = new Signal(Engine.GetMainLoop(), "property_list_changed"); // Enums [SuppressMessage("ReSharper", "UnusedMember.Local")] diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs index eb83833b40..0c0feb3901 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/ExportedProperties.cs @@ -133,7 +133,7 @@ namespace Godot.SourceGenerators.Sample [Export] private Color property_Color { get; set; } = Colors.Aquamarine; [Export] private Plane property_Plane { get; set; } = Plane.PlaneXZ; [Export] private Callable property_Callable { get; set; } = new Callable(Engine.GetMainLoop(), "_process"); - [Export] private SignalInfo property_SignalInfo { get; set; } = new SignalInfo(Engine.GetMainLoop(), "property_list_changed"); + [Export] private Signal property_Signal { get; set; } = new Signal(Engine.GetMainLoop(), "property_list_changed"); // Enums [SuppressMessage("ReSharper", "UnusedMember.Local")] diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs index 15f5803bf0..ee1374d0b9 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalType.cs @@ -37,7 +37,7 @@ namespace Godot.SourceGenerators Color, Plane, Callable, - SignalInfo, + Signal, // Enums Enum, diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs index 5b3f677f87..8b2f96036b 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MarshalUtils.cs @@ -56,7 +56,7 @@ namespace Godot.SourceGenerators MarshalType.Color => VariantType.Color, MarshalType.Plane => VariantType.Plane, MarshalType.Callable => VariantType.Callable, - MarshalType.SignalInfo => VariantType.Signal, + MarshalType.Signal => VariantType.Signal, MarshalType.Enum => VariantType.Int, MarshalType.ByteArray => VariantType.PackedByteArray, MarshalType.Int32Array => VariantType.PackedInt32Array, @@ -147,7 +147,7 @@ namespace Godot.SourceGenerators { Name: "Plane" } => MarshalType.Plane, { Name: "RID" } => MarshalType.RID, { Name: "Callable" } => MarshalType.Callable, - { Name: "SignalInfo" } => MarshalType.SignalInfo, + { Name: "Signal" } => MarshalType.Signal, { Name: "Variant" } => MarshalType.Variant, _ => null }; @@ -304,7 +304,12 @@ namespace Godot.SourceGenerators { return marshalType switch { - // For generic Godot collections, VariantUtils.ConvertTo<T> is slower, so we need this special case + // We need a special case for GodotObjectOrDerived[], because it's not supported by VariantUtils.ConvertTo<T> + MarshalType.GodotObjectOrDerivedArray => + source.Append(VariantUtils, ".ConvertToSystemArrayOfGodotObject<", + ((IArrayTypeSymbol)typeSymbol).ElementType.FullQualifiedNameIncludeGlobal(), ">(", + inputExpr, ")"), + // We need a special case for generic Godot collections and GodotObjectOrDerived[], because VariantUtils.ConvertTo<T> is slower MarshalType.GodotGenericDictionary => source.Append(VariantUtils, ".ConvertToDictionaryObject<", ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedNameIncludeGlobal(), ", ", @@ -324,7 +329,10 @@ namespace Godot.SourceGenerators { return marshalType switch { - // For generic Godot collections, VariantUtils.CreateFrom<T> is slower, so we need this special case + // We need a special case for GodotObjectOrDerived[], because it's not supported by VariantUtils.CreateFrom<T> + MarshalType.GodotObjectOrDerivedArray => + source.Append(VariantUtils, ".CreateFromSystemArrayOfGodotObject(", inputExpr, ")"), + // We need a special case for generic Godot collections and GodotObjectOrDerived[], because VariantUtils.CreateFrom<T> is slower MarshalType.GodotGenericDictionary => source.Append(VariantUtils, ".CreateFromDictionary(", inputExpr, ")"), MarshalType.GodotGenericArray => @@ -339,7 +347,11 @@ namespace Godot.SourceGenerators { return marshalType switch { - // For generic Godot collections, Variant.As<T> is slower, so we need this special case + // We need a special case for GodotObjectOrDerived[], because it's not supported by Variant.As<T> + MarshalType.GodotObjectOrDerivedArray => + source.Append(inputExpr, ".AsGodotObjectArray<", + ((IArrayTypeSymbol)typeSymbol).ElementType.FullQualifiedNameIncludeGlobal(), ">()"), + // We need a special case for generic Godot collections and GodotObjectOrDerived[], because Variant.As<T> is slower MarshalType.GodotGenericDictionary => source.Append(inputExpr, ".AsGodotDictionary<", ((INamedTypeSymbol)typeSymbol).TypeArguments[0].FullQualifiedNameIncludeGlobal(), ", ", @@ -357,7 +369,10 @@ namespace Godot.SourceGenerators { return marshalType switch { - // For generic Godot collections, Variant.From<T> is slower, so we need this special case + // We need a special case for GodotObjectOrDerived[], because it's not supported by Variant.From<T> + MarshalType.GodotObjectOrDerivedArray => + source.Append("global::Godot.Variant.CreateFrom(", inputExpr, ")"), + // We need a special case for generic Godot collections, because Variant.From<T> is slower MarshalType.GodotGenericDictionary or MarshalType.GodotGenericArray => source.Append("global::Godot.Variant.CreateFrom(", inputExpr, ")"), _ => source.Append("global::Godot.Variant.From<", diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 9f0bc3fbe3..7ef42247d1 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -3651,7 +3651,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.cs_type = itype.proxy_name; itype.cs_in_expr = "%0"; itype.c_in = "%5using %0 %1_in = " C_METHOD_MANAGED_TO_SIGNAL "(in %1);\n"; - itype.c_out = "%5return " C_METHOD_MANAGED_FROM_SIGNAL "(&%1);\n"; + itype.c_out = "%5return " C_METHOD_MANAGED_FROM_SIGNAL "(in %1);\n"; itype.c_arg_in = "&%s_in"; itype.c_type = "godot_signal"; itype.c_type_in = "in " + itype.cs_type; diff --git a/modules/mono/glue/GodotSharp/GodotSharp.sln.DotSettings b/modules/mono/glue/GodotSharp/GodotSharp.sln.DotSettings index ba65b61e95..65f33e43a8 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp.sln.DotSettings +++ b/modules/mono/glue/GodotSharp/GodotSharp.sln.DotSettings @@ -1,7 +1,7 @@ <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GC/@EntryIndexedValue">GC</s:String> <s:Boolean x:Key="/Default/UserDictionary/Words/=alcs/@EntryIndexedValue">True</s:Boolean> - <s:Boolean x:Key="/Default/UserDictionary/Words/=gdnative/@EntryIndexedValue">True</s:Boolean> + <s:Boolean x:Key="/Default/UserDictionary/Words/=gdextension/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=godotsharp/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=icall/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=quat/@EntryIndexedValue">True</s:Boolean> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs index b7d633517a..acdae83d2e 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/AssemblyHasScriptsAttribute.cs @@ -1,20 +1,32 @@ using System; +using System.Diagnostics.CodeAnalysis; #nullable enable namespace Godot { /// <summary> - /// An attribute that determines if an assembly has scripts. If so, what types of scripts the assembly has. + /// Attribute that determines that the assembly contains Godot scripts and, optionally, the + /// collection of types that implement scripts; otherwise, retrieving the types requires lookup. /// </summary> [AttributeUsage(AttributeTargets.Assembly)] public class AssemblyHasScriptsAttribute : Attribute { + /// <summary> + /// If the Godot scripts contained in the assembly require lookup + /// and can't rely on <see cref="ScriptTypes"/>. + /// </summary> + [MemberNotNullWhen(false, nameof(ScriptTypes))] public bool RequiresLookup { get; } + + /// <summary> + /// The collection of types that implement a Godot script. + /// </summary> public Type[]? ScriptTypes { get; } /// <summary> - /// Constructs a new AssemblyHasScriptsAttribute instance. + /// Constructs a new AssemblyHasScriptsAttribute instance + /// that requires lookup to get the Godot scripts. /// </summary> public AssemblyHasScriptsAttribute() { @@ -23,9 +35,10 @@ namespace Godot } /// <summary> - /// Constructs a new AssemblyHasScriptsAttribute instance. + /// Constructs a new AssemblyHasScriptsAttribute instance + /// that includes the Godot script types and requires no lookup. /// </summary> - /// <param name="scriptTypes">The specified type(s) of scripts.</param> + /// <param name="scriptTypes">The collection of types that implement a Godot script.</param> public AssemblyHasScriptsAttribute(Type[] scriptTypes) { RequiresLookup = false; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportAttribute.cs index 3d204bdf9f..a48d79091f 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportAttribute.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportAttribute.cs @@ -3,23 +3,30 @@ using System; namespace Godot { /// <summary> - /// An attribute used to export objects. + /// Exports the annotated member as a property of the Godot Object. /// </summary> [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] public sealed class ExportAttribute : Attribute { - private PropertyHint hint; - private string hintString; + /// <summary> + /// Optional hint that determines how the property should be handled by the editor. + /// </summary> + public PropertyHint Hint { get; } + + /// <summary> + /// Optional string that can contain additional metadata for the <see cref="Hint"/>. + /// </summary> + public string HintString { get; } /// <summary> /// Constructs a new ExportAttribute Instance. /// </summary> - /// <param name="hint">A hint to the exported object.</param> - /// <param name="hintString">A string representing the exported object.</param> + /// <param name="hint">The hint for the exported property.</param> + /// <param name="hintString">A string that may contain additional metadata for the hint.</param> public ExportAttribute(PropertyHint hint = PropertyHint.None, string hintString = "") { - this.hint = hint; - this.hintString = hintString; + Hint = hint; + HintString = hintString; } } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportCategoryAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportCategoryAttribute.cs index 101e56f8d3..2ae55acd3e 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportCategoryAttribute.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportCategoryAttribute.cs @@ -8,7 +8,10 @@ namespace Godot [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] public sealed class ExportCategoryAttribute : Attribute { - private string name; + /// <summary> + /// Name of the category. + /// </summary> + public string Name { get; } /// <summary> /// Define a new category for the following exported properties. @@ -16,7 +19,7 @@ namespace Godot /// <param name="name">The name of the category.</param> public ExportCategoryAttribute(string name) { - this.name = name; + Name = name; } } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportGroupAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportGroupAttribute.cs index 3bd532cec1..82bd446640 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportGroupAttribute.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportGroupAttribute.cs @@ -1,5 +1,7 @@ using System; +#nullable enable + namespace Godot { /// <summary> @@ -8,8 +10,15 @@ namespace Godot [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] public sealed class ExportGroupAttribute : Attribute { - private string name; - private string prefix; + /// <summary> + /// Name of the group. + /// </summary> + public string Name { get; } + + /// <summary> + /// If provided, the prefix that all properties must have to be considered part of the group. + /// </summary> + public string? Prefix { get; } /// <summary> /// Define a new group for the following exported properties. @@ -18,8 +27,8 @@ namespace Godot /// <param name="prefix">If provided, the group would make group to only consider properties that have this prefix.</param> public ExportGroupAttribute(string name, string prefix = "") { - this.name = name; - this.prefix = prefix; + Name = name; + Prefix = prefix; } } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportSubgroupAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportSubgroupAttribute.cs index 2ae6eb0b68..3282b466f6 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportSubgroupAttribute.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportSubgroupAttribute.cs @@ -1,5 +1,7 @@ using System; +#nullable enable + namespace Godot { /// <summary> @@ -8,8 +10,15 @@ namespace Godot [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] public sealed class ExportSubgroupAttribute : Attribute { - private string name; - private string prefix; + /// <summary> + /// Name of the subgroup. + /// </summary> + public string Name { get; } + + /// <summary> + /// If provided, the prefix that all properties must have to be considered part of the subgroup. + /// </summary> + public string? Prefix { get; } /// <summary> /// Define a new subgroup for the following exported properties. This helps to organize properties in the Inspector dock. @@ -18,8 +27,8 @@ namespace Godot /// <param name="prefix">If provided, the subgroup would make group to only consider properties that have this prefix.</param> public ExportSubgroupAttribute(string name, string prefix = "") { - this.name = name; - this.prefix = prefix; + Name = name; + Prefix = prefix; } } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs index fb37838ffa..afee926464 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs @@ -19,17 +19,17 @@ namespace Godot /// <summary> /// If the method will also be called locally; otherwise, it is only called remotely. /// </summary> - public bool CallLocal { get; set; } = false; + public bool CallLocal { get; init; } = false; /// <summary> /// Transfer mode for the annotated method. /// </summary> - public MultiplayerPeer.TransferModeEnum TransferMode { get; set; } = MultiplayerPeer.TransferModeEnum.Reliable; + public MultiplayerPeer.TransferModeEnum TransferMode { get; init; } = MultiplayerPeer.TransferModeEnum.Reliable; /// <summary> /// Transfer channel for the annotated mode. /// </summary> - public int TransferChannel { get; set; } = 0; + public int TransferChannel { get; init; } = 0; /// <summary> /// Constructs a <see cref="RPCAttribute"/> instance. diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs index 2c8a53ae1c..f05bcdac38 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ScriptPathAttribute.cs @@ -8,6 +8,9 @@ namespace Godot [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] public class ScriptPathAttribute : Attribute { + /// <summary> + /// File path to the script. + /// </summary> public string Path { get; } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs index a3cfecfaa6..d94fbff331 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs @@ -613,8 +613,8 @@ namespace Godot return VariantUtils.CreateFrom(plane); case Callable callable: return VariantUtils.CreateFrom(callable); - case SignalInfo signalInfo: - return VariantUtils.CreateFrom(signalInfo); + case Signal signal: + return VariantUtils.CreateFrom(signal); case string @string: return VariantUtils.CreateFrom(@string); case byte[] byteArray: @@ -705,7 +705,7 @@ namespace Godot [typeof(Color)] = (in godot_variant variant) => VariantUtils.ConvertTo<Color>(variant), [typeof(Plane)] = (in godot_variant variant) => VariantUtils.ConvertTo<Plane>(variant), [typeof(Callable)] = (in godot_variant variant) => VariantUtils.ConvertTo<Callable>(variant), - [typeof(SignalInfo)] = (in godot_variant variant) => VariantUtils.ConvertTo<SignalInfo>(variant), + [typeof(Signal)] = (in godot_variant variant) => VariantUtils.ConvertTo<Signal>(variant), [typeof(string)] = (in godot_variant variant) => VariantUtils.ConvertTo<string>(variant), [typeof(byte[])] = (in godot_variant variant) => VariantUtils.ConvertTo<byte[]>(variant), [typeof(int[])] = (in godot_variant variant) => VariantUtils.ConvertTo<int[]>(variant), @@ -739,6 +739,26 @@ namespace Godot if (typeof(Godot.Object).IsAssignableFrom(type)) return Convert.ChangeType(VariantUtils.ConvertTo<Godot.Object>(variant), type); + if (typeof(Godot.Object[]).IsAssignableFrom(type)) + { + static Godot.Object[] ConvertToSystemArrayOfGodotObject(in godot_array nativeArray, Type type) + { + var array = Collections.Array.CreateTakingOwnershipOfDisposableValue( + NativeFuncs.godotsharp_array_new_copy(nativeArray)); + + int length = array.Count; + var ret = (Godot.Object[])Activator.CreateInstance(type, length)!; + + for (int i = 0; i < length; i++) + ret[i] = array[i].AsGodotObject(); + + return ret; + } + + using var godotArray = NativeFuncs.godotsharp_variant_as_array(variant); + return Convert.ChangeType(ConvertToSystemArrayOfGodotObject(godotArray, type), type); + } + if (type.IsEnum) { var enumUnderlyingType = type.GetEnumUnderlyingType(); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs index 6176093bc1..0d9a698af0 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs @@ -99,7 +99,7 @@ namespace Godot.NativeInterop if (type == typeof(Callable)) return Variant.Type.Callable; - if (type == typeof(SignalInfo)) + if (type == typeof(Signal)) return Variant.Type.Signal; if (type.IsEnum) @@ -288,9 +288,9 @@ namespace Godot.NativeInterop return new Callable(); } - // SignalInfo + // Signal - public static godot_signal ConvertSignalToNative(in SignalInfo p_managed_signal) + public static godot_signal ConvertSignalToNative(in Signal p_managed_signal) { ulong ownerId = p_managed_signal.Owner.GetInstanceId(); godot_string_name name; @@ -308,12 +308,12 @@ namespace Godot.NativeInterop return new godot_signal(name, ownerId); } - public static SignalInfo ConvertSignalToManaged(in godot_signal p_signal) + public static Signal ConvertSignalToManaged(in godot_signal p_signal) { var owner = GD.InstanceFromId(p_signal.ObjectId); var name = StringName.CreateTakingOwnershipOfDisposableValue( NativeFuncs.godotsharp_string_name_new_copy(p_signal.Name)); - return new SignalInfo(owner, name); + return new Signal(owner, name); } // Array @@ -333,22 +333,6 @@ namespace Godot.NativeInterop return ret; } - // TODO: This needs reflection. Look for an alternative. - internal static Godot.Object[] ConvertNativeGodotArrayToSystemArrayOfGodotObjectType(in godot_array p_array, - Type type) - { - var array = Collections.Array.CreateTakingOwnershipOfDisposableValue( - NativeFuncs.godotsharp_array_new_copy(p_array)); - - int length = array.Count; - var ret = (Godot.Object[])Activator.CreateInstance(type, length)!; - - for (int i = 0; i < length; i++) - ret[i] = array[i].AsGodotObject(); - - return ret; - } - internal static StringName[] ConvertNativeGodotArrayToSystemArrayOfStringName(in godot_array p_array) { var array = Collections.Array.CreateTakingOwnershipOfDisposableValue( diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs index ba8e7a6c65..6a4717f2c3 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs @@ -102,7 +102,7 @@ namespace Godot.NativeInterop => new() { Type = Variant.Type.Signal, Signal = from }; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static godot_variant CreateFromSignalInfo(SignalInfo from) + public static godot_variant CreateFromSignal(Signal from) => CreateFromSignalTakingOwnershipOfDisposableValue( Marshaling.ConvertSignalToNative(from)); @@ -486,7 +486,7 @@ namespace Godot.NativeInterop => NativeFuncs.godotsharp_variant_as_signal(p_var); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SignalInfo ConvertToSignalInfo(in godot_variant p_var) + public static Signal ConvertToSignalManaged(in godot_variant p_var) => Marshaling.ConvertSignalToManaged(ConvertToSignal(p_var)); public static godot_array ConvertToArray(in godot_variant p_var) @@ -594,12 +594,5 @@ namespace Godot.NativeInterop using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var); return Marshaling.ConvertNativeGodotArrayToSystemArrayOfGodotObjectType<T>(godotArray); } - - // ReSharper disable once RedundantNameQualifier - public static Godot.Object[] ConvertToSystemArrayOfGodotObject(in godot_variant p_var, Type type) - { - using var godotArray = NativeFuncs.godotsharp_variant_as_array(p_var); - return Marshaling.ConvertNativeGodotArrayToSystemArrayOfGodotObjectType(godotArray, type); - } } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs index 80ef2a1ea1..9a3ed85e66 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.generic.cs @@ -125,8 +125,8 @@ public partial class VariantUtils if (typeof(T) == typeof(Callable)) return CreateFromCallable(UnsafeAs<Callable>(from)); - if (typeof(T) == typeof(SignalInfo)) - return CreateFromSignalInfo(UnsafeAs<SignalInfo>(from)); + if (typeof(T) == typeof(Signal)) + return CreateFromSignal(UnsafeAs<Signal>(from)); if (typeof(T) == typeof(string)) return CreateFromString(UnsafeAs<string>(from)); @@ -311,8 +311,8 @@ public partial class VariantUtils if (typeof(T) == typeof(Callable)) return UnsafeAsT(ConvertToCallableManaged(variant)); - if (typeof(T) == typeof(SignalInfo)) - return UnsafeAsT(ConvertToSignalInfo(variant)); + if (typeof(T) == typeof(Signal)) + return UnsafeAsT(ConvertToSignalManaged(variant)); if (typeof(T) == typeof(string)) return UnsafeAsT(ConvertToStringObject(variant)); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Signal.cs index 3f50df0a0d..f9b8f06603 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/SignalInfo.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Signal.cs @@ -3,7 +3,7 @@ namespace Godot /// <summary> /// Represents a signal defined in an object. /// </summary> - public readonly struct SignalInfo + public readonly struct Signal : IAwaitable<Variant[]> { private readonly Object _owner; private readonly StringName _signalName; @@ -18,15 +18,20 @@ namespace Godot public StringName Name => _signalName; /// <summary> - /// Creates a new <see cref="SignalInfo"/> with the name <paramref name="name"/> + /// Creates a new <see cref="Signal"/> with the name <paramref name="name"/> /// in the specified <paramref name="owner"/>. /// </summary> /// <param name="owner">Object that contains the signal.</param> /// <param name="name">Name of the signal.</param> - public SignalInfo(Object owner, StringName name) + public Signal(Object owner, StringName name) { _owner = owner; _signalName = name; } + + public IAwaiter<Variant[]> GetAwaiter() + { + return new SignalAwaiter(_owner, _signalName, _owner); + } } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Variant.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Variant.cs index 49a363cef2..c4c53a39f9 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Variant.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Variant.cs @@ -137,7 +137,7 @@ public partial struct Variant : IDisposable Type.Rid => AsRID(), Type.Object => AsGodotObject(), Type.Callable => AsCallable(), - Type.Signal => AsSignalInfo(), + Type.Signal => AsSignal(), Type.Dictionary => AsGodotDictionary(), Type.Array => AsGodotArray(), Type.PackedByteArray => AsByteArray(), @@ -283,8 +283,8 @@ public partial struct Variant : IDisposable VariantUtils.ConvertToCallableManaged((godot_variant)NativeVar); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SignalInfo AsSignalInfo() => - VariantUtils.ConvertToSignalInfo((godot_variant)NativeVar); + public Signal AsSignal() => + VariantUtils.ConvertToSignalManaged((godot_variant)NativeVar); [MethodImpl(MethodImplOptions.AggressiveInlining)] public byte[] AsByteArray() => @@ -464,7 +464,7 @@ public partial struct Variant : IDisposable public static explicit operator Callable(Variant from) => from.AsCallable(); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static explicit operator SignalInfo(Variant from) => from.AsSignalInfo(); + public static explicit operator Signal(Variant from) => from.AsSignal(); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static explicit operator byte[](Variant from) => from.AsByteArray(); @@ -614,7 +614,7 @@ public partial struct Variant : IDisposable public static Variant CreateFrom(Callable from) => from; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Variant CreateFrom(SignalInfo from) => from; + public static Variant CreateFrom(Signal from) => from; [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Variant CreateFrom(Span<byte> from) => from; @@ -804,8 +804,8 @@ public partial struct Variant : IDisposable CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromCallable(from)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator Variant(SignalInfo from) => - CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSignalInfo(from)); + public static implicit operator Variant(Signal from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSignal(from)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator Variant(byte[] from) => diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj index 503e5abe37..644212c74d 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj +++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj @@ -116,7 +116,7 @@ <Compile Include="Core\NativeInterop\NativeFuncs.cs" /> <Compile Include="Core\NativeInterop\InteropStructs.cs" /> <Compile Include="Core\NativeInterop\Marshaling.cs" /> - <Compile Include="Core\SignalInfo.cs" /> + <Compile Include="Core\Signal.cs" /> <Compile Include="Core\SignalAwaiter.cs" /> <Compile Include="Core\StringExtensions.cs" /> <Compile Include="Core\StringName.cs" /> diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp index 0e40e5a4af..e5949c935b 100644 --- a/modules/navigation/godot_navigation_server.cpp +++ b/modules/navigation/godot_navigation_server.cpp @@ -704,14 +704,14 @@ bool GodotNavigationServer::agent_is_map_changed(RID p_agent) const { return agent->is_map_changed(); } -COMMAND_4(agent_set_callback, RID, p_agent, Object *, p_receiver, StringName, p_method, Variant, p_udata) { +COMMAND_4(agent_set_callback, RID, p_agent, ObjectID, p_object_id, StringName, p_method, Variant, p_udata) { RvoAgent *agent = agent_owner.get_or_null(p_agent); ERR_FAIL_COND(agent == nullptr); - agent->set_callback(p_receiver == nullptr ? ObjectID() : p_receiver->get_instance_id(), p_method, p_udata); + agent->set_callback(p_object_id, p_method, p_udata); if (agent->get_map()) { - if (p_receiver == nullptr) { + if (p_object_id == ObjectID()) { agent->get_map()->remove_agent_as_controlled(agent); } else { agent->get_map()->set_agent_as_controlled(agent); diff --git a/modules/navigation/godot_navigation_server.h b/modules/navigation/godot_navigation_server.h index 08ad545b37..18431e39b8 100644 --- a/modules/navigation/godot_navigation_server.h +++ b/modules/navigation/godot_navigation_server.h @@ -172,7 +172,7 @@ public: COMMAND_2(agent_set_position, RID, p_agent, Vector3, p_position); COMMAND_2(agent_set_ignore_y, RID, p_agent, bool, p_ignore); virtual bool agent_is_map_changed(RID p_agent) const override; - COMMAND_4_DEF(agent_set_callback, RID, p_agent, Object *, p_receiver, StringName, p_method, Variant, p_udata, Variant()); + COMMAND_4_DEF(agent_set_callback, RID, p_agent, ObjectID, p_object_id, StringName, p_method, Variant, p_udata, Variant()); COMMAND_1(free, RID, p_object); diff --git a/modules/openxr/action_map/openxr_action.cpp b/modules/openxr/action_map/openxr_action.cpp index 7e02f0374d..634f653376 100644 --- a/modules/openxr/action_map/openxr_action.cpp +++ b/modules/openxr/action_map/openxr_action.cpp @@ -75,6 +75,7 @@ String OpenXRAction::get_name_with_set() const { void OpenXRAction::set_localized_name(const String p_localized_name) { localized_name = p_localized_name; + emit_changed(); } String OpenXRAction::get_localized_name() const { @@ -83,6 +84,7 @@ String OpenXRAction::get_localized_name() const { 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 { @@ -91,6 +93,7 @@ OpenXRAction::ActionType OpenXRAction::get_action_type() const { void OpenXRAction::set_toplevel_paths(const PackedStringArray p_toplevel_paths) { toplevel_paths = p_toplevel_paths; + emit_changed(); } PackedStringArray OpenXRAction::get_toplevel_paths() const { @@ -100,15 +103,18 @@ PackedStringArray OpenXRAction::get_toplevel_paths() const { 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(); } diff --git a/modules/openxr/action_map/openxr_action_map.cpp b/modules/openxr/action_map/openxr_action_map.cpp index 123f860ce9..226bfa18ba 100644 --- a/modules/openxr/action_map/openxr_action_map.cpp +++ b/modules/openxr/action_map/openxr_action_map.cpp @@ -95,6 +95,7 @@ void OpenXRActionMap::add_action_set(Ref<OpenXRActionSet> p_action_set) { if (action_sets.find(p_action_set) == -1) { action_sets.push_back(p_action_set); + emit_changed(); } } @@ -102,6 +103,7 @@ 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(); } } @@ -146,6 +148,7 @@ void OpenXRActionMap::add_interaction_profile(Ref<OpenXRInteractionProfile> p_in if (interaction_profiles.find(p_interaction_profile) == -1) { interaction_profiles.push_back(p_interaction_profile); + emit_changed(); } } @@ -153,6 +156,7 @@ void OpenXRActionMap::remove_interaction_profile(Ref<OpenXRInteractionProfile> p int idx = interaction_profiles.find(p_interaction_profile); if (idx != -1) { interaction_profiles.remove_at(idx); + emit_changed(); } } @@ -489,30 +493,34 @@ Ref<OpenXRAction> OpenXRActionMap::get_action(const String p_path) const { return Ref<OpenXRAction>(); } -void OpenXRActionMap::remove_action(const String p_path) { +void OpenXRActionMap::remove_action(const String p_path, bool p_remove_interaction_profiles) { Ref<OpenXRAction> action = get_action(p_path); if (action.is_valid()) { + for (int i = 0; i < interaction_profiles.size(); i++) { + Ref<OpenXRInteractionProfile> interaction_profile = interaction_profiles[i]; + + 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); } - - for (int i = 0; i < interaction_profiles.size(); i++) { - Ref<OpenXRInteractionProfile> interaction_profile = interaction_profiles[i]; - - // Remove any bindings for this action - interaction_profile->remove_binding_for_action(action); - } } } -PackedStringArray OpenXRActionMap::get_top_level_paths(Ref<OpenXRAction> p_action) { +PackedStringArray OpenXRActionMap::get_top_level_paths(const Ref<OpenXRAction> p_action) { PackedStringArray arr; for (int i = 0; i < interaction_profiles.size(); i++) { Ref<OpenXRInteractionProfile> ip = interaction_profiles[i]; - const OpenXRDefs::InteractionProfile *profile = OpenXRDefs::get_profile(ip->get_interaction_profile_path()); + const OpenXRInteractionProfileMetaData::InteractionProfile *profile = OpenXRInteractionProfileMetaData::get_singleton()->get_profile(ip->get_interaction_profile_path()); if (profile != nullptr) { for (int j = 0; j < ip->get_binding_count(); j++) { @@ -521,9 +529,9 @@ PackedStringArray OpenXRActionMap::get_top_level_paths(Ref<OpenXRAction> p_actio PackedStringArray paths = binding->get_paths(); for (int k = 0; k < paths.size(); k++) { - const OpenXRDefs::IOPath *io_path = profile->get_io_path(paths[k]); + const OpenXRInteractionProfileMetaData::IOPath *io_path = profile->get_io_path(paths[k]); if (io_path != nullptr) { - String top_path = String(io_path->top_level_path->openxr_path); + String top_path = io_path->top_level_path; if (!arr.has(top_path)) { arr.push_back(top_path); @@ -535,7 +543,7 @@ PackedStringArray OpenXRActionMap::get_top_level_paths(Ref<OpenXRAction> p_actio } } - print_line("Toplevel paths for", p_action->get_name_with_set(), "are", arr); + // print_line("Toplevel paths for", p_action->get_name_with_set(), "are", arr); return arr; } diff --git a/modules/openxr/action_map/openxr_action_map.h b/modules/openxr/action_map/openxr_action_map.h index 8659cd3942..43a4d741f4 100644 --- a/modules/openxr/action_map/openxr_action_map.h +++ b/modules/openxr/action_map/openxr_action_map.h @@ -71,8 +71,8 @@ public: // 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); // Remove action from action set, also removes it from interaction profiles - PackedStringArray get_top_level_paths(Ref<OpenXRAction> p_action); // Determines the top level paths based on where an action is bound in interaction profiles + 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 diff --git a/modules/openxr/action_map/openxr_action_set.cpp b/modules/openxr/action_map/openxr_action_set.cpp index be45218300..f46ac4a5ce 100644 --- a/modules/openxr/action_map/openxr_action_set.cpp +++ b/modules/openxr/action_map/openxr_action_set.cpp @@ -62,6 +62,7 @@ Ref<OpenXRActionSet> OpenXRActionSet::new_action_set(const char *p_name, const c void OpenXRActionSet::set_localized_name(const String p_localized_name) { localized_name = p_localized_name; + emit_changed(); } String OpenXRActionSet::get_localized_name() const { @@ -70,6 +71,7 @@ String OpenXRActionSet::get_localized_name() const { void OpenXRActionSet::set_priority(const int p_priority) { priority = p_priority; + emit_changed(); } int OpenXRActionSet::get_priority() const { @@ -82,11 +84,16 @@ int OpenXRActionSet::get_action_count() const { 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.size() == 0) { + 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) { @@ -125,6 +132,7 @@ void OpenXRActionSet::add_action(Ref<OpenXRAction> p_action) { p_action->action_set = this; actions.push_back(p_action); + emit_changed(); } } @@ -135,6 +143,8 @@ void OpenXRActionSet::remove_action(Ref<OpenXRAction> p_action) { 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(); } } diff --git a/modules/openxr/action_map/openxr_defs.cpp b/modules/openxr/action_map/openxr_defs.cpp deleted file mode 100644 index 59ce829f1b..0000000000 --- a/modules/openxr/action_map/openxr_defs.cpp +++ /dev/null @@ -1,671 +0,0 @@ -/*************************************************************************/ -/* openxr_defs.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "openxr_defs.h" - -// Our top level paths to which devices can be bound -OpenXRDefs::TopLevelPath OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_TOP_LEVEL_PATH_MAX] = { - // Core OpenXR paths - { "Left hand controller", "/user/hand/left" }, - { "Right hand controller", "/user/hand/right" }, - { "Head", "/user/head" }, - { "Gamepad", "/user/gamepad" }, - { "Treadmill", "/user/treadmill" }, - - // Specific to HTC tracker extension - // { "Handheld object tracker", "/user/vive_tracker_htcx/role/handheld_object" }, - { "Left foot tracker", "/user/vive_tracker_htcx/role/left_foot" }, - { "Right foot tracker", "/user/vive_tracker_htcx/role/right_foot" }, - { "Left shoulder tracker", "/user/vive_tracker_htcx/role/left_shoulder" }, - { "Right shoulder tracker", "/user/vive_tracker_htcx/role/right_shoulder" }, - { "Left elbow tracker", "/user/vive_tracker_htcx/role/left_elbow" }, - { "Right elbow tracker", "/user/vive_tracker_htcx/role/right_elbow" }, - { "Left knee tracker", "/user/vive_tracker_htcx/role/left_knee" }, - { "Right knee tracker", "/user/vive_tracker_htcx/role/right_knee" }, - { "Waist tracker", "/user/vive_tracker_htcx/role/waist" }, - { "Chest tracker", "/user/vive_tracker_htcx/role/chest" }, - { "Camera tracker", "/user/vive_tracker_htcx/role/camera" }, - { "Keyboard tracker", "/user/vive_tracker_htcx/role/keyboard" }, - -}; - -// Fallback Khronos simple controller -OpenXRDefs::IOPath OpenXRDefs::simple_io_paths[] = { - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE }, - - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Select click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/select/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Select click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/select/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, -}; - -// Original HTC Vive wands -OpenXRDefs::IOPath OpenXRDefs::vive_io_paths[] = { - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE }, - - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "System click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/system/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "System click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/system/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, -}; - -// Microsoft motion controller (original WMR controllers) -OpenXRDefs::IOPath OpenXRDefs::motion_io_paths[] = { - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE }, - - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, -}; - -// HP MR controller (newer G2 controllers) -OpenXRDefs::IOPath OpenXRDefs::hpmr_io_paths[] = { - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE }, - - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "X click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/x/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Y click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/y/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "A click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/a/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "B click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/b/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Squeeze", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Squeeze", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/squeeze/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - - { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, -}; - -// Meta touch controller (original touch controllers, Quest 1 and Quest 2 controllers) -OpenXRDefs::IOPath OpenXRDefs::touch_io_paths[] = { - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE }, - - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "System click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/system/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "X click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/x/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "X touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/x/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Y click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/y/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Y touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/y/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "A click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/a/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "A touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/a/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "B click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/b/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "B touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/b/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Squeeze", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Squeeze", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/squeeze/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - - { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Thumbstick touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Thumbstick touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, -}; - -// Valve index controller -OpenXRDefs::IOPath OpenXRDefs::index_io_paths[] = { - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE }, - - { "System click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/system/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "System click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/system/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "A click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/a/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "A touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/a/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "A click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/a/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "A touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/a/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "B click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/b/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "B touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/b/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "B click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/b/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "B touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/b/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Squeeze", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Squeeze", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/squeeze/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - - { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Thumbstick touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Thumbstick touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Trackpad force", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/force", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Trackpad force", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/force", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, -}; - -// Samsung odyssey controller -OpenXRDefs::IOPath OpenXRDefs::odyssey_io_paths[] = { - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE }, - - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, -}; - -// Vive Cosmos controller -OpenXRDefs::IOPath OpenXRDefs::vive_cosmos_paths[] = { - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE }, - - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "System click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/system/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "X click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/x/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Y click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/y/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "A click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/a/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "B click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/b/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Shoulder click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/right/input/shoulder/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Shoulder click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/shoulder/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Thumbstick touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Thumbstick touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, -}; - -// Vive Focus 3 controller -OpenXRDefs::IOPath OpenXRDefs::vive_focus3_paths[] = { - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE }, - - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "System click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/system/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "X click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/x/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Y click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/y/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "A click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/a/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "B click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/b/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/touch ", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Squeeze touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Squeeze touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/squeeze/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Thumbstick touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Thumbstick touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Thumbrest touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbrest/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, -}; - -// Huawei controller -OpenXRDefs::IOPath OpenXRDefs::huawei_controller_paths[] = { - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Palm pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/palm_ext/pose", OpenXRAction::OPENXR_ACTION_POSE }, - - { "Home click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/home/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Home click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/home/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Back click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/back/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Back click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/back/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Volume up click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/volume_up/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Volume up click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/volume_up/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Volume down click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/volume_down/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Volume down click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/volume_down/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, -}; - -// HTC Vive tracker -// Interestingly enough trackers don't have buttons or inputs, yet these are defined in the spec. -// I think this can be supported through attachments on the trackers. -OpenXRDefs::IOPath OpenXRDefs::vive_tracker_controller_paths[] = { - // { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_HANDHELD_TRACKER], "/user/vive_tracker_htcx/role/handheld_object/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/left_foot/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/right_foot/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/left_shoulder/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/right_shoulder/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/left_elbow/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/right_elbow/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/left_knee/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/right_knee/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_WAIST_TRACKER], "/user/vive_tracker_htcx/role/waist/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CHEST_TRACKER], "/user/vive_tracker_htcx/role/chest/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CAMERA_TRACKER], "/user/vive_tracker_htcx/role/camera/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_KEYBOARD_TRACKER], "/user/vive_tracker_htcx/role/keyboard/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - // { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_HANDHELD_TRACKER], "/user/vive_tracker_htcx/role/handheld_object/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/left_foot/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/right_foot/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/left_shoulder/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/right_shoulder/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/left_elbow/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/right_elbow/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/left_knee/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/right_knee/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_WAIST_TRACKER], "/user/vive_tracker_htcx/role/waist/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CHEST_TRACKER], "/user/vive_tracker_htcx/role/chest/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CAMERA_TRACKER], "/user/vive_tracker_htcx/role/camera/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_KEYBOARD_TRACKER], "/user/vive_tracker_htcx/role/keyboard/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT }, - - // { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_HANDHELD_TRACKER], "/user/vive_tracker_htcx/role/handheld_object/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/left_foot/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/right_foot/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/left_shoulder/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/right_shoulder/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/left_elbow/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/right_elbow/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/left_knee/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/right_knee/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_WAIST_TRACKER], "/user/vive_tracker_htcx/role/waist/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CHEST_TRACKER], "/user/vive_tracker_htcx/role/chest/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CAMERA_TRACKER], "/user/vive_tracker_htcx/role/camera/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_KEYBOARD_TRACKER], "/user/vive_tracker_htcx/role/keyboard/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - // { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_HANDHELD_TRACKER], "/user/vive_tracker_htcx/role/handheld_object/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/left_foot/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/right_foot/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/left_shoulder/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/right_shoulder/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/left_elbow/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/right_elbow/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/left_knee/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/right_knee/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_WAIST_TRACKER], "/user/vive_tracker_htcx/role/waist/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CHEST_TRACKER], "/user/vive_tracker_htcx/role/chest/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CAMERA_TRACKER], "/user/vive_tracker_htcx/role/camera/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_KEYBOARD_TRACKER], "/user/vive_tracker_htcx/role/keyboard/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - // { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_HANDHELD_TRACKER], "/user/vive_tracker_htcx/role/handheld_object/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/left_foot/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/right_foot/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/left_shoulder/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/right_shoulder/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/left_elbow/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/right_elbow/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/left_knee/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/right_knee/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_WAIST_TRACKER], "/user/vive_tracker_htcx/role/waist/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CHEST_TRACKER], "/user/vive_tracker_htcx/role/chest/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CAMERA_TRACKER], "/user/vive_tracker_htcx/role/camera/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_KEYBOARD_TRACKER], "/user/vive_tracker_htcx/role/keyboard/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 }, - - // { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_HANDHELD_TRACKER], "/user/vive_tracker_htcx/role/handheld_object/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/left_foot/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/right_foot/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/left_shoulder/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/right_shoulder/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/left_elbow/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/right_elbow/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/left_knee/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/right_knee/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_WAIST_TRACKER], "/user/vive_tracker_htcx/role/waist/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CHEST_TRACKER], "/user/vive_tracker_htcx/role/chest/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CAMERA_TRACKER], "/user/vive_tracker_htcx/role/camera/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_KEYBOARD_TRACKER], "/user/vive_tracker_htcx/role/keyboard/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL }, - - // { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_HANDHELD_TRACKER], "/user/vive_tracker_htcx/role/handheld_object/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/left_foot/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/right_foot/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/left_shoulder/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/right_shoulder/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/left_elbow/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/right_elbow/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/left_knee/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/right_knee/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_WAIST_TRACKER], "/user/vive_tracker_htcx/role/waist/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CHEST_TRACKER], "/user/vive_tracker_htcx/role/chest/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CAMERA_TRACKER], "/user/vive_tracker_htcx/role/camera/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_KEYBOARD_TRACKER], "/user/vive_tracker_htcx/role/keyboard/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL }, - - // { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_HANDHELD_TRACKER], "/user/vive_tracker_htcx/role/handheld_object/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/left_foot/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/right_foot/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/left_shoulder/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/right_shoulder/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/left_elbow/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/right_elbow/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/left_knee/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/right_knee/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_WAIST_TRACKER], "/user/vive_tracker_htcx/role/waist/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CHEST_TRACKER], "/user/vive_tracker_htcx/role/chest/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CAMERA_TRACKER], "/user/vive_tracker_htcx/role/camera/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_KEYBOARD_TRACKER], "/user/vive_tracker_htcx/role/keyboard/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE }, - - // { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_HANDHELD_TRACKER], "/user/vive_tracker_htcx/role/handheld_object/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/left_foot/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_FOOT_TRACKER], "/user/vive_tracker_htcx/role/right_foot/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/left_shoulder/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_SHOULDER_TRACKER], "/user/vive_tracker_htcx/role/right_shoulder/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/left_elbow/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_ELBOW_TRACKER], "/user/vive_tracker_htcx/role/right_elbow/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_LEFT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/left_knee/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_RIGHT_KNEE_TRACKER], "/user/vive_tracker_htcx/role/right_knee/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_WAIST_TRACKER], "/user/vive_tracker_htcx/role/waist/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CHEST_TRACKER], "/user/vive_tracker_htcx/role/chest/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_CAMERA_TRACKER], "/user/vive_tracker_htcx/role/camera/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, - { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_HTC_KEYBOARD_TRACKER], "/user/vive_tracker_htcx/role/keyboard/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC }, -}; - -OpenXRDefs::InteractionProfile OpenXRDefs::available_interaction_profiles[] = { - { - "Simple controller", // display_name - "/interaction_profiles/khr/simple_controller", // openxr_path - simple_io_paths, // io_paths - sizeof(simple_io_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count - }, - { - "HTC Vive wand", // display_name - "/interaction_profiles/htc/vive_controller", // openxr_path - vive_io_paths, // io_paths - sizeof(vive_io_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count - }, - { - "MS Motion controller", // display_name - "/interaction_profiles/microsoft/motion_controller", // openxr_path - motion_io_paths, // io_paths - sizeof(motion_io_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count - }, - { - "HPMR controller", // display_name - "/interaction_profiles/hp/mixed_reality_controller", // openxr_path - hpmr_io_paths, // io_paths - sizeof(hpmr_io_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count - }, - { - "Touch controller", // display_name - "/interaction_profiles/oculus/touch_controller", // openxr_path - touch_io_paths, // io_paths - sizeof(touch_io_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count - }, - { - "Index controller", // display_name - "/interaction_profiles/valve/index_controller", // openxr_path - index_io_paths, // io_paths - sizeof(index_io_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count - }, - { - "Samsung Odyssey controller", // display_name - "/interaction_profiles/samsung/odyssey_controller", // openxr_path - odyssey_io_paths, // io_paths - sizeof(odyssey_io_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count - }, - { - "Vive Cosmos controller", // display_name - "/interaction_profiles/htc/vive_cosmos_controller", // openxr_path - vive_cosmos_paths, // io_paths - sizeof(vive_cosmos_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count - }, - { - "Vive Focus 3 controller", // display_name - "/interaction_profiles/htc/vive_focus3_controller", // openxr_path - vive_focus3_paths, // io_paths - sizeof(vive_focus3_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count - }, - { - "Huawei controller", // display_name - "/interaction_profiles/huawei/controller", // openxr_path - huawei_controller_paths, // io_paths - sizeof(huawei_controller_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count - }, - - { - "HTC Vive tracker", // display_name - "/interaction_profiles/htc/vive_tracker_htcx", // openxr_path - vive_tracker_controller_paths, // io_paths - sizeof(vive_tracker_controller_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count - }, -}; - -int OpenXRDefs::available_interaction_profile_count = sizeof(OpenXRDefs::available_interaction_profiles) / sizeof(OpenXRDefs::InteractionProfile); - -const OpenXRDefs::TopLevelPath *OpenXRDefs::get_top_level_path(const String p_top_level_path) { - for (int i = 0; i < OPENXR_TOP_LEVEL_PATH_MAX; i++) { - if (available_top_level_paths[i].openxr_path == p_top_level_path) { - return &OpenXRDefs::available_top_level_paths[i]; - } - } - - return nullptr; -} - -const OpenXRDefs::InteractionProfile *OpenXRDefs::get_profile(const String p_interaction_profile_path) { - for (int i = 0; i < available_interaction_profile_count; i++) { - if (available_interaction_profiles[i].openxr_path == p_interaction_profile_path) { - return &available_interaction_profiles[i]; - } - } - - return nullptr; -} - -const OpenXRDefs::IOPath *OpenXRDefs::InteractionProfile::get_io_path(const String p_io_path) const { - for (int i = 0; i < available_interaction_profiles[i].io_path_count; i++) { - if (io_paths[i].openxr_path == p_io_path) { - return &io_paths[i]; - } - } - - return nullptr; -} - -const OpenXRDefs::IOPath *OpenXRDefs::get_io_path(const String p_interaction_profile_path, const String p_io_path) { - const OpenXRDefs::InteractionProfile *profile = OpenXRDefs::get_profile(p_interaction_profile_path); - if (profile != nullptr) { - return profile->get_io_path(p_io_path); - } - - return nullptr; -} - -PackedStringArray OpenXRDefs::get_interaction_profile_paths() { - PackedStringArray arr; - - for (int i = 0; i < available_interaction_profile_count; i++) { - arr.push_back(available_interaction_profiles[i].openxr_path); - } - - return arr; -} diff --git a/modules/openxr/action_map/openxr_defs.h b/modules/openxr/action_map/openxr_defs.h deleted file mode 100644 index 446e6eb9c6..0000000000 --- a/modules/openxr/action_map/openxr_defs.h +++ /dev/null @@ -1,124 +0,0 @@ -/*************************************************************************/ -/* openxr_defs.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef OPENXR_DEFS_H -#define OPENXR_DEFS_H - -#include "openxr_action.h" - -/////////////////////////////////////////////////////////////////////////// -// Stores available interaction profiles -// -// 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 extensions that need to be enabled -// until they are 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 on action type that automatic conversions between boolean and float -// are supported but otherwise action types should match between action and -// input/output paths. - -class OpenXRDefs { -public: - enum TOP_LEVEL_PATH { - // Core OpenXR toplevel paths - OPENXR_LEFT_HAND, - OPENXR_RIGHT_HAND, - OPENXR_HEAD, - OPENXR_GAMEPAD, - OPENXR_TREADMILL, - - // HTC tracker extension toplevel paths - // OPENXR_HTC_HANDHELD_TRACKER, - OPENXR_HTC_LEFT_FOOT_TRACKER, - OPENXR_HTC_RIGHT_FOOT_TRACKER, - OPENXR_HTC_LEFT_SHOULDER_TRACKER, - OPENXR_HTC_RIGHT_SHOULDER_TRACKER, - OPENXR_HTC_LEFT_ELBOW_TRACKER, - OPENXR_HTC_RIGHT_ELBOW_TRACKER, - OPENXR_HTC_LEFT_KNEE_TRACKER, - OPENXR_HTC_RIGHT_KNEE_TRACKER, - OPENXR_HTC_WAIST_TRACKER, - OPENXR_HTC_CHEST_TRACKER, - OPENXR_HTC_CAMERA_TRACKER, - OPENXR_HTC_KEYBOARD_TRACKER, - - OPENXR_TOP_LEVEL_PATH_MAX - }; - - struct TopLevelPath { - const char *display_name; // User friendly display name (i.e. Left controller) - const char *openxr_path; // Path in OpenXR (i.e. /user/hand/left) - }; - - struct IOPath { - const char *display_name; // User friendly display name (i.e. Grip pose (left controller)) - const TopLevelPath *top_level_path; // Top level path identifying the usage of the device in relation to this input/output - const char *openxr_path; // Path in OpenXR (i.e. /user/hand/left/input/grip/pose) - const OpenXRAction::ActionType action_type; // Type of input/output - }; - - struct InteractionProfile { - const char *display_name; // User friendly display name (i.e. Simple controller) - const char *openxr_path; // Path in OpenXR (i.e. /interaction_profiles/khr/simple_controller) - const IOPath *io_paths; // Inputs and outputs for this device - const int io_path_count; // Number of inputs and outputs for this device - - const IOPath *get_io_path(const String p_io_path) const; - }; - -private: - static TopLevelPath available_top_level_paths[OPENXR_TOP_LEVEL_PATH_MAX]; - static IOPath simple_io_paths[]; - static IOPath vive_io_paths[]; - static IOPath motion_io_paths[]; - static IOPath hpmr_io_paths[]; - static IOPath touch_io_paths[]; - static IOPath index_io_paths[]; - static IOPath odyssey_io_paths[]; - static IOPath vive_cosmos_paths[]; - static IOPath vive_focus3_paths[]; - static IOPath huawei_controller_paths[]; - static IOPath vive_tracker_controller_paths[]; - static InteractionProfile available_interaction_profiles[]; - static int available_interaction_profile_count; - -public: - static const TopLevelPath *get_top_level_path(const String p_top_level_path); - static const InteractionProfile *get_profile(const String p_interaction_profile_path); - static const IOPath *get_io_path(const String p_interaction_profile_path, const String p_io_path); - - static PackedStringArray get_interaction_profile_paths(); -}; - -#endif // OPENXR_DEFS_H diff --git a/modules/openxr/action_map/openxr_interaction_profile.cpp b/modules/openxr/action_map/openxr_interaction_profile.cpp index abb714c3bb..8bb657a2db 100644 --- a/modules/openxr/action_map/openxr_interaction_profile.cpp +++ b/modules/openxr/action_map/openxr_interaction_profile.cpp @@ -58,6 +58,7 @@ Ref<OpenXRIPBinding> OpenXRIPBinding::new_binding(const Ref<OpenXRAction> p_acti void OpenXRIPBinding::set_action(const Ref<OpenXRAction> p_action) { action = p_action; + emit_changed(); } Ref<OpenXRAction> OpenXRIPBinding::get_action() const { @@ -70,6 +71,7 @@ int OpenXRIPBinding::get_path_count() const { void OpenXRIPBinding::set_paths(const PackedStringArray p_paths) { paths = p_paths; + emit_changed(); } PackedStringArray OpenXRIPBinding::get_paths() const { @@ -78,6 +80,7 @@ PackedStringArray OpenXRIPBinding::get_paths() const { void OpenXRIPBinding::parse_paths(const String p_paths) { paths = p_paths.split(",", false); + emit_changed(); } bool OpenXRIPBinding::has_path(const String p_path) const { @@ -87,12 +90,14 @@ bool OpenXRIPBinding::has_path(const String p_path) const { void OpenXRIPBinding::add_path(const String p_path) { if (!paths.has(p_path)) { paths.push_back(p_path); + emit_changed(); } } void OpenXRIPBinding::remove_path(const String p_path) { if (paths.has(p_path)) { paths.erase(p_path); + emit_changed(); } } @@ -122,6 +127,7 @@ Ref<OpenXRInteractionProfile> OpenXRInteractionProfile::new_profile(const char * void OpenXRInteractionProfile::set_interaction_profile_path(const String p_input_profile_path) { interaction_profile_path = p_input_profile_path; + emit_changed(); } String OpenXRInteractionProfile::get_interaction_profile_path() const { @@ -139,9 +145,10 @@ Ref<OpenXRIPBinding> OpenXRInteractionProfile::get_binding(int p_index) const { } void OpenXRInteractionProfile::set_bindings(Array p_bindings) { - bindings = p_bindings; - // TODO add check here that our bindings don't contain duplicate actions + + bindings = p_bindings; + emit_changed(); } Array OpenXRInteractionProfile::get_bindings() const { @@ -166,6 +173,7 @@ void OpenXRInteractionProfile::add_binding(Ref<OpenXRIPBinding> p_binding) { ERR_FAIL_COND_MSG(get_binding_for_action(p_binding->get_action()).is_valid(), "There is already a binding for this action in this interaction profile"); bindings.push_back(p_binding); + emit_changed(); } } @@ -173,6 +181,7 @@ void OpenXRInteractionProfile::remove_binding(Ref<OpenXRIPBinding> p_binding) { int idx = bindings.find(p_binding); if (idx != -1) { bindings.remove_at(idx); + emit_changed(); } } @@ -192,6 +201,17 @@ void OpenXRInteractionProfile::remove_binding_for_action(const Ref<OpenXRAction> } } +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; +} + OpenXRInteractionProfile::~OpenXRInteractionProfile() { bindings.clear(); } diff --git a/modules/openxr/action_map/openxr_interaction_profile.h b/modules/openxr/action_map/openxr_interaction_profile.h index c77fd490bb..c7db77870e 100644 --- a/modules/openxr/action_map/openxr_interaction_profile.h +++ b/modules/openxr/action_map/openxr_interaction_profile.h @@ -34,7 +34,7 @@ #include "core/io/resource.h" #include "openxr_action.h" -#include "openxr_defs.h" +#include "openxr_interaction_profile_meta_data.h" class OpenXRIPBinding : public Resource { GDCLASS(OpenXRIPBinding, Resource); @@ -94,6 +94,7 @@ public: void add_new_binding(const Ref<OpenXRAction> p_action, const char *p_paths); // Create a new binding for this profile void remove_binding_for_action(const Ref<OpenXRAction> p_action); // Remove all bindings for this action + bool has_binding_for_action(const Ref<OpenXRAction> p_action); // Returns true if we have a binding for this action ~OpenXRInteractionProfile(); }; diff --git a/modules/openxr/action_map/openxr_interaction_profile_meta_data.cpp b/modules/openxr/action_map/openxr_interaction_profile_meta_data.cpp new file mode 100644 index 0000000000..db4062b196 --- /dev/null +++ b/modules/openxr/action_map/openxr_interaction_profile_meta_data.cpp @@ -0,0 +1,713 @@ +/*************************************************************************/ +/* openxr_interaction_profile_meta_data.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "openxr_interaction_profile_meta_data.h" + +#include <openxr/openxr.h> + +OpenXRInteractionProfileMetaData *OpenXRInteractionProfileMetaData::singleton = nullptr; + +OpenXRInteractionProfileMetaData::OpenXRInteractionProfileMetaData() { + singleton = this; + + _register_core_metadata(); +} + +OpenXRInteractionProfileMetaData::~OpenXRInteractionProfileMetaData() { + singleton = nullptr; +} + +void OpenXRInteractionProfileMetaData::_bind_methods() { + 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_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 (int i = 0; i < interaction_profiles.size(); i++) { + if (interaction_profiles[i].openxr_path == p_interaction_profile) { + ERR_FAIL_COND_MSG(interaction_profiles[i].has_io_path(p_openxr_path), p_interaction_profile + " already has io path " + p_openxr_path + " registered!"); + + IOPath new_io_path = { + p_display_name, + p_toplevel_path, + p_openxr_path, + p_openxr_extension_name, + p_action_type + }; + + interaction_profiles.ptrw()[i].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 (int i = 0; i < interaction_profiles.size(); i++) { + if (interaction_profiles[i].openxr_path == p_openxr_path) { + return true; + } + } + + return false; +} + +String OpenXRInteractionProfileMetaData::get_interaction_profile_extension(const String p_openxr_path) const { + for (int i = 0; i < interaction_profiles.size(); i++) { + if (interaction_profiles[i].openxr_path == p_openxr_path) { + return interaction_profiles[i].openxr_extension_name; + } + } + + return XR_PATH_UNSUPPORTED_NAME; +} + +const OpenXRInteractionProfileMetaData::InteractionProfile *OpenXRInteractionProfileMetaData::get_profile(const String p_openxr_path) const { + for (int i = 0; i < interaction_profiles.size(); i++) { + if (interaction_profiles[i].openxr_path == p_openxr_path) { + return &interaction_profiles[i]; + } + } + + 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 (int i = 0; i < interaction_profiles.size(); i++) { + arr.push_back(interaction_profiles[i].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", ""); + + // TODO move this into OpenXRHTCViveTrackerExtension once this is supported. + // register_top_level_path("Handheld object tracker", "/user/vive_tracker_htcx/role/handheld_object", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + register_top_level_path("Left foot tracker", "/user/vive_tracker_htcx/role/left_foot", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + register_top_level_path("Right foot tracker", "/user/vive_tracker_htcx/role/right_foot", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + register_top_level_path("Left shoulder tracker", "/user/vive_tracker_htcx/role/left_shoulder", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + register_top_level_path("Right shoulder tracker", "/user/vive_tracker_htcx/role/right_shoulder", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + register_top_level_path("Left elbow tracker", "/user/vive_tracker_htcx/role/left_elbow", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + register_top_level_path("Right elbow tracker", "/user/vive_tracker_htcx/role/right_elbow", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + register_top_level_path("Left knee tracker", "/user/vive_tracker_htcx/role/left_knee", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + register_top_level_path("Right knee tracker", "/user/vive_tracker_htcx/role/right_knee", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + register_top_level_path("Waist tracker", "/user/vive_tracker_htcx/role/waist", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + register_top_level_path("Chest tracker", "/user/vive_tracker_htcx/role/chest", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + register_top_level_path("Camera tracker", "/user/vive_tracker_htcx/role/camera", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + register_top_level_path("Keyboard tracker", "/user/vive_tracker_htcx/role/keyboard", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + + // Fallback Khronos simple controller + register_interaction_profile("Simple controller", "/interaction_profiles/khr/simple_controller", ""); + register_io_path("/interaction_profiles/khr/simple_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/khr/simple_controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/khr/simple_controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/khr/simple_controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/khr/simple_controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/khr/simple_controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + + register_io_path("/interaction_profiles/khr/simple_controller", "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/khr/simple_controller", "Menu click", "/user/hand/right", "/user/hand/right/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/khr/simple_controller", "Select click", "/user/hand/left", "/user/hand/left/input/select/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/khr/simple_controller", "Select click", "/user/hand/right", "/user/hand/right/input/select/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/khr/simple_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + register_io_path("/interaction_profiles/khr/simple_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + + // Original HTC Vive wands + register_interaction_profile("HTC Vive wand", "/interaction_profiles/htc/vive_controller", ""); + register_io_path("/interaction_profiles/htc/vive_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + + register_io_path("/interaction_profiles/htc/vive_controller", "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_controller", "Menu click", "/user/hand/right", "/user/hand/right/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_controller", "System click", "/user/hand/left", "/user/hand/left/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_controller", "System click", "/user/hand/right", "/user/hand/right/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/htc/vive_controller", "Trigger", "/user/hand/left", "/user/hand/left/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/htc/vive_controller", "Trigger click", "/user/hand/left", "/user/hand/left/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_controller", "Trigger", "/user/hand/right", "/user/hand/right/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/htc/vive_controller", "Trigger click", "/user/hand/right", "/user/hand/right/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/htc/vive_controller", "Squeeze click", "/user/hand/left", "/user/hand/left/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_controller", "Squeeze click", "/user/hand/right", "/user/hand/right/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/htc/vive_controller", "Trackpad", "/user/hand/left", "/user/hand/left/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/htc/vive_controller", "Trackpad click", "/user/hand/left", "/user/hand/left/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_controller", "Trackpad touch", "/user/hand/left", "/user/hand/left/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_controller", "Trackpad", "/user/hand/right", "/user/hand/right/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/htc/vive_controller", "Trackpad click", "/user/hand/right", "/user/hand/right/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_controller", "Trackpad touch", "/user/hand/right", "/user/hand/right/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/htc/vive_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + register_io_path("/interaction_profiles/htc/vive_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + + // Microsoft motion controller (original WMR controllers) + register_interaction_profile("MS Motion controller", "/interaction_profiles/microsoft/motion_controller", ""); + register_io_path("/interaction_profiles/microsoft/motion_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/microsoft/motion_controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/microsoft/motion_controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/microsoft/motion_controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/microsoft/motion_controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/microsoft/motion_controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + + register_io_path("/interaction_profiles/microsoft/motion_controller", "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/microsoft/motion_controller", "Menu click", "/user/hand/right", "/user/hand/right/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/microsoft/motion_controller", "Trigger", "/user/hand/left", "/user/hand/left/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/microsoft/motion_controller", "Trigger click", "/user/hand/left", "/user/hand/left/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/microsoft/motion_controller", "Trigger", "/user/hand/right", "/user/hand/right/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/microsoft/motion_controller", "Trigger click", "/user/hand/right", "/user/hand/right/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/microsoft/motion_controller", "Squeeze click", "/user/hand/left", "/user/hand/left/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/microsoft/motion_controller", "Squeeze click", "/user/hand/right", "/user/hand/right/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/microsoft/motion_controller", "Thumbstick", "/user/hand/left", "/user/hand/left/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/microsoft/motion_controller", "Thumbstick click", "/user/hand/left", "/user/hand/left/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/microsoft/motion_controller", "Thumbstick", "/user/hand/right", "/user/hand/right/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/microsoft/motion_controller", "Thumbstick click", "/user/hand/right", "/user/hand/right/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/microsoft/motion_controller", "Trackpad", "/user/hand/left", "/user/hand/left/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/microsoft/motion_controller", "Trackpad click", "/user/hand/left", "/user/hand/left/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/microsoft/motion_controller", "Trackpad touch", "/user/hand/left", "/user/hand/left/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/microsoft/motion_controller", "Trackpad", "/user/hand/right", "/user/hand/right/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/microsoft/motion_controller", "Trackpad click", "/user/hand/right", "/user/hand/right/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/microsoft/motion_controller", "Trackpad touch", "/user/hand/right", "/user/hand/right/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/microsoft/motion_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + register_io_path("/interaction_profiles/microsoft/motion_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + + // Meta touch controller (original touch controllers, Quest 1 and Quest 2 controllers) + register_interaction_profile("Touch controller", "/interaction_profiles/oculus/touch_controller", ""); + register_io_path("/interaction_profiles/oculus/touch_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/oculus/touch_controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/oculus/touch_controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/oculus/touch_controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/oculus/touch_controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/oculus/touch_controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + + register_io_path("/interaction_profiles/oculus/touch_controller", "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/oculus/touch_controller", "System click", "/user/hand/right", "/user/hand/right/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/oculus/touch_controller", "X click", "/user/hand/left", "/user/hand/left/input/x/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/oculus/touch_controller", "X touch", "/user/hand/left", "/user/hand/left/input/x/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/oculus/touch_controller", "Y click", "/user/hand/left", "/user/hand/left/input/y/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/oculus/touch_controller", "Y touch", "/user/hand/left", "/user/hand/left/input/y/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/oculus/touch_controller", "A click", "/user/hand/right", "/user/hand/right/input/a/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/oculus/touch_controller", "A touch", "/user/hand/right", "/user/hand/right/input/a/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/oculus/touch_controller", "B click", "/user/hand/right", "/user/hand/right/input/b/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/oculus/touch_controller", "B touch", "/user/hand/right", "/user/hand/right/input/b/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/oculus/touch_controller", "Trigger", "/user/hand/left", "/user/hand/left/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/oculus/touch_controller", "Trigger touch", "/user/hand/left", "/user/hand/left/input/trigger/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/oculus/touch_controller", "Trigger", "/user/hand/right", "/user/hand/right/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/oculus/touch_controller", "Trigger touch", "/user/hand/right", "/user/hand/right/input/trigger/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/oculus/touch_controller", "Squeeze", "/user/hand/left", "/user/hand/left/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/oculus/touch_controller", "Squeeze", "/user/hand/right", "/user/hand/right/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + + register_io_path("/interaction_profiles/oculus/touch_controller", "Thumbstick", "/user/hand/left", "/user/hand/left/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/oculus/touch_controller", "Thumbstick click", "/user/hand/left", "/user/hand/left/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/oculus/touch_controller", "Thumbstick touch", "/user/hand/left", "/user/hand/left/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/oculus/touch_controller", "Thumbstick", "/user/hand/right", "/user/hand/right/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/oculus/touch_controller", "Thumbstick click", "/user/hand/right", "/user/hand/right/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/oculus/touch_controller", "Thumbstick touch", "/user/hand/right", "/user/hand/right/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/oculus/touch_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + register_io_path("/interaction_profiles/oculus/touch_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + + // Valve Index controller + register_interaction_profile("Index controller", "/interaction_profiles/valve/index_controller", ""); + register_io_path("/interaction_profiles/valve/index_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/valve/index_controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/valve/index_controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/valve/index_controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/valve/index_controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/valve/index_controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + + register_io_path("/interaction_profiles/valve/index_controller", "System click", "/user/hand/left", "/user/hand/left/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/valve/index_controller", "System click", "/user/hand/right", "/user/hand/right/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/valve/index_controller", "A click", "/user/hand/left", "/user/hand/left/input/a/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/valve/index_controller", "A touch", "/user/hand/left", "/user/hand/left/input/a/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/valve/index_controller", "A click", "/user/hand/right", "/user/hand/right/input/a/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/valve/index_controller", "A touch", "/user/hand/right", "/user/hand/right/input/a/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/valve/index_controller", "B click", "/user/hand/left", "/user/hand/left/input/b/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/valve/index_controller", "B touch", "/user/hand/left", "/user/hand/left/input/b/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/valve/index_controller", "B click", "/user/hand/right", "/user/hand/right/input/b/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/valve/index_controller", "B touch", "/user/hand/right", "/user/hand/right/input/b/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/valve/index_controller", "Trigger", "/user/hand/left", "/user/hand/left/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/valve/index_controller", "Trigger click", "/user/hand/left", "/user/hand/left/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/valve/index_controller", "Trigger touch", "/user/hand/left", "/user/hand/left/input/trigger/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/valve/index_controller", "Trigger", "/user/hand/right", "/user/hand/right/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/valve/index_controller", "Trigger click", "/user/hand/right", "/user/hand/right/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/valve/index_controller", "Trigger touch", "/user/hand/right", "/user/hand/right/input/trigger/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/valve/index_controller", "Squeeze", "/user/hand/left", "/user/hand/left/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/valve/index_controller", "Squeeze", "/user/hand/right", "/user/hand/right/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + + register_io_path("/interaction_profiles/valve/index_controller", "Thumbstick", "/user/hand/left", "/user/hand/left/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/valve/index_controller", "Thumbstick click", "/user/hand/left", "/user/hand/left/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/valve/index_controller", "Thumbstick touch", "/user/hand/left", "/user/hand/left/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/valve/index_controller", "Thumbstick", "/user/hand/right", "/user/hand/right/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/valve/index_controller", "Thumbstick click", "/user/hand/right", "/user/hand/right/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/valve/index_controller", "Thumbstick touch", "/user/hand/right", "/user/hand/right/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/valve/index_controller", "Trackpad", "/user/hand/left", "/user/hand/left/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/valve/index_controller", "Trackpad force", "/user/hand/left", "/user/hand/left/input/trackpad/force", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/valve/index_controller", "Trackpad touch", "/user/hand/left", "/user/hand/left/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/valve/index_controller", "Trackpad", "/user/hand/right", "/user/hand/right/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/valve/index_controller", "Trackpad force", "/user/hand/right", "/user/hand/right/input/trackpad/force", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/valve/index_controller", "Trackpad touch", "/user/hand/right", "/user/hand/right/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/valve/index_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + register_io_path("/interaction_profiles/valve/index_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + + // HP MR controller (newer G2 controllers) + // TODO move this into an extension once this is supported. + register_interaction_profile("HPMR controller", "/interaction_profiles/hp/mixed_reality_controller", XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME); + register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + + register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Menu click", "/user/hand/right", "/user/hand/right/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/hp/mixed_reality_controller", "X click", "/user/hand/left", "/user/hand/left/input/x/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Y click", "/user/hand/left", "/user/hand/left/input/y/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/hp/mixed_reality_controller", "A click", "/user/hand/right", "/user/hand/right/input/a/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/hp/mixed_reality_controller", "B click", "/user/hand/right", "/user/hand/right/input/b/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Trigger", "/user/hand/left", "/user/hand/left/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Trigger click", "/user/hand/left", "/user/hand/left/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Trigger", "/user/hand/right", "/user/hand/right/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Trigger click", "/user/hand/right", "/user/hand/right/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Squeeze", "/user/hand/left", "/user/hand/left/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Squeeze", "/user/hand/right", "/user/hand/right/input/squeeze/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + + register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Thumbstick", "/user/hand/left", "/user/hand/left/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Thumbstick click", "/user/hand/left", "/user/hand/left/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Thumbstick", "/user/hand/right", "/user/hand/right/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Thumbstick click", "/user/hand/right", "/user/hand/right/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + register_io_path("/interaction_profiles/hp/mixed_reality_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + + // Samsung Odyssey controller + // TODO move this into an extension once this is supported. + register_interaction_profile("Samsung Odyssey controller", "/interaction_profiles/samsung/odyssey_controller", XR_EXT_SAMSUNG_ODYSSEY_CONTROLLER_EXTENSION_NAME); + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Menu click", "/user/hand/right", "/user/hand/right/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Trigger", "/user/hand/left", "/user/hand/left/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Trigger click", "/user/hand/left", "/user/hand/left/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Trigger", "/user/hand/right", "/user/hand/right/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Trigger click", "/user/hand/right", "/user/hand/right/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Squeeze click", "/user/hand/left", "/user/hand/left/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Squeeze click", "/user/hand/right", "/user/hand/right/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Thumbstick", "/user/hand/left", "/user/hand/left/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Thumbstick click", "/user/hand/left", "/user/hand/left/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Thumbstick", "/user/hand/right", "/user/hand/right/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Thumbstick click", "/user/hand/right", "/user/hand/right/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Trackpad", "/user/hand/left", "/user/hand/left/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Trackpad click", "/user/hand/left", "/user/hand/left/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Trackpad touch", "/user/hand/left", "/user/hand/left/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Trackpad", "/user/hand/right", "/user/hand/right/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Trackpad click", "/user/hand/right", "/user/hand/right/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Trackpad touch", "/user/hand/right", "/user/hand/right/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + register_io_path("/interaction_profiles/samsung/odyssey_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + + // HTC Vive Cosmos controller + // TODO move this into an extension once this is supported. + register_interaction_profile("Vive Cosmos controller", "/interaction_profiles/htc/vive_cosmos_controller", XR_HTC_VIVE_COSMOS_CONTROLLER_INTERACTION_EXTENSION_NAME); + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "System click", "/user/hand/right", "/user/hand/right/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "X click", "/user/hand/left", "/user/hand/left/input/x/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Y click", "/user/hand/left", "/user/hand/left/input/y/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "A click", "/user/hand/right", "/user/hand/right/input/a/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "B click", "/user/hand/right", "/user/hand/right/input/b/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Shoulder click", "/user/hand/left", "/user/hand/left/input/shoulder/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Shoulder click", "/user/hand/right", "/user/hand/right/input/shoulder/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Trigger", "/user/hand/left", "/user/hand/left/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Trigger click", "/user/hand/left", "/user/hand/left/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Trigger", "/user/hand/right", "/user/hand/right/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Trigger click", "/user/hand/right", "/user/hand/right/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Squeeze click", "/user/hand/left", "/user/hand/left/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Squeeze click", "/user/hand/right", "/user/hand/right/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Thumbstick", "/user/hand/left", "/user/hand/left/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Thumbstick click", "/user/hand/left", "/user/hand/left/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Thumbstick touch", "/user/hand/left", "/user/hand/left/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Thumbstick", "/user/hand/right", "/user/hand/right/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Thumbstick click", "/user/hand/right", "/user/hand/right/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Thumbstick touch", "/user/hand/right", "/user/hand/right/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + register_io_path("/interaction_profiles/htc/vive_cosmos_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + + // HTC Vive Focus 3 controller + // TODO move this into an extension once this is supported. + register_interaction_profile("Vive Focus 3 controller", "/interaction_profiles/htc/vive_focus3_controller", XR_HTC_VIVE_FOCUS3_CONTROLLER_INTERACTION_EXTENSION_NAME); + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", XR_EXT_PALM_POSE_EXTENSION_NAME, OpenXRAction::OPENXR_ACTION_POSE); + + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Menu click", "/user/hand/left", "/user/hand/left/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "System click", "/user/hand/right", "/user/hand/right/input/system/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "X click", "/user/hand/left", "/user/hand/left/input/x/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Y click", "/user/hand/left", "/user/hand/left/input/y/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "A click", "/user/hand/right", "/user/hand/right/input/a/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "B click", "/user/hand/right", "/user/hand/right/input/b/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Trigger", "/user/hand/left", "/user/hand/left/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Trigger click", "/user/hand/left", "/user/hand/left/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Trigger touch", "/user/hand/left", "/user/hand/left/input/trigger/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Trigger", "/user/hand/right", "/user/hand/right/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Trigger click", "/user/hand/right", "/user/hand/right/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Trigger touch", "/user/hand/right", "/user/hand/right/input/trigger/touch ", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Squeeze click", "/user/hand/left", "/user/hand/left/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Squeeze touch", "/user/hand/left", "/user/hand/left/input/squeeze/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Squeeze click", "/user/hand/right", "/user/hand/right/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Squeeze touch", "/user/hand/right", "/user/hand/right/input/squeeze/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Thumbstick", "/user/hand/left", "/user/hand/left/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Thumbstick click", "/user/hand/left", "/user/hand/left/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Thumbstick touch", "/user/hand/left", "/user/hand/left/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Thumbstick", "/user/hand/right", "/user/hand/right/input/thumbstick", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Thumbstick click", "/user/hand/right", "/user/hand/right/input/thumbstick/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Thumbstick touch", "/user/hand/right", "/user/hand/right/input/thumbstick/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Thumbrest touch", "/user/hand/right", "/user/hand/right/input/thumbrest/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + register_io_path("/interaction_profiles/htc/vive_focus3_controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + + // Huawei controller + // TODO move this into an extension once this is supported. + register_interaction_profile("Huawei controller", "/interaction_profiles/huawei/controller", XR_HUAWEI_CONTROLLER_INTERACTION_EXTENSION_NAME); + register_io_path("/interaction_profiles/huawei/controller", "Grip pose", "/user/hand/left", "/user/hand/left/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/huawei/controller", "Grip pose", "/user/hand/right", "/user/hand/right/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/huawei/controller", "Aim pose", "/user/hand/left", "/user/hand/left/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/huawei/controller", "Aim pose", "/user/hand/right", "/user/hand/right/input/aim/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/huawei/controller", "Palm pose", "/user/hand/left", "/user/hand/left/input/palm_ext/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/huawei/controller", "Palm pose", "/user/hand/right", "/user/hand/right/input/palm_ext/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + + register_io_path("/interaction_profiles/huawei/controller", "Home click", "/user/hand/left", "/user/hand/left/input/home/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/huawei/controller", "Home click", "/user/hand/right", "/user/hand/right/input/home/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/huawei/controller", "Back click", "/user/hand/left", "/user/hand/left/input/back/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/huawei/controller", "Back click", "/user/hand/right", "/user/hand/right/input/back/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/huawei/controller", "Volume up click", "/user/hand/left", "/user/hand/left/input/volume_up/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/huawei/controller", "Volume up click", "/user/hand/right", "/user/hand/right/input/volume_up/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/huawei/controller", "Volume down click", "/user/hand/left", "/user/hand/left/input/volume_down/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/huawei/controller", "Volume down click", "/user/hand/right", "/user/hand/right/input/volume_down/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/huawei/controller", "Trigger", "/user/hand/left", "/user/hand/left/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/huawei/controller", "Trigger click", "/user/hand/left", "/user/hand/left/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/huawei/controller", "Trigger", "/user/hand/right", "/user/hand/right/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/huawei/controller", "Trigger click", "/user/hand/right", "/user/hand/right/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/huawei/controller", "Trackpad", "/user/hand/left", "/user/hand/left/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/huawei/controller", "Trackpad click", "/user/hand/left", "/user/hand/left/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/huawei/controller", "Trackpad touch", "/user/hand/left", "/user/hand/left/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/huawei/controller", "Trackpad", "/user/hand/right", "/user/hand/right/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/huawei/controller", "Trackpad click", "/user/hand/right", "/user/hand/right/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/huawei/controller", "Trackpad touch", "/user/hand/right", "/user/hand/right/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + + register_io_path("/interaction_profiles/huawei/controller", "Haptic output", "/user/hand/left", "/user/hand/left/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + register_io_path("/interaction_profiles/huawei/controller", "Haptic output", "/user/hand/right", "/user/hand/right/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + + // HTC Vive tracker + // Interestingly enough trackers don't have buttons or inputs, yet these are defined in the spec. + // I think this can be supported through attachments on the trackers. + // TODO move this into an extension once this is supported. + register_interaction_profile("HTC Vive tracker", "/interaction_profiles/htc/vive_tracker_htcx", XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Menu click", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/left_foot/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Menu click", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/right_foot/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Menu click", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/left_shoulder/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Menu click", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/right_shoulder/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Menu click", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/left_elbow/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Menu click", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/right_elbow/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Menu click", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/left_knee/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Menu click", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/right_knee/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Menu click", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/waist/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Menu click", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/chest/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Menu click", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/camera/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Menu click", "/user/vive_tracker_htcx/role/keyboard", "/user/vive_tracker_htcx/role/keyboard/input/menu/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + // register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/handheld_object", "/user/vive_tracker_htcx/role/handheld_object/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/left_foot/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/right_foot/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/left_shoulder/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/right_shoulder/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/left_elbow/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/right_elbow/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/left_knee/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/right_knee/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/waist/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/chest/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/camera/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger", "/user/vive_tracker_htcx/role/keyboard", "/user/vive_tracker_htcx/role/keyboard/input/trigger/value", "", OpenXRAction::OPENXR_ACTION_FLOAT); + + // register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/handheld_object", "/user/vive_tracker_htcx/role/handheld_object/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/left_foot/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/right_foot/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/left_shoulder/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/right_shoulder/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/left_elbow/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/right_elbow/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/left_knee/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/right_knee/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/waist/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/chest/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/camera/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trigger click", "/user/vive_tracker_htcx/role/keyboard", "/user/vive_tracker_htcx/role/keyboard/input/trigger/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + // register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/handheld_object", "/user/vive_tracker_htcx/role/handheld_object/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/left_foot/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/right_foot/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/left_shoulder/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/right_shoulder/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/left_elbow/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/right_elbow/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/left_knee/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/right_knee/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/waist/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/chest/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/camera/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Squeeze click", "/user/vive_tracker_htcx/role/keyboard", "/user/vive_tracker_htcx/role/keyboard/input/squeeze/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + // register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/handheld_object", "/user/vive_tracker_htcx/role/handheld_object/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/left_foot/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/right_foot/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/left_shoulder/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/right_shoulder/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/left_elbow/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/right_elbow/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/left_knee/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/right_knee/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/waist/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/chest/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/camera/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad", "/user/vive_tracker_htcx/role/keyboard", "/user/vive_tracker_htcx/role/keyboard/input/trackpad", "", OpenXRAction::OPENXR_ACTION_VECTOR2); + + // register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/handheld_object", "/user/vive_tracker_htcx/role/handheld_object/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/left_foot/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/right_foot/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/left_shoulder/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/right_shoulder/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/left_elbow/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/right_elbow/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/left_knee/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/right_knee/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/waist/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/chest/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/camera/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad click", "/user/vive_tracker_htcx/role/keyboard", "/user/vive_tracker_htcx/role/keyboard/input/trackpad/click", "", OpenXRAction::OPENXR_ACTION_BOOL); + + // register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/handheld_object", "/user/vive_tracker_htcx/role/handheld_object/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/left_foot/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/right_foot/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/left_shoulder/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/right_shoulder/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/left_elbow/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/right_elbow/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/left_knee/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/right_knee/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/waist/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/chest/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/camera/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Trackpad touch", "/user/vive_tracker_htcx/role/keyboard", "/user/vive_tracker_htcx/role/keyboard/input/trackpad/touch", "", OpenXRAction::OPENXR_ACTION_BOOL); + + // register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/handheld_object", "/user/vive_tracker_htcx/role/handheld_object/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/left_foot/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/right_foot/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/left_shoulder/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/right_shoulder/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/left_elbow/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/right_elbow/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/left_knee/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/right_knee/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/waist/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/chest/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/camera/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Grip pose", "/user/vive_tracker_htcx/role/keyboard", "/user/vive_tracker_htcx/role/keyboard/input/grip/pose", "", OpenXRAction::OPENXR_ACTION_POSE); + + // register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/handheld_object", "/user/vive_tracker_htcx/role/handheld_object/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/left_foot", "/user/vive_tracker_htcx/role/left_foot/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/right_foot", "/user/vive_tracker_htcx/role/right_foot/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/left_shoulder", "/user/vive_tracker_htcx/role/left_shoulder/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/right_shoulder", "/user/vive_tracker_htcx/role/right_shoulder/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/left_elbow", "/user/vive_tracker_htcx/role/left_elbow/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/right_elbow", "/user/vive_tracker_htcx/role/right_elbow/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/left_knee", "/user/vive_tracker_htcx/role/left_knee/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/right_knee", "/user/vive_tracker_htcx/role/right_knee/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/waist", "/user/vive_tracker_htcx/role/waist/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/chest", "/user/vive_tracker_htcx/role/chest/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/camera", "/user/vive_tracker_htcx/role/camera/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); + register_io_path("/interaction_profiles/htc/vive_tracker_htcx", "Haptic output", "/user/vive_tracker_htcx/role/keyboard", "/user/vive_tracker_htcx/role/keyboard/output/haptic", "", OpenXRAction::OPENXR_ACTION_HAPTIC); +} diff --git a/modules/openxr/action_map/openxr_interaction_profile_meta_data.h b/modules/openxr/action_map/openxr_interaction_profile_meta_data.h new file mode 100644 index 0000000000..0ae6454be7 --- /dev/null +++ b/modules/openxr/action_map/openxr_interaction_profile_meta_data.h @@ -0,0 +1,118 @@ +/*************************************************************************/ +/* openxr_interaction_profile_meta_data.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef OPENXR_INTERACTION_PROFILE_META_DATA_H +#define OPENXR_INTERACTION_PROFILE_META_DATA_H + +#include "openxr_action.h" + +/////////////////////////////////////////////////////////////////////////// +// Stores available interaction profile meta data +// +// 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 "core/object/object.h" + +#define XR_PATH_UNSUPPORTED_NAME "unsupported" + +class OpenXRInteractionProfileMetaData : public 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; + + 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_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; +}; + +#endif // OPENXR_INTERACTION_PROFILE_META_DATA_H diff --git a/modules/openxr/editor/openxr_action_editor.cpp b/modules/openxr/editor/openxr_action_editor.cpp index 52216fa483..a6c99741d7 100644 --- a/modules/openxr/editor/openxr_action_editor.cpp +++ b/modules/openxr/editor/openxr_action_editor.cpp @@ -29,8 +29,13 @@ /*************************************************************************/ #include "openxr_action_editor.h" +#include "editor/editor_node.h" void OpenXRActionEditor::_bind_methods() { + ClassDB::bind_method(D_METHOD("_do_set_name", "name"), &OpenXRActionEditor::_do_set_name); + ClassDB::bind_method(D_METHOD("_do_set_localized_name", "name"), &OpenXRActionEditor::_do_set_localized_name); + ClassDB::bind_method(D_METHOD("_do_set_action_type", "type"), &OpenXRActionEditor::_do_set_action_type); + ADD_SIGNAL(MethodInfo("remove", PropertyInfo(Variant::OBJECT, "action_editor"))); } @@ -48,24 +53,71 @@ void OpenXRActionEditor::_notification(int p_what) { } void OpenXRActionEditor::_on_action_name_changed(const String p_new_text) { - // TODO validate if entry is allowed - - // If our localized name matches our action name, set this too - if (action->get_name() == action->get_localized_name()) { - action->set_localized_name(p_new_text); - action_localized_name->set_text(p_new_text); + if (action->get_name() != p_new_text) { + undo_redo->create_action(TTR("Rename Action")); + undo_redo->add_do_method(this, "_do_set_name", p_new_text); + undo_redo->add_undo_method(this, "_do_set_name", action->get_name()); + undo_redo->commit_action(false); + + // If our localized name matches our action name, set this too + if (action->get_name() == action->get_localized_name()) { + undo_redo->create_action(TTR("Rename Actions Localized name")); + undo_redo->add_do_method(this, "_do_set_localized_name", p_new_text); + undo_redo->add_undo_method(this, "_do_set_localized_name", action->get_localized_name()); + undo_redo->commit_action(false); + + action->set_localized_name(p_new_text); + action_localized_name->set_text(p_new_text); + } + action->set_name(p_new_text); + action->set_edited(true); } +} + +void OpenXRActionEditor::_do_set_name(const String p_new_text) { action->set_name(p_new_text); + action->set_edited(true); + action_name->set_text(p_new_text); } void OpenXRActionEditor::_on_action_localized_name_changed(const String p_new_text) { + if (action->get_localized_name() != p_new_text) { + undo_redo->create_action(TTR("Rename Actions Localized name")); + undo_redo->add_do_method(this, "_do_set_localized_name", p_new_text); + undo_redo->add_undo_method(this, "_do_set_localized_name", action->get_localized_name()); + undo_redo->commit_action(false); + + action->set_localized_name(p_new_text); + action->set_edited(true); + } +} + +void OpenXRActionEditor::_do_set_localized_name(const String p_new_text) { action->set_localized_name(p_new_text); + action->set_edited(true); + action_localized_name->set_text(p_new_text); } void OpenXRActionEditor::_on_item_selected(int p_idx) { ERR_FAIL_INDEX(p_idx, OpenXRAction::OPENXR_ACTION_MAX); - action->set_action_type(OpenXRAction::ActionType(p_idx)); + OpenXRAction::ActionType action_type = OpenXRAction::ActionType(p_idx); + + if (action->get_action_type() != action_type) { + undo_redo->create_action(TTR("Change Action Type")); + undo_redo->add_do_method(this, "_do_set_action_type", action_type); + undo_redo->add_undo_method(this, "_do_set_action_type", action->get_action_type()); + undo_redo->commit_action(false); + + action->set_action_type(action_type); + action->set_edited(true); + } +} + +void OpenXRActionEditor::_do_set_action_type(OpenXRAction::ActionType p_action_type) { + action->set_action_type(p_action_type); + action->set_edited(true); + action_type_button->select(int(action->get_action_type())); } void OpenXRActionEditor::_on_remove_action() { @@ -73,6 +125,7 @@ void OpenXRActionEditor::_on_remove_action() { } OpenXRActionEditor::OpenXRActionEditor(Ref<OpenXRAction> p_action) { + undo_redo = EditorNode::get_undo_redo(); action = p_action; set_h_size_flags(Control::SIZE_EXPAND_FILL); @@ -90,16 +143,16 @@ OpenXRActionEditor::OpenXRActionEditor(Ref<OpenXRAction> p_action) { action_localized_name->connect("text_changed", callable_mp(this, &OpenXRActionEditor::_on_action_localized_name_changed)); add_child(action_localized_name); - action_type = memnew(OptionButton); - action_type->add_item("Bool", OpenXRAction::OPENXR_ACTION_BOOL); - action_type->add_item("Float", OpenXRAction::OPENXR_ACTION_FLOAT); - action_type->add_item("Vector2", OpenXRAction::OPENXR_ACTION_VECTOR2); - action_type->add_item("Pose", OpenXRAction::OPENXR_ACTION_POSE); - action_type->add_item("Haptic", OpenXRAction::OPENXR_ACTION_HAPTIC); - action_type->select(int(action->get_action_type())); - action_type->set_custom_minimum_size(Size2(100.0, 0.0)); - action_type->connect("item_selected", callable_mp(this, &OpenXRActionEditor::_on_item_selected)); - add_child(action_type); + action_type_button = memnew(OptionButton); + action_type_button->add_item("Bool", OpenXRAction::OPENXR_ACTION_BOOL); + action_type_button->add_item("Float", OpenXRAction::OPENXR_ACTION_FLOAT); + action_type_button->add_item("Vector2", OpenXRAction::OPENXR_ACTION_VECTOR2); + action_type_button->add_item("Pose", OpenXRAction::OPENXR_ACTION_POSE); + action_type_button->add_item("Haptic", OpenXRAction::OPENXR_ACTION_HAPTIC); + action_type_button->select(int(action->get_action_type())); + action_type_button->set_custom_minimum_size(Size2(100.0, 0.0)); + action_type_button->connect("item_selected", callable_mp(this, &OpenXRActionEditor::_on_item_selected)); + add_child(action_type_button); // maybe add dropdown to edit our toplevel paths, or do we deduce them from our suggested bindings? diff --git a/modules/openxr/editor/openxr_action_editor.h b/modules/openxr/editor/openxr_action_editor.h index 6cf098cf08..66b7eebaeb 100644 --- a/modules/openxr/editor/openxr_action_editor.h +++ b/modules/openxr/editor/openxr_action_editor.h @@ -32,6 +32,7 @@ #define OPENXR_ACTION_EDITOR_H #include "../action_map/openxr_action.h" +#include "editor/editor_undo_redo_manager.h" #include "scene/gui/box_container.h" #include "scene/gui/button.h" #include "scene/gui/line_edit.h" @@ -42,11 +43,12 @@ class OpenXRActionEditor : public HBoxContainer { GDCLASS(OpenXRActionEditor, HBoxContainer); private: + Ref<EditorUndoRedoManager> undo_redo; Ref<OpenXRAction> action; LineEdit *action_name = nullptr; LineEdit *action_localized_name = nullptr; - OptionButton *action_type = nullptr; + OptionButton *action_type_button = nullptr; Button *rem_action = nullptr; void _theme_changed(); @@ -59,6 +61,11 @@ protected: static void _bind_methods(); void _notification(int p_what); + // used for undo/redo + void _do_set_name(const String p_new_text); + void _do_set_localized_name(const String p_new_text); + void _do_set_action_type(OpenXRAction::ActionType p_action_type); + public: Ref<OpenXRAction> get_action() { return action; }; OpenXRActionEditor(Ref<OpenXRAction> p_action); diff --git a/modules/openxr/editor/openxr_action_map_editor.cpp b/modules/openxr/editor/openxr_action_map_editor.cpp index b5223e5903..a2c33a91c4 100644 --- a/modules/openxr/editor/openxr_action_map_editor.cpp +++ b/modules/openxr/editor/openxr_action_map_editor.cpp @@ -40,14 +40,16 @@ void OpenXRActionMapEditor::_bind_methods() { ClassDB::bind_method("_add_action_set_editor", &OpenXRActionMapEditor::_add_action_set_editor); - ClassDB::bind_method("_update_action_sets", &OpenXRActionMapEditor::_update_action_sets); - ClassDB::bind_method("_add_interaction_profile_editor", &OpenXRActionMapEditor::_add_interaction_profile_editor); - ClassDB::bind_method("_update_interaction_profiles", &OpenXRActionMapEditor::_update_interaction_profiles); ClassDB::bind_method(D_METHOD("_add_action_set", "name"), &OpenXRActionMapEditor::_add_action_set); ClassDB::bind_method(D_METHOD("_set_focus_on_action_set", "action_set"), &OpenXRActionMapEditor::_set_focus_on_action_set); ClassDB::bind_method(D_METHOD("_remove_action_set", "name"), &OpenXRActionMapEditor::_remove_action_set); + + ClassDB::bind_method(D_METHOD("_do_add_action_set_editor", "action_set_editor"), &OpenXRActionMapEditor::_do_add_action_set_editor); + ClassDB::bind_method(D_METHOD("_do_remove_action_set_editor", "action_set_editor"), &OpenXRActionMapEditor::_do_remove_action_set_editor); + ClassDB::bind_method(D_METHOD("_do_add_interaction_profile_editor", "interaction_profile_editor"), &OpenXRActionMapEditor::_do_add_interaction_profile_editor); + ClassDB::bind_method(D_METHOD("_do_remove_interaction_profile_editor", "interaction_profile_editor"), &OpenXRActionMapEditor::_do_remove_interaction_profile_editor); } void OpenXRActionMapEditor::_notification(int p_what) { @@ -63,8 +65,8 @@ void OpenXRActionMapEditor::_notification(int p_what) { } break; case NOTIFICATION_READY: { - _update_action_sets(); - _update_interaction_profiles(); + _create_action_sets(); + _create_interaction_profiles(); } break; } } @@ -75,18 +77,13 @@ OpenXRActionSetEditor *OpenXRActionMapEditor::_add_action_set_editor(Ref<OpenXRA OpenXRActionSetEditor *action_set_editor = memnew(OpenXRActionSetEditor(action_map, p_action_set)); action_set_editor->connect("remove", callable_mp(this, &OpenXRActionMapEditor::_on_remove_action_set)); action_set_editor->connect("action_removed", callable_mp(this, &OpenXRActionMapEditor::_on_action_removed)); + actionsets_vb->add_child(action_set_editor); return action_set_editor; } -void OpenXRActionMapEditor::_update_action_sets() { - // out with the old... - while (actionsets_vb->get_child_count() > 0) { - memdelete(actionsets_vb->get_child(0)); - } - - // in with the new... +void OpenXRActionMapEditor::_create_action_sets() { if (action_map.is_valid()) { Array action_sets = action_map->get_action_sets(); for (int i = 0; i < action_sets.size(); i++) { @@ -116,22 +113,10 @@ OpenXRInteractionProfileEditorBase *OpenXRActionMapEditor::_add_interaction_prof new_profile_editor->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree"))); tabs->set_tab_button_icon(tabs->get_tab_count() - 1, get_theme_icon(SNAME("close"), SNAME("TabBar"))); - interaction_profiles.push_back(new_profile_editor); - return new_profile_editor; } -void OpenXRActionMapEditor::_update_interaction_profiles() { - // out with the old... - while (interaction_profiles.size() > 0) { - Node *interaction_profile = interaction_profiles[0]; - interaction_profiles.remove_at(0); - - tabs->remove_child(interaction_profile); - interaction_profile->queue_free(); - } - - // in with the new... +void OpenXRActionMapEditor::_create_interaction_profiles() { if (action_map.is_valid()) { Array new_interaction_profiles = action_map->get_interaction_profiles(); for (int i = 0; i < new_interaction_profiles.size(); i++) { @@ -150,9 +135,17 @@ OpenXRActionSetEditor *OpenXRActionMapEditor::_add_action_set(String p_name) { new_action_set->set_name(p_name); new_action_set->set_localized_name(p_name); action_map->add_action_set(new_action_set); + action_map->set_edited(true); // update our editor right away - return _add_action_set_editor(new_action_set); + OpenXRActionSetEditor *action_set_editor = _add_action_set_editor(new_action_set); + + undo_redo->create_action(TTR("Add action set")); + undo_redo->add_do_method(this, "_do_add_action_set_editor", action_set_editor); + undo_redo->add_undo_method(this, "_do_remove_action_set_editor", action_set_editor); + undo_redo->commit_action(false); + + return action_set_editor; } void OpenXRActionMapEditor::_remove_action_set(String p_name) { @@ -160,13 +153,12 @@ void OpenXRActionMapEditor::_remove_action_set(String p_name) { Ref<OpenXRActionSet> action_set = action_map->find_action_set(p_name); ERR_FAIL_COND(action_set.is_null()); - if (action_set->get_action_count() > 0) { - // we should remove these and add to our redo/undo step before calling _remove_action_set - WARN_PRINT("Action set still has associated actions before being removed!"); + for (int i = 0; i < actionsets_vb->get_child_count(); i++) { + OpenXRActionSetEditor *action_set_editor = Object::cast_to<OpenXRActionSetEditor>(actionsets_vb->get_child(i)); + if (action_set_editor && action_set_editor->get_action_set() == action_set) { + _on_remove_action_set(action_set_editor); + } } - - // now we remove it - action_map->remove_action_set(action_set); } void OpenXRActionMapEditor::_on_add_action_set() { @@ -203,14 +195,23 @@ void OpenXRActionMapEditor::_on_remove_action_set(Object *p_action_set_editor) { Ref<OpenXRActionSet> action_set = action_set_editor->get_action_set(); ERR_FAIL_COND(action_set.is_null()); - action_map->remove_action_set(action_set); - actionsets_vb->remove_child(action_set_editor); - action_set_editor->queue_free(); + action_set_editor->remove_all_actions(); + + undo_redo->create_action(TTR("Remove action set")); + undo_redo->add_do_method(this, "_do_remove_action_set_editor", action_set_editor); + undo_redo->add_undo_method(this, "_do_add_action_set_editor", action_set_editor); + undo_redo->commit_action(true); + + action_map->set_edited(true); } void OpenXRActionMapEditor::_on_action_removed() { - // make sure our interaction profiles are updated - _update_interaction_profiles(); + for (int i = 0; i < tabs->get_tab_count(); i++) { + // First tab won't be an interaction profile editor, but being thorough.. + OpenXRInteractionProfileEditorBase *interaction_profile_editor = static_cast<OpenXRInteractionProfileEditorBase *>(tabs->get_tab_control(i)); + if (interaction_profile_editor) { + } + } } void OpenXRActionMapEditor::_on_add_interaction_profile() { @@ -232,20 +233,35 @@ void OpenXRActionMapEditor::_on_interaction_profile_selected(const String p_path new_profile.instantiate(); new_profile->set_interaction_profile_path(p_path); action_map->add_interaction_profile(new_profile); + action_map->set_edited(true); - _add_interaction_profile_editor(new_profile); + OpenXRInteractionProfileEditorBase *interaction_profile_editor = _add_interaction_profile_editor(new_profile); + + undo_redo->create_action(TTR("Add interaction profile")); + undo_redo->add_do_method(this, "_do_add_interaction_profile_editor", interaction_profile_editor); + undo_redo->add_undo_method(this, "_do_remove_interaction_profile_editor", interaction_profile_editor); + undo_redo->commit_action(false); tabs->set_current_tab(tabs->get_tab_count() - 1); } void OpenXRActionMapEditor::_load_action_map(const String p_path, bool p_create_new_if_missing) { - action_map = ResourceLoader::load(p_path, "", ResourceFormatLoader::CACHE_MODE_IGNORE); - if (action_map.is_null()) { - if (p_create_new_if_missing) { + Error err = OK; + action_map = ResourceLoader::load(p_path, "", ResourceFormatLoader::CACHE_MODE_IGNORE, &err); + if (err != OK) { + if ((err == ERR_FILE_NOT_FOUND || err == ERR_CANT_OPEN) && p_create_new_if_missing) { action_map.instantiate(); action_map->create_default_action_sets(); + + // Save it immediately + err = ResourceSaver::save(action_map, p_path); + if (err != OK) { + // show warning but continue + EditorNode::get_singleton()->show_warning(vformat(TTR("Error saving file %s: %s"), edited_path, error_names[err])); + } + } else { - EditorNode::get_singleton()->show_warning(TTR("Invalid file, not an OpenXR action map.")); + EditorNode::get_singleton()->show_warning(vformat(TTR("Error loading %s: %s."), edited_path, error_names[err])); edited_path = ""; header_label->set_text(""); @@ -254,55 +270,123 @@ void OpenXRActionMapEditor::_load_action_map(const String p_path, bool p_create_ } edited_path = p_path; - header_label->set_text(TTR("OpenXR Action map:") + " " + p_path.get_file()); + header_label->set_text(TTR("OpenXR Action map:") + " " + edited_path.get_file()); } void OpenXRActionMapEditor::_on_save_action_map() { Error err = ResourceSaver::save(action_map, edited_path); if (err != OK) { - EditorNode::get_singleton()->show_warning(vformat(TTR("Error saving file: %s"), edited_path)); + EditorNode::get_singleton()->show_warning(vformat(TTR("Error saving file %s: %s"), edited_path, error_names[err])); return; } - _update_action_sets(); - _update_interaction_profiles(); + // TODO should clear undo/redo history + + // out with the old + _clear_action_map(); + + _create_action_sets(); + _create_interaction_profiles(); } void OpenXRActionMapEditor::_on_reset_to_default_layout() { + // TODO should clear undo/redo history + + // out with the old + _clear_action_map(); + // create a new one action_map.unref(); action_map.instantiate(); action_map->create_default_action_sets(); + action_map->set_edited(true); - _update_action_sets(); - _update_interaction_profiles(); + _create_action_sets(); + _create_interaction_profiles(); } void OpenXRActionMapEditor::_on_tabs_tab_changed(int p_tab) { } void OpenXRActionMapEditor::_on_tab_button_pressed(int p_tab) { - OpenXRInteractionProfileEditorBase *profile_editor = static_cast<OpenXRInteractionProfileEditorBase *>(tabs->get_tab_control(p_tab)); - ERR_FAIL_NULL(profile_editor); + OpenXRInteractionProfileEditorBase *interaction_profile_editor = static_cast<OpenXRInteractionProfileEditorBase *>(tabs->get_tab_control(p_tab)); + ERR_FAIL_NULL(interaction_profile_editor); + + undo_redo->create_action(TTR("Remove interaction profile")); + undo_redo->add_do_method(this, "_do_remove_interaction_profile_editor", interaction_profile_editor); + undo_redo->add_undo_method(this, "_do_add_interaction_profile_editor", interaction_profile_editor); + undo_redo->commit_action(true); + + action_map->set_edited(true); +} + +void OpenXRActionMapEditor::_do_add_action_set_editor(OpenXRActionSetEditor *p_action_set_editor) { + Ref<OpenXRActionSet> action_set = p_action_set_editor->get_action_set(); + ERR_FAIL_COND(action_set.is_null()); + + action_map->add_action_set(action_set); + actionsets_vb->add_child(p_action_set_editor); +} + +void OpenXRActionMapEditor::_do_remove_action_set_editor(OpenXRActionSetEditor *p_action_set_editor) { + Ref<OpenXRActionSet> action_set = p_action_set_editor->get_action_set(); + ERR_FAIL_COND(action_set.is_null()); + + actionsets_vb->remove_child(p_action_set_editor); + action_map->remove_action_set(action_set); +} + +void OpenXRActionMapEditor::_do_add_interaction_profile_editor(OpenXRInteractionProfileEditorBase *p_interaction_profile_editor) { + Ref<OpenXRInteractionProfile> interaction_profile = p_interaction_profile_editor->get_interaction_profile(); + ERR_FAIL_COND(interaction_profile.is_null()); + + action_map->add_interaction_profile(interaction_profile); + tabs->add_child(p_interaction_profile_editor); + tabs->set_tab_button_icon(tabs->get_tab_count() - 1, get_theme_icon(SNAME("close"), SNAME("TabBar"))); + + tabs->set_current_tab(tabs->get_tab_count() - 1); +} - Ref<OpenXRInteractionProfile> interaction_profile = profile_editor->get_interaction_profile(); +void OpenXRActionMapEditor::_do_remove_interaction_profile_editor(OpenXRInteractionProfileEditorBase *p_interaction_profile_editor) { + Ref<OpenXRInteractionProfile> interaction_profile = p_interaction_profile_editor->get_interaction_profile(); ERR_FAIL_COND(interaction_profile.is_null()); + tabs->remove_child(p_interaction_profile_editor); action_map->remove_interaction_profile(interaction_profile); - tabs->remove_child(profile_editor); - profile_editor->queue_free(); } void OpenXRActionMapEditor::open_action_map(String p_path) { EditorNode::get_singleton()->make_bottom_panel_item_visible(this); + // out with the old... + _clear_action_map(); + + // now load in our new action map _load_action_map(p_path); - _update_action_sets(); - _update_interaction_profiles(); + _create_action_sets(); + _create_interaction_profiles(); +} + +void OpenXRActionMapEditor::_clear_action_map() { + while (actionsets_vb->get_child_count() > 0) { + Node *child = actionsets_vb->get_child(0); + actionsets_vb->remove_child(child); + child->queue_free(); + } + + for (int i = 0; i < tabs->get_tab_count(); i++) { + // First tab won't be an interaction profile editor, but being thorough.. + OpenXRInteractionProfileEditorBase *interaction_profile_editor = static_cast<OpenXRInteractionProfileEditorBase *>(tabs->get_tab_control(i)); + if (interaction_profile_editor) { + tabs->remove_child(interaction_profile_editor); + interaction_profile_editor->queue_free(); + } + } } OpenXRActionMapEditor::OpenXRActionMapEditor() { + undo_redo = EditorNode::get_undo_redo(); set_custom_minimum_size(Size2(0.0, 300.0)); top_hb = memnew(HBoxContainer); @@ -364,7 +448,9 @@ OpenXRActionMapEditor::OpenXRActionMapEditor() { select_interaction_profile_dialog->connect("interaction_profile_selected", callable_mp(this, &OpenXRActionMapEditor::_on_interaction_profile_selected)); add_child(select_interaction_profile_dialog); - _load_action_map(GLOBAL_GET("xr/openxr/default_action_map")); + // Our Action map editor is only shown if openxr is enabled in project settings + // So load our action map and if it doesn't exist, create it right away. + _load_action_map(GLOBAL_GET("xr/openxr/default_action_map"), true); } OpenXRActionMapEditor::~OpenXRActionMapEditor() { diff --git a/modules/openxr/editor/openxr_action_map_editor.h b/modules/openxr/editor/openxr_action_map_editor.h index a19bc90f56..8e3210a8e9 100644 --- a/modules/openxr/editor/openxr_action_map_editor.h +++ b/modules/openxr/editor/openxr_action_map_editor.h @@ -37,6 +37,7 @@ #include "../editor/openxr_select_interaction_profile_dialog.h" #include "editor/editor_plugin.h" +#include "editor/editor_undo_redo_manager.h" #include "scene/gui/box_container.h" #include "scene/gui/button.h" #include "scene/gui/label.h" @@ -47,9 +48,9 @@ class OpenXRActionMapEditor : public VBoxContainer { GDCLASS(OpenXRActionMapEditor, VBoxContainer); private: + Ref<EditorUndoRedoManager> undo_redo; String edited_path; Ref<OpenXRActionMap> action_map; - Vector<Node *> interaction_profiles; HBoxContainer *top_hb = nullptr; Label *header_label = nullptr; @@ -64,9 +65,9 @@ private: OpenXRSelectInteractionProfileDialog *select_interaction_profile_dialog = nullptr; OpenXRActionSetEditor *_add_action_set_editor(Ref<OpenXRActionSet> p_action_set); - void _update_action_sets(); + void _create_action_sets(); OpenXRInteractionProfileEditorBase *_add_interaction_profile_editor(Ref<OpenXRInteractionProfile> p_interaction_profile); - void _update_interaction_profiles(); + void _create_interaction_profiles(); OpenXRActionSetEditor *_add_action_set(String p_name); void _remove_action_set(String p_name); @@ -90,6 +91,14 @@ protected: static void _bind_methods(); void _notification(int p_what); + void _clear_action_map(); + + // used for undo/redo + void _do_add_action_set_editor(OpenXRActionSetEditor *p_action_set_editor); + void _do_remove_action_set_editor(OpenXRActionSetEditor *p_action_set_editor); + void _do_add_interaction_profile_editor(OpenXRInteractionProfileEditorBase *p_interaction_profile_editor); + void _do_remove_interaction_profile_editor(OpenXRInteractionProfileEditorBase *p_interaction_profile_editor); + public: void open_action_map(String p_path); diff --git a/modules/openxr/editor/openxr_action_set_editor.cpp b/modules/openxr/editor/openxr_action_set_editor.cpp index 3869146e8e..d3b6945635 100644 --- a/modules/openxr/editor/openxr_action_set_editor.cpp +++ b/modules/openxr/editor/openxr_action_set_editor.cpp @@ -32,8 +32,14 @@ #include "openxr_action_editor.h" void OpenXRActionSetEditor::_bind_methods() { + ClassDB::bind_method(D_METHOD("_do_set_name", "name"), &OpenXRActionSetEditor::_do_set_name); + ClassDB::bind_method(D_METHOD("_do_set_localized_name", "name"), &OpenXRActionSetEditor::_do_set_localized_name); + ClassDB::bind_method(D_METHOD("_do_set_priority", "value"), &OpenXRActionSetEditor::_do_set_priority); + ClassDB::bind_method(D_METHOD("_do_add_action_editor", "action_editor"), &OpenXRActionSetEditor::_do_add_action_editor); + ClassDB::bind_method(D_METHOD("_do_remove_action_editor", "action_editor"), &OpenXRActionSetEditor::_do_remove_action_editor); + ADD_SIGNAL(MethodInfo("remove", PropertyInfo(Variant::OBJECT, "action_set_editor"))); - ADD_SIGNAL(MethodInfo("action_removed")); + ADD_SIGNAL(MethodInfo("action_removed", PropertyInfo(Variant::OBJECT, "action"))); } void OpenXRActionSetEditor::_set_fold_icon() { @@ -68,20 +74,6 @@ OpenXRActionEditor *OpenXRActionSetEditor::_add_action_editor(Ref<OpenXRAction> return action_editor; } -void OpenXRActionSetEditor::_update_actions() { - // out with the old... - while (actions_vb->get_child_count() > 0) { - memdelete(actions_vb->get_child(0)); - } - - // in with the new... - Array actions = action_set->get_actions(); - for (int i = 0; i < actions.size(); i++) { - Ref<OpenXRAction> action = actions[i]; - _add_action_editor(action); - } -} - void OpenXRActionSetEditor::_on_toggle_expand() { is_expanded = !is_expanded; actions_vb->set_visible(is_expanded); @@ -89,24 +81,66 @@ void OpenXRActionSetEditor::_on_toggle_expand() { } void OpenXRActionSetEditor::_on_action_set_name_changed(const String p_new_text) { - // TODO validate if entry is allowed - - // If our localized name matches our action set name, set this too - if (action_set->get_name() == action_set->get_localized_name()) { - action_set->set_localized_name(p_new_text); - action_set_localized_name->set_text(p_new_text); + if (action_set->get_name() != p_new_text) { + undo_redo->create_action(TTR("Rename Action Set")); + undo_redo->add_do_method(this, "_do_set_name", p_new_text); + undo_redo->add_undo_method(this, "_do_set_name", action_set->get_name()); + undo_redo->commit_action(false); + + // If our localized name matches our action set name, set this too + if (action_set->get_name() == action_set->get_localized_name()) { + undo_redo->create_action(TTR("Rename Action Sets Localized name")); + undo_redo->add_do_method(this, "_do_set_localized_name", p_new_text); + undo_redo->add_undo_method(this, "_do_set_localized_name", action_set->get_localized_name()); + undo_redo->commit_action(false); + + action_set->set_localized_name(p_new_text); + action_set_localized_name->set_text(p_new_text); + } + action_set->set_name(p_new_text); + action_set->set_edited(true); } +} + +void OpenXRActionSetEditor::_do_set_name(const String p_new_text) { action_set->set_name(p_new_text); + action_set_name->set_text(p_new_text); } void OpenXRActionSetEditor::_on_action_set_localized_name_changed(const String p_new_text) { + if (action_set->get_localized_name() != p_new_text) { + undo_redo->create_action(TTR("Rename Action Sets Localized name")); + undo_redo->add_do_method(this, "_do_set_localized_name", p_new_text); + undo_redo->add_undo_method(this, "_do_set_localized_name", action_set->get_localized_name()); + undo_redo->commit_action(false); + + action_set->set_localized_name(p_new_text); + action_set->set_edited(true); + } +} + +void OpenXRActionSetEditor::_do_set_localized_name(const String p_new_text) { action_set->set_localized_name(p_new_text); + action_set_localized_name->set_text(p_new_text); } void OpenXRActionSetEditor::_on_action_set_priority_changed(const String p_new_text) { int64_t value = p_new_text.to_int(); - action_set->set_priority(value); + if (action_set->get_priority() != value) { + undo_redo->create_action(TTR("Change Action Sets priority")); + undo_redo->add_do_method(this, "_do_set_priority", value); + undo_redo->add_undo_method(this, "_do_set_priority", action_set->get_priority()); + undo_redo->commit_action(false); + + action_set->set_priority(value); + action_set->set_edited(true); + } +} + +void OpenXRActionSetEditor::_do_set_priority(int64_t p_value) { + action_set->set_priority(p_value); + action_set_priority->set_text(itos(p_value)); } void OpenXRActionSetEditor::_on_add_action() { @@ -116,8 +150,14 @@ void OpenXRActionSetEditor::_on_add_action() { new_action->set_name("New"); new_action->set_localized_name("New"); action_set->add_action(new_action); + action_set->set_edited(true); - _add_action_editor(new_action); + OpenXRActionEditor *action_editor = _add_action_editor(new_action); + + undo_redo->create_action(TTR("Add action")); + undo_redo->add_do_method(this, "_do_add_action_editor", action_editor); + undo_redo->add_undo_method(this, "_do_remove_action_editor", action_editor); + undo_redo->commit_action(false); // TODO handle focus } @@ -133,17 +173,36 @@ void OpenXRActionSetEditor::_on_remove_action(Object *p_action_editor) { Ref<OpenXRAction> action = action_editor->get_action(); ERR_FAIL_COND(action.is_null()); - // TODO add undo/redo action + emit_signal("action_removed", action); + + undo_redo->create_action(TTR("Delete action")); + undo_redo->add_do_method(this, "_do_remove_action_editor", action_editor); + undo_redo->add_undo_method(this, "_do_add_action_editor", action_editor); + undo_redo->commit_action(true); - // TODO find where this action is used by our interaction profiles and remove it there + action_set->set_edited(true); +} - // And remove it.... - action_map->remove_action(action->get_name_with_set()); // remove it from the set and any interaction profile it relates to - actions_vb->remove_child(action_editor); - action_editor->queue_free(); +void OpenXRActionSetEditor::_do_add_action_editor(OpenXRActionEditor *p_action_editor) { + Ref<OpenXRAction> action = p_action_editor->get_action(); + ERR_FAIL_COND(action.is_null()); - // Let action map editor know so we can update our interaction profiles - emit_signal("action_removed"); + action_set->add_action(action); + actions_vb->add_child(p_action_editor); +} + +void OpenXRActionSetEditor::_do_remove_action_editor(OpenXRActionEditor *p_action_editor) { + Ref<OpenXRAction> action = p_action_editor->get_action(); + ERR_FAIL_COND(action.is_null()); + + actions_vb->remove_child(p_action_editor); + action_set->remove_action(action); +} + +void OpenXRActionSetEditor::remove_all_actions() { + for (int i = actions_vb->get_child_count(); i > 0; --i) { + _on_remove_action(actions_vb->get_child(i)); + } } void OpenXRActionSetEditor::set_focus_on_entry() { @@ -214,5 +273,10 @@ OpenXRActionSetEditor::OpenXRActionSetEditor(Ref<OpenXRActionMap> p_action_map, actions_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL); main_vb->add_child(actions_vb); - _update_actions(); + // Add our existing actions + Array actions = action_set->get_actions(); + for (int i = 0; i < actions.size(); i++) { + Ref<OpenXRAction> action = actions[i]; + _add_action_editor(action); + } } diff --git a/modules/openxr/editor/openxr_action_set_editor.h b/modules/openxr/editor/openxr_action_set_editor.h index d8c85d03dd..7a8dc0dcbf 100644 --- a/modules/openxr/editor/openxr_action_set_editor.h +++ b/modules/openxr/editor/openxr_action_set_editor.h @@ -44,6 +44,7 @@ class OpenXRActionSetEditor : public HBoxContainer { GDCLASS(OpenXRActionSetEditor, HBoxContainer); private: + Ref<EditorUndoRedoManager> undo_redo; Ref<OpenXRActionMap> action_map; Ref<OpenXRActionSet> action_set; @@ -63,7 +64,6 @@ private: void _set_fold_icon(); void _theme_changed(); OpenXRActionEditor *_add_action_editor(Ref<OpenXRAction> p_action); - void _update_actions(); void _on_toggle_expand(); void _on_action_set_name_changed(const String p_new_text); @@ -78,10 +78,19 @@ protected: static void _bind_methods(); void _notification(int p_what); + // used for undo/redo + void _do_set_name(const String p_new_text); + void _do_set_localized_name(const String p_new_text); + void _do_set_priority(int64_t value); + void _do_add_action_editor(OpenXRActionEditor *p_action_editor); + void _do_remove_action_editor(OpenXRActionEditor *p_action_editor); + public: Ref<OpenXRActionSet> get_action_set() { return action_set; }; void set_focus_on_entry(); + void remove_all_actions(); + OpenXRActionSetEditor(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRActionSet> p_action_set); }; diff --git a/modules/openxr/editor/openxr_interaction_profile_editor.cpp b/modules/openxr/editor/openxr_interaction_profile_editor.cpp index e2dc2d1b74..3eca1967f5 100644 --- a/modules/openxr/editor/openxr_interaction_profile_editor.cpp +++ b/modules/openxr/editor/openxr_interaction_profile_editor.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "openxr_interaction_profile_editor.h" +#include "editor/editor_node.h" #include "scene/gui/box_container.h" #include "scene/gui/button.h" #include "scene/gui/label.h" @@ -58,6 +59,13 @@ void OpenXRInteractionProfileEditorBase::_notification(int p_what) { } } +void OpenXRInteractionProfileEditorBase::_do_update_interaction_profile() { + if (!is_dirty) { + is_dirty = true; + call_deferred("_update_interaction_profile"); + } +} + void OpenXRInteractionProfileEditorBase::_add_binding(const String p_action, const String p_path) { ERR_FAIL_COND(action_map.is_null()); ERR_FAIL_COND(interaction_profile.is_null()); @@ -71,14 +79,16 @@ void OpenXRInteractionProfileEditorBase::_add_binding(const String p_action, con binding.instantiate(); binding->set_action(action); interaction_profile->add_binding(binding); + interaction_profile->set_edited(true); } binding->add_path(p_path); + binding->set_edited(true); // Update our toplevel paths action->set_toplevel_paths(action_map->get_top_level_paths(action)); - call_deferred("_update_interaction_profile"); + _do_update_interaction_profile(); } void OpenXRInteractionProfileEditorBase::_remove_binding(const String p_action, const String p_path) { @@ -91,25 +101,54 @@ void OpenXRInteractionProfileEditorBase::_remove_binding(const String p_action, Ref<OpenXRIPBinding> binding = interaction_profile->get_binding_for_action(action); if (binding.is_valid()) { binding->remove_path(p_path); + binding->set_edited(true); if (binding->get_path_count() == 0) { interaction_profile->remove_binding(binding); + interaction_profile->set_edited(true); } // Update our toplevel paths action->set_toplevel_paths(action_map->get_top_level_paths(action)); - call_deferred("_update_interaction_profile"); + _do_update_interaction_profile(); + } +} + +void OpenXRInteractionProfileEditorBase::remove_all_bindings_for_action(Ref<OpenXRAction> p_action) { + Ref<OpenXRIPBinding> binding = interaction_profile->get_binding_for_action(p_action); + if (binding.is_valid()) { + String action_name = p_action->get_name_with_set(); + + // for our undo/redo we process all paths + undo_redo->create_action(TTR("Remove action from interaction profile")); + PackedStringArray paths = binding->get_paths(); + for (const String &path : paths) { + undo_redo->add_do_method(this, "_remove_binding", p_action, path); + undo_redo->add_undo_method(this, "_add_binding", p_action, path); + } + undo_redo->commit_action(false); + + // but we take a shortcut here :) + interaction_profile->remove_binding(binding); + interaction_profile->set_edited(true); + + // Update our toplevel paths + p_action->set_toplevel_paths(action_map->get_top_level_paths(p_action)); + + _do_update_interaction_profile(); } } OpenXRInteractionProfileEditorBase::OpenXRInteractionProfileEditorBase(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile) { + undo_redo = EditorNode::get_undo_redo(); + action_map = p_action_map; interaction_profile = p_interaction_profile; String profile_path = interaction_profile->get_interaction_profile_path(); String profile_name = profile_path; - profile_def = OpenXRDefs::get_profile(profile_path); + profile_def = OpenXRInteractionProfileMetaData::get_singleton()->get_profile(profile_path); if (profile_def != nullptr) { profile_name = profile_def->display_name; } @@ -117,6 +156,9 @@ OpenXRInteractionProfileEditorBase::OpenXRInteractionProfileEditorBase(Ref<OpenX set_name(profile_name); set_h_size_flags(SIZE_EXPAND_FILL); set_v_size_flags(SIZE_EXPAND_FILL); + + // Make sure it is updated when it enters the tree... + is_dirty = true; } /////////////////////////////////////////////////////////////////////////// @@ -128,11 +170,22 @@ void OpenXRInteractionProfileEditor::select_action_for(const String p_io_path) { } void OpenXRInteractionProfileEditor::action_selected(const String p_action) { - _add_binding(p_action, selecting_for_io_path); + undo_redo->create_action(TTR("Add binding")); + undo_redo->add_do_method(this, "_add_binding", p_action, selecting_for_io_path); + undo_redo->add_undo_method(this, "_remove_binding", p_action, selecting_for_io_path); + undo_redo->commit_action(true); + selecting_for_io_path = ""; } -void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, const OpenXRDefs::IOPath *p_io_path) { +void OpenXRInteractionProfileEditor::_on_remove_pressed(const String p_action, const String p_for_io_path) { + undo_redo->create_action(TTR("Remove binding")); + undo_redo->add_do_method(this, "_remove_binding", p_action, p_for_io_path); + undo_redo->add_undo_method(this, "_add_binding", p_action, p_for_io_path); + undo_redo->commit_action(true); +} + +void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, const OpenXRInteractionProfileMetaData::IOPath *p_io_path) { HBoxContainer *path_hb = memnew(HBoxContainer); path_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL); p_container->add_child(path_hb); @@ -196,7 +249,7 @@ void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, co Button *action_rem = memnew(Button); action_rem->set_flat(true); action_rem->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); - action_rem->connect("pressed", callable_mp((OpenXRInteractionProfileEditorBase *)this, &OpenXRInteractionProfileEditorBase::_remove_binding).bind(action->get_name_with_set(), String(p_io_path->openxr_path))); + action_rem->connect("pressed", callable_mp((OpenXRInteractionProfileEditor *)this, &OpenXRInteractionProfileEditor::_on_remove_pressed).bind(action->get_name_with_set(), String(p_io_path->openxr_path))); action_hb->add_child(action_rem); } } @@ -206,6 +259,11 @@ void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, co void OpenXRInteractionProfileEditor::_update_interaction_profile() { ERR_FAIL_NULL(profile_def); + if (!is_dirty) { + // no need to update + return; + } + // out with the old... while (main_hb->get_child_count() > 0) { memdelete(main_hb->get_child(0)); @@ -214,9 +272,9 @@ void OpenXRInteractionProfileEditor::_update_interaction_profile() { // in with the new... // Determine toplevel paths - Vector<const OpenXRDefs::TopLevelPath *> top_level_paths; - for (int i = 0; i < profile_def->io_path_count; i++) { - const OpenXRDefs::IOPath *io_path = &profile_def->io_paths[i]; + Vector<String> top_level_paths; + for (int i = 0; i < profile_def->io_paths.size(); i++) { + const OpenXRInteractionProfileMetaData::IOPath *io_path = &profile_def->io_paths[i]; if (!top_level_paths.has(io_path->top_level_path)) { top_level_paths.push_back(io_path->top_level_path); @@ -233,16 +291,19 @@ void OpenXRInteractionProfileEditor::_update_interaction_profile() { panel->add_child(container); Label *label = memnew(Label); - label->set_text(top_level_paths[i]->display_name); + label->set_text(OpenXRInteractionProfileMetaData::get_singleton()->get_top_level_name(top_level_paths[i])); container->add_child(label); - for (int j = 0; j < profile_def->io_path_count; j++) { - const OpenXRDefs::IOPath *io_path = &profile_def->io_paths[j]; + for (int j = 0; j < profile_def->io_paths.size(); j++) { + const OpenXRInteractionProfileMetaData::IOPath *io_path = &profile_def->io_paths[j]; if (io_path->top_level_path == top_level_paths[i]) { _add_io_path(container, io_path); } } } + + // and we've updated it... + is_dirty = false; } void OpenXRInteractionProfileEditor::_theme_changed() { @@ -256,14 +317,10 @@ void OpenXRInteractionProfileEditor::_theme_changed() { OpenXRInteractionProfileEditor::OpenXRInteractionProfileEditor(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile) : OpenXRInteractionProfileEditorBase(p_action_map, p_interaction_profile) { - // TODO background of scrollbox should be darker with our VBoxContainers we're adding in _update_interaction_profile the normal color - main_hb = memnew(HBoxContainer); add_child(main_hb); select_action_dialog = memnew(OpenXRSelectActionDialog(p_action_map)); select_action_dialog->connect("action_selected", callable_mp(this, &OpenXRInteractionProfileEditor::action_selected)); add_child(select_action_dialog); - - _update_interaction_profile(); } diff --git a/modules/openxr/editor/openxr_interaction_profile_editor.h b/modules/openxr/editor/openxr_interaction_profile_editor.h index 20a37a80eb..14af702b94 100644 --- a/modules/openxr/editor/openxr_interaction_profile_editor.h +++ b/modules/openxr/editor/openxr_interaction_profile_editor.h @@ -32,8 +32,9 @@ #define OPENXR_INTERACTION_PROFILE_EDITOR_H #include "../action_map/openxr_action_map.h" -#include "../action_map/openxr_defs.h" #include "../action_map/openxr_interaction_profile.h" +#include "../action_map/openxr_interaction_profile_meta_data.h" +#include "editor/editor_undo_redo_manager.h" #include "scene/gui/scroll_container.h" #include "openxr_select_action_dialog.h" @@ -42,22 +43,29 @@ class OpenXRInteractionProfileEditorBase : public ScrollContainer { GDCLASS(OpenXRInteractionProfileEditorBase, ScrollContainer); protected: + Ref<EditorUndoRedoManager> undo_redo; Ref<OpenXRInteractionProfile> interaction_profile; Ref<OpenXRActionMap> action_map; + bool is_dirty = false; + static void _bind_methods(); void _notification(int p_what); - const OpenXRDefs::InteractionProfile *profile_def = nullptr; + const OpenXRInteractionProfileMetaData::InteractionProfile *profile_def = nullptr; public: Ref<OpenXRInteractionProfile> get_interaction_profile() { return interaction_profile; } virtual void _update_interaction_profile() {} virtual void _theme_changed() {} + + void _do_update_interaction_profile(); void _add_binding(const String p_action, const String p_path); void _remove_binding(const String p_action, const String p_path); + void remove_all_bindings_for_action(Ref<OpenXRAction> p_action); + OpenXRInteractionProfileEditorBase(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile); }; @@ -69,11 +77,12 @@ private: HBoxContainer *main_hb = nullptr; OpenXRSelectActionDialog *select_action_dialog = nullptr; - void _add_io_path(VBoxContainer *p_container, const OpenXRDefs::IOPath *p_io_path); + void _add_io_path(VBoxContainer *p_container, const OpenXRInteractionProfileMetaData::IOPath *p_io_path); public: void select_action_for(const String p_io_path); void action_selected(const String p_action); + void _on_remove_pressed(const String p_action, const String p_for_io_path); virtual void _update_interaction_profile() override; virtual void _theme_changed() override; diff --git a/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp b/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp index e92519aec2..6ce26a62db 100644 --- a/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp +++ b/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp @@ -75,13 +75,13 @@ void OpenXRSelectInteractionProfileDialog::open(PackedStringArray p_do_not_inclu ip_buttons.clear(); // in with the new - PackedStringArray interaction_profiles = OpenXRDefs::get_interaction_profile_paths(); + PackedStringArray interaction_profiles = OpenXRInteractionProfileMetaData::get_singleton()->get_interaction_profile_paths(); for (int i = 0; i < interaction_profiles.size(); i++) { String path = interaction_profiles[i]; if (!p_do_not_include.has(path)) { Button *ip_button = memnew(Button); ip_button->set_flat(true); - ip_button->set_text(OpenXRDefs::get_profile(path)->display_name); + ip_button->set_text(OpenXRInteractionProfileMetaData::get_singleton()->get_profile(path)->display_name); ip_button->connect("pressed", callable_mp(this, &OpenXRSelectInteractionProfileDialog::_on_select_interaction_profile).bind(path)); main_vb->add_child(ip_button); diff --git a/modules/openxr/editor/openxr_select_interaction_profile_dialog.h b/modules/openxr/editor/openxr_select_interaction_profile_dialog.h index 54bfe3120a..767326bc46 100644 --- a/modules/openxr/editor/openxr_select_interaction_profile_dialog.h +++ b/modules/openxr/editor/openxr_select_interaction_profile_dialog.h @@ -31,7 +31,7 @@ #ifndef OPENXR_SELECT_INTERACTION_PROFILE_DIALOG_H #define OPENXR_SELECT_INTERACTION_PROFILE_DIALOG_H -#include "../action_map/openxr_defs.h" +#include "../action_map/openxr_interaction_profile_meta_data.h" #include "scene/gui/box_container.h" #include "scene/gui/button.h" #include "scene/gui/dialogs.h" diff --git a/modules/openxr/extensions/openxr_extension_wrapper.h b/modules/openxr/extensions/openxr_extension_wrapper.h index 77b52ab355..eed969d628 100644 --- a/modules/openxr/extensions/openxr_extension_wrapper.h +++ b/modules/openxr/extensions/openxr_extension_wrapper.h @@ -89,11 +89,6 @@ public: return false; } - // Return false if this extension is responsible for this path but the path is not enabled - virtual bool is_path_supported(const String &p_path) { - return true; - } - OpenXRExtensionWrapper(OpenXRAPI *p_openxr_api) { openxr_api = p_openxr_api; }; virtual ~OpenXRExtensionWrapper() = default; }; diff --git a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp index 29208efb20..302acf4e30 100644 --- a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp +++ b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.cpp @@ -65,38 +65,3 @@ bool OpenXRHTCViveTrackerExtension::on_event_polled(const XrEventDataBuffer &eve } break; } } - -bool OpenXRHTCViveTrackerExtension::is_path_supported(const String &p_path) { - if (p_path == "/interaction_profiles/htc/vive_tracker_htcx") { - return available; - } else if (p_path == "/user/vive_tracker_htcx/role/handheld_object") { - return available; - } else if (p_path == "/user/vive_tracker_htcx/role/left_foot") { - return available; - } else if (p_path == "/user/vive_tracker_htcx/role/right_foot") { - return available; - } else if (p_path == "/user/vive_tracker_htcx/role/left_shoulder") { - return available; - } else if (p_path == "/user/vive_tracker_htcx/role/right_shoulder") { - return available; - } else if (p_path == "/user/vive_tracker_htcx/role/left_elbow") { - return available; - } else if (p_path == "/user/vive_tracker_htcx/role/right_elbow") { - return available; - } else if (p_path == "/user/vive_tracker_htcx/role/left_knee") { - return available; - } else if (p_path == "/user/vive_tracker_htcx/role/right_knee") { - return available; - } else if (p_path == "/user/vive_tracker_htcx/role/waist") { - return available; - } else if (p_path == "/user/vive_tracker_htcx/role/chest") { - return available; - } else if (p_path == "/user/vive_tracker_htcx/role/camera") { - return available; - } else if (p_path == "/user/vive_tracker_htcx/role/keyboard") { - return available; - } - - // Not a path under this extensions control, so we return true; - return true; -} diff --git a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.h b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.h index ab8e8535f1..376af35e37 100644 --- a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.h +++ b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.h @@ -43,7 +43,6 @@ public: bool is_available(); virtual bool on_event_polled(const XrEventDataBuffer &event) override; - virtual bool is_path_supported(const String &p_path) override; private: static OpenXRHTCViveTrackerExtension *singleton; diff --git a/modules/openxr/extensions/openxr_palm_pose_extension.cpp b/modules/openxr/extensions/openxr_palm_pose_extension.cpp index fd3b8f50fe..8f87aaea7f 100644 --- a/modules/openxr/extensions/openxr_palm_pose_extension.cpp +++ b/modules/openxr/extensions/openxr_palm_pose_extension.cpp @@ -51,16 +51,3 @@ OpenXRPalmPoseExtension::~OpenXRPalmPoseExtension() { bool OpenXRPalmPoseExtension::is_available() { return available; } - -bool OpenXRPalmPoseExtension::is_path_supported(const String &p_path) { - if (p_path == "/user/hand/left/input/palm_ext/pose") { - return available; - } - - if (p_path == "/user/hand/right/input/palm_ext/pose") { - return available; - } - - // Not a path under this extensions control, so we return true; - return true; -} diff --git a/modules/openxr/extensions/openxr_palm_pose_extension.h b/modules/openxr/extensions/openxr_palm_pose_extension.h index a7ef83c5d5..a63c57eb51 100644 --- a/modules/openxr/extensions/openxr_palm_pose_extension.h +++ b/modules/openxr/extensions/openxr_palm_pose_extension.h @@ -42,8 +42,6 @@ public: bool is_available(); - virtual bool is_path_supported(const String &p_path) override; - private: static OpenXRPalmPoseExtension *singleton; diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp index b652ca4617..a075031ac9 100644 --- a/modules/openxr/openxr_api.cpp +++ b/modules/openxr/openxr_api.cpp @@ -208,17 +208,79 @@ bool OpenXRAPI::is_extension_supported(const String &p_extension) const { return false; } -bool OpenXRAPI::is_path_supported(const String &p_path) { - // This checks with extensions whether a path is *unsupported* and returns false if this is so. - // This allows us to filter out paths that are only available if related extensions are supported. - // WARNING: This method will return true for unknown/mistyped paths as we have no way to validate those. +bool OpenXRAPI::is_extension_enabled(const String &p_extension) const { + CharString extension = p_extension.ascii(); - for (OpenXRExtensionWrapper *wrapper : registered_extension_wrappers) { - if (!wrapper->is_path_supported(p_path)) { - return false; + for (int i = 0; i < enabled_extensions.size(); i++) { + if (strcmp(enabled_extensions[i].ptr(), extension.ptr()) == 0) { + return true; } } + return false; +} + +bool OpenXRAPI::is_top_level_path_supported(const String &p_toplevel_path) { + String required_extension = OpenXRInteractionProfileMetaData::get_singleton()->get_top_level_extension(p_toplevel_path); + + // If unsupported is returned we likely have a misspelled interaction profile path in our action map. Always output that as an error. + ERR_FAIL_COND_V_MSG(required_extension == XR_PATH_UNSUPPORTED_NAME, false, "OpenXR: Unsupported interaction profile " + p_toplevel_path); + + if (required_extension == "") { + // no extension needed, core top level are always "supported", they just won't be used if not really supported + return true; + } + + if (!is_extension_enabled(required_extension)) { + // It is very likely we have top level paths for which the extension is not available so don't flood the logs with unnecessary spam. + print_verbose("OpenXR: Top level path " + p_toplevel_path + " requires extension " + required_extension); + return false; + } + + return true; +} + +bool OpenXRAPI::is_interaction_profile_supported(const String &p_ip_path) { + String required_extension = OpenXRInteractionProfileMetaData::get_singleton()->get_interaction_profile_extension(p_ip_path); + + // If unsupported is returned we likely have a misspelled interaction profile path in our action map. Always output that as an error. + ERR_FAIL_COND_V_MSG(required_extension == XR_PATH_UNSUPPORTED_NAME, false, "OpenXR: Unsupported interaction profile " + p_ip_path); + + if (required_extension == "") { + // no extension needed, core interaction profiles are always "supported", they just won't be used if not really supported + return true; + } + + if (!is_extension_enabled(required_extension)) { + // It is very likely we have interaction profiles for which the extension is not available so don't flood the logs with unnecessary spam. + print_verbose("OpenXR: Interaction profile " + p_ip_path + " requires extension " + required_extension); + return false; + } + + return true; +} + +bool OpenXRAPI::interaction_profile_supports_io_path(const String &p_ip_path, const String &p_io_path) { + if (!is_interaction_profile_supported(p_ip_path)) { + return false; + } + + const OpenXRInteractionProfileMetaData::IOPath *io_path = OpenXRInteractionProfileMetaData::get_singleton()->get_io_path(p_ip_path, p_io_path); + + // If the io_path is not part of our meta data we've likely got a misspelled name or a bad action map, report + ERR_FAIL_NULL_V_MSG(io_path, false, "OpenXR: Unsupported io path " + String(p_ip_path) + String(p_io_path)); + + if (io_path->openxr_extension_name == "") { + // no extension needed, core io paths are always "supported", they just won't be used if not really supported + return true; + } + + if (!is_extension_enabled(io_path->openxr_extension_name)) { + // It is very likely we have io paths for which the extension is not available so don't flood the logs with unnecessary spam. + print_verbose("OpenXR: IO path " + String(p_ip_path) + String(p_io_path) + " requires extension " + io_path->openxr_extension_name); + return false; + } + return true; } @@ -283,6 +345,7 @@ bool OpenXRAPI::create_instance() { Vector<const char *> extension_ptrs; for (int i = 0; i < enabled_extensions.size(); i++) { + print_verbose(String("OpenXR: Enabling extension ") + String(enabled_extensions[i])); extension_ptrs.push_back(enabled_extensions[i].get_data()); } @@ -2341,7 +2404,7 @@ XrPath OpenXRAPI::get_interaction_profile_path(RID p_interaction_profile) { } RID OpenXRAPI::interaction_profile_create(const String p_name) { - if (!is_path_supported(p_name)) { + if (!is_interaction_profile_supported(p_name)) { // The extension enabling this path must not be active, we will silently skip this interaction profile return RID(); } @@ -2382,14 +2445,13 @@ void OpenXRAPI::interaction_profile_clear_bindings(RID p_interaction_profile) { } bool OpenXRAPI::interaction_profile_add_binding(RID p_interaction_profile, RID p_action, const String p_path) { - if (!is_path_supported(p_path)) { - // The extension enabling this path must not be active, we will silently skip this binding - return false; - } - InteractionProfile *ip = interaction_profile_owner.get_or_null(p_interaction_profile); ERR_FAIL_NULL_V(ip, false); + if (!interaction_profile_supports_io_path(ip->name, p_path)) { + return false; + } + XrActionSuggestedBinding binding; Action *action = action_owner.get_or_null(p_action); diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h index ac4bbff94c..806e859da0 100644 --- a/modules/openxr/openxr_api.h +++ b/modules/openxr/openxr_api.h @@ -150,6 +150,7 @@ private: bool load_layer_properties(); bool load_supported_extensions(); bool is_extension_supported(const String &p_extension) const; + bool is_extension_enabled(const String &p_extension) const; bool openxr_loader_init(); bool resolve_instance_openxr_symbols(); @@ -301,7 +302,9 @@ public: void parse_velocities(const XrSpaceVelocity &p_velocity, Vector3 &r_linear_velocity, Vector3 &r_angular_velocity); bool xr_result(XrResult result, const char *format, Array args = Array()) const; - bool is_path_supported(const String &p_path); + bool is_top_level_path_supported(const String &p_toplevel_path); + bool is_interaction_profile_supported(const String &p_ip_path); + bool interaction_profile_supports_io_path(const String &p_ip_path, const String &p_io_path); static bool openxr_is_enabled(bool p_check_run_in_editor = true); static OpenXRAPI *get_singleton(); diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp index 40190ab2f3..d6f7cd7b3e 100644 --- a/modules/openxr/openxr_interface.cpp +++ b/modules/openxr/openxr_interface.cpp @@ -158,7 +158,7 @@ void OpenXRInterface::_load_action_map() { for (int k = 0; k < toplevel_paths.size(); k++) { // Only check for our tracker if our path is supported. - if (openxr_api->is_path_supported(toplevel_paths[k])) { + if (openxr_api->is_top_level_path_supported(toplevel_paths[k])) { Tracker *tracker = find_tracker(toplevel_paths[k], true); if (tracker) { trackers_for_action.push_back(tracker); @@ -345,7 +345,7 @@ OpenXRInterface::Tracker *OpenXRInterface::find_tracker(const String &p_tracker_ return nullptr; } - ERR_FAIL_COND_V(!openxr_api->is_path_supported(p_tracker_name), nullptr); + ERR_FAIL_COND_V(!openxr_api->is_top_level_path_supported(p_tracker_name), nullptr); // Create our RID RID tracker_rid = openxr_api->tracker_create(p_tracker_name); diff --git a/modules/openxr/register_types.cpp b/modules/openxr/register_types.cpp index 5694fffe39..0835bbd642 100644 --- a/modules/openxr/register_types.cpp +++ b/modules/openxr/register_types.cpp @@ -37,9 +37,14 @@ #include "action_map/openxr_action_map.h" #include "action_map/openxr_action_set.h" #include "action_map/openxr_interaction_profile.h" +#include "action_map/openxr_interaction_profile_meta_data.h" #include "scene/openxr_hand.h" +static OpenXRAPI *openxr_api = nullptr; +static OpenXRInteractionProfileMetaData *openxr_interaction_profile_meta_data = nullptr; +static Ref<OpenXRInterface> openxr_interface; + #ifdef TOOLS_ENABLED #include "editor/editor_node.h" @@ -49,6 +54,12 @@ static void _editor_init() { if (OpenXRAPI::openxr_is_enabled(false)) { // Only add our OpenXR action map editor if OpenXR is enabled for our project + if (openxr_interaction_profile_meta_data == nullptr) { + // If we didn't initialize our actionmap meta data at startup, we initialise it now. + openxr_interaction_profile_meta_data = memnew(OpenXRInteractionProfileMetaData); + ERR_FAIL_NULL(openxr_interaction_profile_meta_data); + } + OpenXREditorPlugin *openxr_plugin = memnew(OpenXREditorPlugin()); EditorNode::get_singleton()->add_editor_plugin(openxr_plugin); } @@ -56,14 +67,13 @@ static void _editor_init() { #endif -static OpenXRAPI *openxr_api = nullptr; -static Ref<OpenXRInterface> openxr_interface; - void initialize_openxr_module(ModuleInitializationLevel p_level) { if (p_level == MODULE_INITIALIZATION_LEVEL_SERVERS) { // For now we create our openxr device here. If we merge it with openxr_interface we'll create that here soon. if (OpenXRAPI::openxr_is_enabled()) { + openxr_interaction_profile_meta_data = memnew(OpenXRInteractionProfileMetaData); + ERR_FAIL_NULL(openxr_interaction_profile_meta_data); openxr_api = memnew(OpenXRAPI); ERR_FAIL_NULL(openxr_api); @@ -81,6 +91,7 @@ void initialize_openxr_module(ModuleInitializationLevel p_level) { GDREGISTER_CLASS(OpenXRAction); GDREGISTER_CLASS(OpenXRActionSet); GDREGISTER_CLASS(OpenXRActionMap); + GDREGISTER_CLASS(OpenXRInteractionProfileMetaData); GDREGISTER_CLASS(OpenXRIPBinding); GDREGISTER_CLASS(OpenXRInteractionProfile); @@ -131,4 +142,9 @@ void uninitialize_openxr_module(ModuleInitializationLevel p_level) { memdelete(openxr_api); openxr_api = nullptr; } + + if (openxr_interaction_profile_meta_data) { + memdelete(openxr_interaction_profile_meta_data); + openxr_interaction_profile_meta_data = nullptr; + } } diff --git a/modules/raycast/config.py b/modules/raycast/config.py index f4243f01c5..26329d813a 100644 --- a/modules/raycast/config.py +++ b/modules/raycast/config.py @@ -1,13 +1,11 @@ def can_build(env, platform): # Supported architectures depend on the Embree library. - # No ARM32 support planned. - if env["arch"] == "arm32": - return False + if env["arch"] in ["x86_64", "arm64", "wasm32"]: + return True # x86_32 only seems supported on Windows for now. - if env["arch"] == "x86_32" and platform != "windows": - return False - # The rest works, even wasm32! - return True + if env["arch"] == "x86_32" and platform == "windows": + return True + return False def configure(env): diff --git a/modules/register_module_types.h b/modules/register_module_types.h index cfd1b355d4..706e641735 100644 --- a/modules/register_module_types.h +++ b/modules/register_module_types.h @@ -31,13 +31,13 @@ #ifndef REGISTER_MODULE_TYPES_H #define REGISTER_MODULE_TYPES_H -#include "core/extension/gdnative_interface.h" +#include "core/extension/gdextension_interface.h" enum ModuleInitializationLevel { - MODULE_INITIALIZATION_LEVEL_CORE = GDNATIVE_INITIALIZATION_CORE, - MODULE_INITIALIZATION_LEVEL_SERVERS = GDNATIVE_INITIALIZATION_SERVERS, - MODULE_INITIALIZATION_LEVEL_SCENE = GDNATIVE_INITIALIZATION_SCENE, - MODULE_INITIALIZATION_LEVEL_EDITOR = GDNATIVE_INITIALIZATION_EDITOR + MODULE_INITIALIZATION_LEVEL_CORE = GDEXTENSION_INITIALIZATION_CORE, + MODULE_INITIALIZATION_LEVEL_SERVERS = GDEXTENSION_INITIALIZATION_SERVERS, + MODULE_INITIALIZATION_LEVEL_SCENE = GDEXTENSION_INITIALIZATION_SCENE, + MODULE_INITIALIZATION_LEVEL_EDITOR = GDEXTENSION_INITIALIZATION_EDITOR }; void initialize_modules(ModuleInitializationLevel p_level); diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub index 3c7a89b705..4a9c7b3567 100644 --- a/modules/text_server_adv/SCsub +++ b/modules/text_server_adv/SCsub @@ -223,9 +223,6 @@ if env["builtin_graphite"] and freetype_enabled and env["graphite"]: ] ) - if env.msvc: # Not our business to fix. - env_graphite.Append(CCFLAGS=["-D_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS"]) - lib = env_graphite.add_library("graphite_builtin", thirdparty_sources) thirdparty_obj += lib diff --git a/modules/text_server_adv/register_types.cpp b/modules/text_server_adv/register_types.cpp index 6a26584506..64373e9f2b 100644 --- a/modules/text_server_adv/register_types.cpp +++ b/modules/text_server_adv/register_types.cpp @@ -62,7 +62,7 @@ using namespace godot; extern "C" { -GDNativeBool GDN_EXPORT textserver_advanced_init(const GDNativeInterface *p_interface, const GDNativeExtensionClassLibraryPtr p_library, GDNativeInitialization *r_initialization) { +GDExtensionBool GDN_EXPORT textserver_advanced_init(const GDExtensionInterface *p_interface, const GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) { GDExtensionBinding::InitObject init_obj(p_interface, p_library, r_initialization); init_obj.register_initializer(&initialize_text_server_adv_module); diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index cf77d0ed7f..512643867b 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -6196,6 +6196,9 @@ String TextServerAdvanced::_strip_diacritics(const String &p_string) const { } String TextServerAdvanced::_string_to_upper(const String &p_string, const String &p_language) const { + if (p_string.is_empty()) { + return p_string; + } const String lang = (p_language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale() : p_language; // Convert to UTF-16. @@ -6215,6 +6218,9 @@ String TextServerAdvanced::_string_to_upper(const String &p_string, const String } String TextServerAdvanced::_string_to_lower(const String &p_string, const String &p_language) const { + if (p_string.is_empty()) { + return p_string; + } const String lang = (p_language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale() : p_language; // Convert to UTF-16. Char16String utf16 = p_string.utf16(); diff --git a/modules/text_server_fb/register_types.cpp b/modules/text_server_fb/register_types.cpp index fa7b87fc17..98a8f466b3 100644 --- a/modules/text_server_fb/register_types.cpp +++ b/modules/text_server_fb/register_types.cpp @@ -62,7 +62,7 @@ using namespace godot; extern "C" { -GDNativeBool GDN_EXPORT textserver_fallback_init(const GDNativeInterface *p_interface, const GDNativeExtensionClassLibraryPtr p_library, GDNativeInitialization *r_initialization) { +GDExtensionBool GDN_EXPORT textserver_fallback_init(const GDExtensionInterface *p_interface, const GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) { GDExtensionBinding::InitObject init_obj(p_interface, p_library, r_initialization); init_obj.register_initializer(&initialize_text_server_fb_module); diff --git a/modules/webrtc/webrtc_data_channel_extension.h b/modules/webrtc/webrtc_data_channel_extension.h index 467163ed93..92bd9619ef 100644 --- a/modules/webrtc/webrtc_data_channel_extension.h +++ b/modules/webrtc/webrtc_data_channel_extension.h @@ -70,8 +70,8 @@ public: virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size) override; /** GDExtension **/ - GDVIRTUAL2R(Error, _get_packet, GDNativeConstPtr<const uint8_t *>, GDNativePtr<int>); - GDVIRTUAL2R(Error, _put_packet, GDNativeConstPtr<const uint8_t>, int); + GDVIRTUAL2R(Error, _get_packet, GDExtensionConstPtr<const uint8_t *>, GDExtensionPtr<int>); + GDVIRTUAL2R(Error, _put_packet, GDExtensionConstPtr<const uint8_t>, int); WebRTCDataChannelExtension() {} }; |