diff --git a/.clang-format b/.clang-format index b828c2d..76ec17c 100644 --- a/.clang-format +++ b/.clang-format @@ -8,6 +8,8 @@ AllowAllParametersOfDeclarationOnNextLine: false AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: All AllowShortIfStatementsOnASingleLine: true +BinPackArguments: false +BinPackParameters: false BreakBeforeTernaryOperators: false BreakConstructorInitializers: AfterColon ColumnLimit: 100 @@ -18,14 +20,6 @@ ContinuationIndentWidth: 8 Cpp11BracedListStyle: false DisableFormat: false FixNamespaceComments: true -IncludeBlocks: Regroup -IncludeCategories: - - Regex: '".*"' - Priority: 1 - - Regex: '^<.*\.h>' - Priority: 2 - - Regex: '^<.*' - Priority: 3 IndentCaseLabels: true IndentWidth: 4 KeepEmptyLinesAtTheStartOfBlocks: false @@ -40,8 +34,16 @@ UseTab: Never ### C++ specific config ### Language: Cpp Standard: Auto -AccessModifierOffset: -4 +AccessModifierOffset: -3 AllowShortFunctionsOnASingleLine: Inline +IncludeBlocks: Merge +IncludeCategories: + - Regex: '".*"' + Priority: 1 + - Regex: '^<.*\.h>' + Priority: 2 + - Regex: '^<.*' + Priority: 3 --- ### Java specific config ### Language: Java diff --git a/.editorconfig b/.editorconfig index 1143c77..a42d062 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,9 +8,492 @@ indent_style = space insert_final_newline = true max_line_length = 100 trim_trailing_whitespace = true - -[*.{cpp,hpp,c,h,mm}] -ij_c_indent_namespace_members = 0 +tab_width = 4 +ij_continuation_indent_size = 8 +ij_formatter_off_tag = @formatter:off +ij_formatter_on_tag = @formatter:on +ij_formatter_tags_enabled = false +ij_smart_tabs = false +ij_wrap_on_typing = true [*.gd] indent_style = tab + +[{*.cp,*.cc,*.hpp,*.cpp,*.tcc,*.hp,*.ii,*.cxx,*.h++,*.icc,*.mm,*.hxx,*.hh,*.m,*.i,*.h,*.c,*.ipp,*.c++,*.pch,*.ino,*.inl}] +ij_c_add_brief_tag = false +ij_c_add_getter_prefix = true +ij_c_add_setter_prefix = true +ij_c_align_dictionary_pair_values = false +ij_c_align_group_field_declarations = false +ij_c_align_init_list_in_columns = true +ij_c_align_multiline_array_initializer_expression = true +ij_c_align_multiline_assignment = true +ij_c_align_multiline_binary_operation = true +ij_c_align_multiline_chained_methods = true +ij_c_align_multiline_for = true +ij_c_align_multiline_ternary_operation = true +ij_c_array_initializer_comma_on_next_line = false +ij_c_array_initializer_new_line_after_left_brace = false +ij_c_array_initializer_right_brace_on_new_line = false +ij_c_array_initializer_wrap = normal +ij_c_assignment_wrap = off +ij_c_binary_operation_sign_on_next_line = false +ij_c_binary_operation_wrap = normal +ij_c_blank_lines_after_class_header = 0 +ij_c_blank_lines_after_imports = 1 +ij_c_blank_lines_around_class = 1 +ij_c_blank_lines_around_field = 0 +ij_c_blank_lines_around_field_in_interface = 0 +ij_c_blank_lines_around_method = 1 +ij_c_blank_lines_around_method_in_interface = 1 +ij_c_blank_lines_around_namespace = 0 +ij_c_blank_lines_around_properties_in_declaration = 0 +ij_c_blank_lines_around_properties_in_interface = 0 +ij_c_blank_lines_before_imports = 1 +ij_c_blank_lines_before_method_body = 0 +ij_c_block_brace_placement = end_of_line +ij_c_block_brace_style = end_of_line +ij_c_block_comment_at_first_column = true +ij_c_catch_on_new_line = false +ij_c_class_brace_style = end_of_line +ij_c_class_constructor_init_list_align_multiline = true +ij_c_class_constructor_init_list_comma_on_next_line = false +ij_c_class_constructor_init_list_new_line_after_colon = never +ij_c_class_constructor_init_list_new_line_before_colon = if_long +ij_c_class_constructor_init_list_wrap = on_every_item +ij_c_copy_is_deep = false +ij_c_create_interface_for_categories = true +ij_c_declare_generated_methods = true +ij_c_description_include_member_names = true +ij_c_discharged_short_ternary_operator = false +ij_c_do_not_add_breaks = false +ij_c_do_while_brace_force = always +ij_c_else_on_new_line = false +ij_c_enum_constants_comma_on_next_line = false +ij_c_enum_constants_wrap = on_every_item +ij_c_for_brace_force = always +ij_c_for_statement_new_line_after_left_paren = false +ij_c_for_statement_right_paren_on_new_line = false +ij_c_for_statement_wrap = on_every_item +ij_c_function_brace_placement = end_of_line +ij_c_function_call_arguments_align_multiline = true +ij_c_function_call_arguments_align_multiline_pars = false +ij_c_function_call_arguments_comma_on_next_line = false +ij_c_function_call_arguments_new_line_after_lpar = false +ij_c_function_call_arguments_new_line_before_rpar = false +ij_c_function_call_arguments_wrap = on_every_item +ij_c_function_non_top_after_return_type_wrap = normal +ij_c_function_parameters_align_multiline = true +ij_c_function_parameters_align_multiline_pars = false +ij_c_function_parameters_comma_on_next_line = false +ij_c_function_parameters_new_line_after_lpar = false +ij_c_function_parameters_new_line_before_rpar = false +ij_c_function_parameters_wrap = on_every_item +ij_c_function_top_after_return_type_wrap = normal +ij_c_generate_additional_eq_operators = true +ij_c_generate_additional_rel_operators = true +ij_c_generate_class_constructor = true +ij_c_generate_comparison_operators_use_std_tie = false +ij_c_generate_instance_variables_for_properties = ask +ij_c_generate_operators_as_members = true +ij_c_header_guard_style_pattern = ${PROJECT_NAME}_${FILE_NAME}_${EXT} +ij_c_if_brace_force = always +ij_c_in_line_short_ternary_operator = true +ij_c_indent_block_comment = true +ij_c_indent_c_struct_members = 4 +ij_c_indent_case_from_switch = true +ij_c_indent_class_members = 4 +ij_c_indent_directive_as_code = false +ij_c_indent_implementation_members = 0 +ij_c_indent_inside_code_block = 4 +ij_c_indent_interface_members = 0 +ij_c_indent_interface_members_except_ivars_block = false +ij_c_indent_namespace_members = 0 +ij_c_indent_preprocessor_directive = 0 +ij_c_indent_visibility_keywords = 1 +ij_c_insert_override = true +ij_c_insert_virtual_with_override = false +ij_c_introduce_auto_vars = false +ij_c_introduce_const_params = false +ij_c_introduce_const_vars = false +ij_c_introduce_generate_property = false +ij_c_introduce_generate_synthesize = true +ij_c_introduce_globals_to_header = true +ij_c_introduce_prop_to_private_category = false +ij_c_introduce_static_consts = true +ij_c_introduce_use_ns_types = false +ij_c_ivars_prefix = _ +ij_c_keep_blank_lines_before_end = 2 +ij_c_keep_blank_lines_before_right_brace = 2 +ij_c_keep_blank_lines_in_code = 2 +ij_c_keep_blank_lines_in_declarations = 2 +ij_c_keep_case_expressions_in_one_line = false +ij_c_keep_control_statement_in_one_line = true +ij_c_keep_directive_at_first_column = true +ij_c_keep_first_column_comment = true +ij_c_keep_line_breaks = true +ij_c_keep_nested_namespaces_in_one_line = false +ij_c_keep_simple_blocks_in_one_line = true +ij_c_keep_simple_methods_in_one_line = true +ij_c_keep_structures_in_one_line = true +ij_c_lambda_capture_list_align_multiline = true +ij_c_lambda_capture_list_align_multiline_bracket = false +ij_c_lambda_capture_list_comma_on_next_line = false +ij_c_lambda_capture_list_new_line_after_lbracket = true +ij_c_lambda_capture_list_new_line_before_rbracket = false +ij_c_lambda_capture_list_wrap = on_every_item +ij_c_line_comment_add_space = false +ij_c_line_comment_at_first_column = true +ij_c_method_brace_placement = end_of_line +ij_c_method_call_arguments_align_by_colons = true +ij_c_method_call_arguments_align_multiline = false +ij_c_method_call_arguments_special_dictionary_pairs_treatment = true +ij_c_method_call_arguments_wrap = off +ij_c_method_call_chain_wrap = on_every_item +ij_c_method_parameters_align_by_colons = true +ij_c_method_parameters_align_multiline = false +ij_c_method_parameters_wrap = off +ij_c_namespace_brace_placement = end_of_line +ij_c_parentheses_expression_new_line_after_left_paren = false +ij_c_parentheses_expression_right_paren_on_new_line = false +ij_c_place_assignment_sign_on_next_line = false +ij_c_property_nonatomic = true +ij_c_put_ivars_to_implementation = true +ij_c_refactor_compatibility_aliases_and_classes = true +ij_c_refactor_properties_and_ivars = true +ij_c_release_style = ivar +ij_c_retain_object_parameters_in_constructor = true +ij_c_semicolon_after_method_signature = false +ij_c_shift_operation_align_multiline = true +ij_c_shift_operation_wrap = normal +ij_c_show_non_virtual_functions = false +ij_c_space_after_colon = true +ij_c_space_after_colon_in_selector = false +ij_c_space_after_comma = true +ij_c_space_after_cup_in_blocks = false +ij_c_space_after_dictionary_literal_colon = true +ij_c_space_after_for_semicolon = true +ij_c_space_after_init_list_colon = true +ij_c_space_after_method_parameter_type_parentheses = false +ij_c_space_after_method_return_type_parentheses = false +ij_c_space_after_pointer_in_declaration = false +ij_c_space_after_quest = true +ij_c_space_after_reference_in_declaration = false +ij_c_space_after_reference_in_rvalue = false +ij_c_space_after_structures_rbrace = true +ij_c_space_after_superclass_colon = true +ij_c_space_after_type_cast = true +ij_c_space_after_visibility_sign_in_method_declaration = true +ij_c_space_before_autorelease_pool_lbrace = true +ij_c_space_before_catch_keyword = true +ij_c_space_before_catch_left_brace = true +ij_c_space_before_catch_parentheses = true +ij_c_space_before_category_parentheses = true +ij_c_space_before_chained_send_message = true +ij_c_space_before_class_left_brace = true +ij_c_space_before_colon = true +ij_c_space_before_comma = false +ij_c_space_before_dictionary_literal_colon = false +ij_c_space_before_do_left_brace = true +ij_c_space_before_else_keyword = true +ij_c_space_before_else_left_brace = true +ij_c_space_before_for_left_brace = true +ij_c_space_before_for_parentheses = true +ij_c_space_before_for_semicolon = false +ij_c_space_before_if_left_brace = true +ij_c_space_before_if_parentheses = true +ij_c_space_before_init_list = true +ij_c_space_before_init_list_colon = true +ij_c_space_before_method_call_parentheses = false +ij_c_space_before_method_left_brace = true +ij_c_space_before_method_parentheses = false +ij_c_space_before_namespace_lbrace = true +ij_c_space_before_pointer_in_declaration = true +ij_c_space_before_property_attributes_parentheses = false +ij_c_space_before_protocols_brackets = true +ij_c_space_before_quest = true +ij_c_space_before_reference_in_declaration = true +ij_c_space_before_superclass_colon = true +ij_c_space_before_switch_left_brace = true +ij_c_space_before_switch_parentheses = true +ij_c_space_before_template_call_lt = false +ij_c_space_before_template_declaration_lt = false +ij_c_space_before_try_left_brace = true +ij_c_space_before_while_keyword = true +ij_c_space_before_while_left_brace = true +ij_c_space_before_while_parentheses = true +ij_c_space_between_adjacent_brackets = false +ij_c_space_between_operator_and_punctuator = false +ij_c_space_within_empty_array_initializer_braces = false +ij_c_spaces_around_additive_operators = true +ij_c_spaces_around_assignment_operators = true +ij_c_spaces_around_bitwise_operators = true +ij_c_spaces_around_equality_operators = true +ij_c_spaces_around_lambda_arrow = true +ij_c_spaces_around_logical_operators = true +ij_c_spaces_around_multiplicative_operators = true +ij_c_spaces_around_pm_operators = false +ij_c_spaces_around_relational_operators = true +ij_c_spaces_around_shift_operators = true +ij_c_spaces_around_unary_operator = false +ij_c_spaces_within_array_initializer_braces = false +ij_c_spaces_within_braces = true +ij_c_spaces_within_brackets = false +ij_c_spaces_within_cast_parentheses = false +ij_c_spaces_within_catch_parentheses = false +ij_c_spaces_within_category_parentheses = false +ij_c_spaces_within_empty_braces = false +ij_c_spaces_within_empty_function_call_parentheses = false +ij_c_spaces_within_empty_function_declaration_parentheses = false +ij_c_spaces_within_empty_lambda_capture_list_bracket = false +ij_c_spaces_within_empty_template_call_ltgt = false +ij_c_spaces_within_empty_template_declaration_ltgt = false +ij_c_spaces_within_for_parentheses = false +ij_c_spaces_within_function_call_parentheses = false +ij_c_spaces_within_function_declaration_parentheses = false +ij_c_spaces_within_if_parentheses = false +ij_c_spaces_within_lambda_capture_list_bracket = false +ij_c_spaces_within_method_parameter_type_parentheses = false +ij_c_spaces_within_method_return_type_parentheses = false +ij_c_spaces_within_parentheses = false +ij_c_spaces_within_property_attributes_parentheses = false +ij_c_spaces_within_protocols_brackets = false +ij_c_spaces_within_send_message_brackets = false +ij_c_spaces_within_switch_parentheses = false +ij_c_spaces_within_template_call_ltgt = false +ij_c_spaces_within_template_declaration_ltgt = false +ij_c_spaces_within_template_double_gt = true +ij_c_spaces_within_while_parentheses = false +ij_c_special_else_if_treatment = true +ij_c_superclass_list_after_colon = never +ij_c_superclass_list_align_multiline = true +ij_c_superclass_list_before_colon = if_long +ij_c_superclass_list_comma_on_next_line = false +ij_c_superclass_list_wrap = on_every_item +ij_c_tag_prefix_of_block_comment = at +ij_c_tag_prefix_of_line_comment = back_slash +ij_c_template_call_arguments_align_multiline = false +ij_c_template_call_arguments_align_multiline_pars = false +ij_c_template_call_arguments_comma_on_next_line = false +ij_c_template_call_arguments_new_line_after_lt = false +ij_c_template_call_arguments_new_line_before_gt = false +ij_c_template_call_arguments_wrap = off +ij_c_template_declaration_function_body_indent = false +ij_c_template_declaration_function_wrap = split_into_lines +ij_c_template_declaration_struct_body_indent = false +ij_c_template_declaration_struct_wrap = split_into_lines +ij_c_template_parameters_align_multiline = false +ij_c_template_parameters_align_multiline_pars = false +ij_c_template_parameters_comma_on_next_line = false +ij_c_template_parameters_new_line_after_lt = false +ij_c_template_parameters_new_line_before_gt = false +ij_c_template_parameters_wrap = off +ij_c_ternary_operation_signs_on_next_line = true +ij_c_ternary_operation_wrap = normal +ij_c_type_qualifiers_placement = before +ij_c_use_modern_casts = true +ij_c_use_setters_in_constructor = true +ij_c_while_brace_force = always +ij_c_while_on_new_line = false +ij_c_wrap_property_declaration = off + +[{*.kts,*.kt}] +ij_kotlin_align_in_columns_case_branch = false +ij_kotlin_align_multiline_binary_operation = false +ij_kotlin_align_multiline_extends_list = false +ij_kotlin_align_multiline_method_parentheses = false +ij_kotlin_align_multiline_parameters = true +ij_kotlin_align_multiline_parameters_in_calls = false +ij_kotlin_assignment_wrap = off +ij_kotlin_blank_lines_after_class_header = 0 +ij_kotlin_blank_lines_around_block_when_branches = 0 +ij_kotlin_block_comment_at_first_column = true +ij_kotlin_call_parameters_new_line_after_left_paren = false +ij_kotlin_call_parameters_right_paren_on_new_line = false +ij_kotlin_call_parameters_wrap = off +ij_kotlin_catch_on_new_line = false +ij_kotlin_class_annotation_wrap = split_into_lines +ij_kotlin_continuation_indent_for_chained_calls = true +ij_kotlin_continuation_indent_for_expression_bodies = true +ij_kotlin_continuation_indent_in_argument_lists = true +ij_kotlin_continuation_indent_in_elvis = true +ij_kotlin_continuation_indent_in_if_conditions = true +ij_kotlin_continuation_indent_in_parameter_lists = true +ij_kotlin_continuation_indent_in_supertype_lists = true +ij_kotlin_else_on_new_line = false +ij_kotlin_enum_constants_wrap = off +ij_kotlin_extends_list_wrap = off +ij_kotlin_field_annotation_wrap = split_into_lines +ij_kotlin_finally_on_new_line = false +ij_kotlin_if_rparen_on_new_line = false +ij_kotlin_import_nested_classes = false +ij_kotlin_insert_whitespaces_in_simple_one_line_method = true +ij_kotlin_keep_blank_lines_before_right_brace = 2 +ij_kotlin_keep_blank_lines_in_code = 2 +ij_kotlin_keep_blank_lines_in_declarations = 2 +ij_kotlin_keep_first_column_comment = true +ij_kotlin_keep_indents_on_empty_lines = false +ij_kotlin_keep_line_breaks = true +ij_kotlin_lbrace_on_next_line = false +ij_kotlin_line_comment_add_space = false +ij_kotlin_line_comment_at_first_column = true +ij_kotlin_method_annotation_wrap = split_into_lines +ij_kotlin_method_call_chain_wrap = off +ij_kotlin_method_parameters_new_line_after_left_paren = false +ij_kotlin_method_parameters_right_paren_on_new_line = false +ij_kotlin_method_parameters_wrap = off +ij_kotlin_name_count_to_use_star_import = 5 +ij_kotlin_name_count_to_use_star_import_for_members = 3 +ij_kotlin_parameter_annotation_wrap = off +ij_kotlin_space_after_comma = true +ij_kotlin_space_after_extend_colon = true +ij_kotlin_space_after_type_colon = true +ij_kotlin_space_before_catch_parentheses = true +ij_kotlin_space_before_comma = false +ij_kotlin_space_before_extend_colon = true +ij_kotlin_space_before_for_parentheses = true +ij_kotlin_space_before_if_parentheses = true +ij_kotlin_space_before_lambda_arrow = true +ij_kotlin_space_before_type_colon = false +ij_kotlin_space_before_when_parentheses = true +ij_kotlin_space_before_while_parentheses = true +ij_kotlin_spaces_around_additive_operators = true +ij_kotlin_spaces_around_assignment_operators = true +ij_kotlin_spaces_around_equality_operators = true +ij_kotlin_spaces_around_function_type_arrow = true +ij_kotlin_spaces_around_logical_operators = true +ij_kotlin_spaces_around_multiplicative_operators = true +ij_kotlin_spaces_around_range = false +ij_kotlin_spaces_around_relational_operators = true +ij_kotlin_spaces_around_unary_operator = false +ij_kotlin_spaces_around_when_arrow = true +ij_kotlin_variable_annotation_wrap = off +ij_kotlin_while_on_new_line = false +ij_kotlin_wrap_elvis_expressions = 1 +ij_kotlin_wrap_expression_body_functions = 0 +ij_kotlin_wrap_first_method_in_call_chain = false + +[{CMakeLists.txt,*.cmake}] +ij_cmake_align_multiline_parameters_in_calls = false +ij_cmake_force_commands_case = 2 +ij_cmake_keep_blank_lines_in_code = 2 +ij_cmake_space_before_for_parentheses = true +ij_cmake_space_before_if_parentheses = true +ij_cmake_space_before_method_call_parentheses = false +ij_cmake_space_before_method_parentheses = false +ij_cmake_space_before_while_parentheses = true +ij_cmake_spaces_within_for_parentheses = false +ij_cmake_spaces_within_if_parentheses = false +ij_cmake_spaces_within_method_call_parentheses = false +ij_cmake_spaces_within_method_parentheses = false +ij_cmake_spaces_within_while_parentheses = false + +[{*.mkd,*.markdown,*.md}] +max_line_length = 72 +ij_wrap_on_typing = false +ij_markdown_abbreviations_placement = 0 +ij_markdown_abbreviations_sort = 0 +ij_markdown_attribute_class = 0 +ij_markdown_attribute_equal_space = 0 +ij_markdown_attribute_id = 0 +ij_markdown_attribute_value_quotes = 0 +ij_markdown_attributes_combine_consecutive = false +ij_markdown_attributes_sort = false +ij_markdown_attributes_spaces = 0 +ij_markdown_atx_header_trailing_marker = 0 +ij_markdown_block_quote_markers = 0 +ij_markdown_bullet_list_item_marker = 0 +ij_markdown_code_fence_marker_length = 3 +ij_markdown_code_fence_marker_type = 0 +ij_markdown_code_fence_match_closing_marker = false +ij_markdown_code_fence_minimize_indent = false +ij_markdown_code_fence_space_before_info = false +ij_markdown_code_keep_trailing_spaces = 0 +ij_markdown_definition_marker_spaces = 3 +ij_markdown_definition_marker_type = 0 +ij_markdown_enumerated_reference_format_placement = 0 +ij_markdown_enumerated_reference_format_sort = 0 +ij_markdown_escape_numbered_lead_in_on_wrap = true +ij_markdown_escape_special_chars_on_wrap = true +ij_markdown_footnote_placement = 0 +ij_markdown_footnote_sort = 0 +ij_markdown_format_with_soft_wrap = 0 +ij_markdown_heading_preference = 0 +ij_markdown_keep_at_start_explicit_link = 0 +ij_markdown_keep_at_start_image_links = 0 +ij_markdown_keep_blank_lines = 2 +ij_markdown_keep_trailing_spaces = 1 +ij_markdown_list_add_blank_line_before = false +ij_markdown_list_align_numeric = 0 +ij_markdown_list_ordered_task_item_priority = 1 +ij_markdown_list_renumber_items = true +ij_markdown_list_reset_first_item_number = false +ij_markdown_list_spacing = 0 +ij_markdown_macro_placement = 0 +ij_markdown_macro_sort = 0 +ij_markdown_new_bullet_list_item_marker = 1 +ij_markdown_para_wrap_text = true +ij_markdown_reference_placement = 0 +ij_markdown_reference_sort = 0 +ij_markdown_right_margin = 72 +ij_markdown_setext_header_equalize_marker = true +ij_markdown_smart_edit_atx_header = true +ij_markdown_smart_edit_setext_header = true +ij_markdown_smart_edit_table_separator_line = true +ij_markdown_smart_edit_tables = false +ij_markdown_smart_enter_atx_header = true +ij_markdown_smart_enter_setext_header = true +ij_markdown_space_after_atx_marker = 1 +ij_markdown_tab_size = 4 +ij_markdown_table_adjust_column_width = true +ij_markdown_table_apply_column_alignment = true +ij_markdown_table_caption = 0 +ij_markdown_table_caption_spaces = 0 +ij_markdown_table_fill_missing_columns = true +ij_markdown_table_lead_trail_pipes = true +ij_markdown_table_left_align_marker = 1 +ij_markdown_table_space_around_pipe = true +ij_markdown_table_trim_cells = false +ij_markdown_task_list_item_case = 0 +ij_markdown_task_list_item_placement = 0 +ij_markdown_toc_format_on_save = false +ij_markdown_toc_generate_html = false +ij_markdown_toc_generate_numbered_list = false +ij_markdown_toc_generate_structure = 0 +ij_markdown_toc_generate_text_only = false +ij_markdown_toc_heading_levels = 12 +ij_markdown_toc_title = Table of Contents +ij_markdown_toc_title_level = 1 +ij_markdown_toc_update_on_doc_format = 1 +ij_markdown_trailing_spaces_option_1 = 0 +ij_markdown_trailing_spaces_option_10 = 0 +ij_markdown_trailing_spaces_option_11 = 0 +ij_markdown_trailing_spaces_option_12 = 0 +ij_markdown_trailing_spaces_option_13 = 0 +ij_markdown_trailing_spaces_option_14 = 0 +ij_markdown_trailing_spaces_option_15 = 0 +ij_markdown_trailing_spaces_option_16 = 0 +ij_markdown_trailing_spaces_option_17 = 0 +ij_markdown_trailing_spaces_option_18 = 0 +ij_markdown_trailing_spaces_option_19 = 0 +ij_markdown_trailing_spaces_option_2 = 0 +ij_markdown_trailing_spaces_option_20 = 0 +ij_markdown_trailing_spaces_option_3 = 0 +ij_markdown_trailing_spaces_option_4 = 0 +ij_markdown_trailing_spaces_option_5 = 0 +ij_markdown_trailing_spaces_option_6 = 0 +ij_markdown_trailing_spaces_option_7 = 0 +ij_markdown_trailing_spaces_option_8 = 0 +ij_markdown_trailing_spaces_option_9 = 0 +ij_markdown_unescape_special_chars_on_wrap = true +ij_markdown_use_actual_char_width = true +ij_markdown_verbatim_minimize_indent = false + +[{*.zsh,*.bash,*.sh}] +indent_size = 2 +tab_width = 2 +ij_shell_binary_ops_start_line = false +ij_shell_keep_column_alignment_padding = false +ij_shell_minify_program = false +ij_shell_redirect_followed_by_space = false +ij_shell_switch_cases_indented = false diff --git a/README.md b/README.md index 34dd3c3..45ea292 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ Clone the repository and **initialise the submodules** with `git submodule updat #### Oculus Mobile SDK - Download the [latest version](https://developer.oculus.com/downloads/package/oculus-mobile-sdk/) -(**Oculus Mobile SDK 17.0** (1.34.0) or higher) of the Oculus Mobile SDK and extract it into the +(**Oculus Mobile SDK 19.0** (1.36.0) or higher) of the Oculus Mobile SDK and extract it into the `plugin/libs/ovr_sdk_mobile` directory (create the directory if it doesn't exist). - If you change the default install location, update the `OVR_ROOT_DIR` cmake variable in the the `plugin/CMakeLists.txt` build file to point to the Oculus Mobile SDK install location. @@ -69,7 +69,8 @@ Clone the repository and **initialise the submodules** with `git submodule updat - Navigate to the `plugin/libs/godot-cpp` directory and follow [these steps](https://github.com/GodotNativeTools/godot-cpp/tree/master#compiling-the-cpp-bindings-library) to generate the cpp bindings. #### Android SDK & NDK -- Download and setup [Android Studio version **4.0** or higher](https://developer.android.com/studio). +- Download and setup + [Android Studio version **4.1** or higher](https://developer.android.com/studio). - After setup, ensure you have the latest versions by checking the [SDK Manager](https://developer.android.com/studio/intro/update.html#sdk-manager) for updates. - Set the environment variable `ANDROID_HOME` to the Android SDK location. - Follow the instructions [here](https://developer.android.com/studio/projects/install-ndk#specific-version) and install version **21.0.6113669** of the NDK. diff --git a/build.gradle.kts b/build.gradle similarity index 69% rename from build.gradle.kts rename to build.gradle index 0cd1926..3ea115c 100644 --- a/build.gradle.kts +++ b/build.gradle @@ -1,19 +1,15 @@ -apply(from = "config.gradle.kts") +apply from: 'config.gradle' buildscript { - apply(from = "config.gradle.kts") - - val kotlinVersion: String by extra - val gradlePluginVersion: String by extra + apply from: 'config.gradle' repositories { google() jcenter() - } dependencies { - classpath("com.android.tools.build:gradle:$gradlePluginVersion") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") + classpath "com.android.tools.build:gradle:$versions.gradlePluginVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$versions.kotlinVersion" } } @@ -21,23 +17,24 @@ allprojects { repositories { google() jcenter() - } } -val outputDir = "build/outputs" +def outputDir = "build/outputs" + +task clean(type: Delete) { + dependsOn(":OVRMobile:clean") -tasks.register("clean") { delete(rootProject.buildDir) - // Delete the contents of the outputs directory. + // Delete the contents of the outputs directory delete(outputDir) } /** * Generate the plugin binaries. */ -tasks.register("generatePluginBinary") { +task generatePluginBinary(type: Copy) { dependsOn(":OVRMobile:assembleDebug") dependsOn(":OVRMobile:assembleRelease") from("plugin/build/outputs/aar") @@ -48,7 +45,7 @@ tasks.register("generatePluginBinary") { * Generate the plugin native shared libraries. * This is mostly to be used by maintainers to update the https://github.com/GodotVR/godot-oculus-mobile-asset repo. */ -tasks.register("generateSharedLibs") { +task generateSharedLibs(type: Copy) { dependsOn(":OVRMobile:externalNativeBuildDebug") dependsOn(":OVRMobile:externalNativeBuildRelease") diff --git a/config.gradle b/config.gradle new file mode 100644 index 0000000..855b9ed --- /dev/null +++ b/config.gradle @@ -0,0 +1,8 @@ +ext.versions = [ + gradlePluginVersion: '4.1.0', + compileSdk : 30, + minSdk : 18, + targetSdk : 30, + buildTools : '30.0.1', + kotlinVersion : '1.4.10', +] diff --git a/config.gradle.kts b/config.gradle.kts deleted file mode 100644 index 7b88633..0000000 --- a/config.gradle.kts +++ /dev/null @@ -1,7 +0,0 @@ -val kotlinVersion by extra("1.3.72") -val gradlePluginVersion by extra("4.0.0") - -val compileSdk by extra(29) -val buildTools by extra("29.0.3") -val minSdk by extra(18) -val targetSdk by extra(29) diff --git a/demo/addons/godot_ovrmobile/example_scenes/arvr_origin.gd b/demo/addons/godot_ovrmobile/example_scenes/arvr_origin.gd index 656bf8e..5ed651c 100644 --- a/demo/addons/godot_ovrmobile/example_scenes/arvr_origin.gd +++ b/demo/addons/godot_ovrmobile/example_scenes/arvr_origin.gd @@ -13,7 +13,7 @@ var ovr_init_config = null; # the other APIs are available during runtime var ovr_performance = null; -var ovr_display_refresh_rate = null; +var ovr_display = null; var ovr_vr_api_proxy = null; # some of the Oculus VrAPI constants are defined in this file. Have a look into it to learn more @@ -51,14 +51,22 @@ func _initialize_ovr_mobile_arvr_interface(): Engine.iterations_per_second = 72 # Quest # load the .gdns classes. - ovr_display_refresh_rate = load("res://addons/godot_ovrmobile/OvrDisplayRefreshRate.gdns"); + ovr_display = load("res://addons/godot_ovrmobile/OvrDisplay.gdns"); ovr_performance = load("res://addons/godot_ovrmobile/OvrPerformance.gdns"); ovr_vr_api_proxy = load("res://addons/godot_ovrmobile/OvrVrApiProxy.gdns"); # and now instance the .gdns classes for use if load was successfull - if (ovr_display_refresh_rate): ovr_display_refresh_rate = ovr_display_refresh_rate.new() - if (ovr_performance): ovr_performance = ovr_performance.new() - if (ovr_vr_api_proxy): ovr_vr_api_proxy = ovr_vr_api_proxy.new() + if (ovr_display): + ovr_display = ovr_display.new() + # Get the list of supported display refresh rates. + print("Display refresh rates: " + str(ovr_display.get_supported_display_refresh_rates())) + # Get the device color space + print("Device color space: " + str(ovr_display.get_color_space())) + + if (ovr_performance): + ovr_performance = ovr_performance.new() + if (ovr_vr_api_proxy): + ovr_vr_api_proxy = ovr_vr_api_proxy.new() # Connect to the plugin signals _connect_to_signals() diff --git a/demo/addons/godot_ovrmobile/example_scenes/arvr_origin.tscn b/demo/addons/godot_ovrmobile/example_scenes/arvr_origin.tscn index 6132353..3887aa0 100644 --- a/demo/addons/godot_ovrmobile/example_scenes/arvr_origin.tscn +++ b/demo/addons/godot_ovrmobile/example_scenes/arvr_origin.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=7 format=2] +[gd_scene load_steps=8 format=2] [ext_resource path="res://addons/godot_ovrmobile/example_scenes/touch_controller.dae" type="PackedScene" id=1] [ext_resource path="res://addons/godot_ovrmobile/example_scenes/left_hand_model.glb" type="PackedScene" id=2] @@ -6,6 +6,7 @@ [ext_resource path="res://addons/godot_ovrmobile/example_scenes/arvr_origin.gd" type="Script" id=4] [ext_resource path="res://addons/godot_ovrmobile/example_scenes/oculus_touch_controller.gd" type="Script" id=5] [ext_resource path="res://addons/godot_ovrmobile/example_scenes/oculus_hand_tracker.gd" type="Script" id=6] +[ext_resource path="res://addons/godot_ovrmobile/example_scenes/hand_pointer.tscn" type="PackedScene" id=7] [node name="ARVROrigin" type="ARVROrigin"] script = ExtResource( 4 ) @@ -34,12 +35,18 @@ script = ExtResource( 6 ) [node name="HandModel" parent="LeftHand" instance=ExtResource( 2 )] +[node name="HandPointer" parent="LeftHand/HandModel" instance=ExtResource( 7 )] +visible = false + [node name="RightHand" type="ARVRController" parent="."] transform = Transform( 1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0.346606, 1.72656, -0.4 ) controller_id = 2 script = ExtResource( 6 ) [node name="HandModel" parent="RightHand" instance=ExtResource( 3 )] + +[node name="HandPointer" parent="RightHand/HandModel" instance=ExtResource( 7 )] +visible = false [connection signal="button_pressed" from="LeftTouchController" to="LeftTouchController" method="_on_LeftTouchController_button_pressed"] [connection signal="button_pressed" from="RightTouchController" to="RightTouchController" method="_on_RightTouchController_button_pressed"] [connection signal="button_release" from="RightTouchController" to="RightTouchController" method="_on_RightTouchController_button_release"] diff --git a/demo/addons/godot_ovrmobile/example_scenes/hand_pointer.tscn b/demo/addons/godot_ovrmobile/example_scenes/hand_pointer.tscn new file mode 100644 index 0000000..6e025eb --- /dev/null +++ b/demo/addons/godot_ovrmobile/example_scenes/hand_pointer.tscn @@ -0,0 +1,28 @@ +[gd_scene load_steps=5 format=2] + +[ext_resource path="res://addons/godot_ovrmobile/example_scenes/ray_cast_with_reticle.gd" type="Script" id=1] +[ext_resource path="res://addons/godot_ovrmobile/example_scenes/ray_reticle.tscn" type="PackedScene" id=2] + +[sub_resource type="SpatialMaterial" id=1] + +[sub_resource type="CylinderMesh" id=2] +material = SubResource( 1 ) +top_radius = 0.001 +bottom_radius = 0.01 +height = 0.05 + +[node name="HandPointer" type="Spatial"] + +[node name="RayCast" type="RayCast" parent="." groups=[ +"gast_ray_caster", +]] +enabled = true +cast_to = Vector3( 0, 0, -4 ) +script = ExtResource( 1 ) + +[node name="RayReticle" parent="RayCast" instance=ExtResource( 2 )] + +[node name="PointerModel" type="MeshInstance" parent="."] +transform = Transform( 1, 0, 0, 0, -1.62921e-07, 1, 0, -1, -1.62921e-07, 0, 0, -0.03 ) +mesh = SubResource( 2 ) +material/0 = null diff --git a/demo/addons/godot_ovrmobile/example_scenes/oculus_hand_tracker.gd b/demo/addons/godot_ovrmobile/example_scenes/oculus_hand_tracker.gd index 2fce1cc..66bc1a9 100644 --- a/demo/addons/godot_ovrmobile/example_scenes/oculus_hand_tracker.gd +++ b/demo/addons/godot_ovrmobile/example_scenes/oculus_hand_tracker.gd @@ -40,6 +40,7 @@ Quat(-0.081241, -0.013242, 0.560496, 0.824056), Quat(0.00276, 0.037404, 0.637818 var _t = 0.0 onready var hand_model : Spatial = $HandModel +onready var hand_pointer : Spatial = $HandModel/HandPointer func _ready(): _initialize_hands() @@ -53,6 +54,7 @@ func _ready(): func _process(delta_t): _update_hand_model(hand_model, hand_skel); + _update_hand_pointer(hand_pointer) # If we are on desktop or don't have hand tracking we set a debug pose on the left hand if (controller_id == LEFT_TRACKER_ID && !ovr_hand_tracking): @@ -111,6 +113,15 @@ func _update_hand_model(model : Spatial, skel: Skeleton): return false; +func _update_hand_pointer(model: Spatial): + if (ovr_hand_tracking): # check if the hand tracking API was loaded + if (ovr_hand_tracking.is_pointer_pose_valid(controller_id)): + model.visible = true + model.global_transform = ovr_hand_tracking.get_pointer_pose(controller_id) + else: + model.visible = false + + func _on_LeftHand_pinch_pressed(button): if (button == FINGER_PINCH.INDEX_PINCH): print("Left Index Pinching"); if (button == FINGER_PINCH.MIDDLE_PINCH): diff --git a/demo/addons/godot_ovrmobile/example_scenes/ray_cast_with_reticle.gd b/demo/addons/godot_ovrmobile/example_scenes/ray_cast_with_reticle.gd new file mode 100644 index 0000000..43c4dcf --- /dev/null +++ b/demo/addons/godot_ovrmobile/example_scenes/ray_cast_with_reticle.gd @@ -0,0 +1,9 @@ +extends RayCast + +onready var ray_reticle = $RayReticle + +func _physics_process(delta): + ray_reticle.visible = is_colliding() + if (ray_reticle.visible): + ray_reticle.translation = to_local(get_collision_point()) + diff --git a/demo/addons/godot_ovrmobile/example_scenes/ray_reticle.tscn b/demo/addons/godot_ovrmobile/example_scenes/ray_reticle.tscn new file mode 100644 index 0000000..c941345 --- /dev/null +++ b/demo/addons/godot_ovrmobile/example_scenes/ray_reticle.tscn @@ -0,0 +1,13 @@ +[gd_scene load_steps=3 format=2] + +[sub_resource type="SpatialMaterial" id=1] +albedo_color = Color( 1, 1, 1, 0.75 ) + +[sub_resource type="SphereMesh" id=2] +material = SubResource( 1 ) +radius = 0.02 +height = 0.04 + +[node name="RayReticle" type="MeshInstance"] +mesh = SubResource( 2 ) +material/0 = null diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ef7f3f0..6854969 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Jun 03 16:52:10 PDT 2020 +#Wed Sep 23 18:33:41 PDT 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index 19ed27b..bbaf9e1 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -46,7 +46,7 @@ set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) -project(godot_ovrmobile) +project(godot_ovrmobile VERSION 2.0.0) ############################################################################### ## PROJECT SETUP diff --git a/plugin/build.gradle b/plugin/build.gradle index 8bdd738..8c25eec 100644 --- a/plugin/build.gradle +++ b/plugin/build.gradle @@ -2,14 +2,15 @@ apply plugin: "com.android.library" apply plugin: "kotlin-android" android { - compileSdkVersion compileSdk - buildToolsVersion = buildTools + buildToolsVersion = versions.buildTools + compileSdkVersion versions.compileSdk + ndkVersion "21.1.6352462" defaultConfig { - minSdkVersion minSdk - targetSdkVersion targetSdk - versionCode 2 - versionName '2.0.0' + minSdkVersion versions.minSdk + targetSdkVersion versions.targetSdk + versionCode 3 + versionName '2.1.0' setProperty("archivesBaseName", "gdovrmobile.${versionName}") externalNativeBuild { @@ -23,8 +24,6 @@ android { } } - ndkVersion "21.0.6113669" - externalNativeBuild { cmake { path "CMakeLists.txt" @@ -35,10 +34,20 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + + buildFeatures { + prefabPublishing true + } + + prefab { + godot_ovrmobile { + headers "src/main/cpp" + } + } } dependencies { - implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion") + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:$versions.kotlinVersion") if (rootProject.findProject(":godot:lib") != null) { compileOnly(project(":godot:lib")) } else { diff --git a/plugin/gdovrmobile.gdap b/plugin/gdovrmobile.gdap index f031fab..08b3a0b 100644 --- a/plugin/gdovrmobile.gdap +++ b/plugin/gdovrmobile.gdap @@ -2,4 +2,4 @@ name="OVRMobile" binary_type="local" -binary="gdovrmobile.2.0.0-release.aar" +binary="gdovrmobile.2.1.0-release.aar" diff --git a/plugin/libs/godot-lib.3.2.2.stable.release.aar b/plugin/libs/godot-lib.3.2.3.stable.release.aar similarity index 77% rename from plugin/libs/godot-lib.3.2.2.stable.release.aar rename to plugin/libs/godot-lib.3.2.3.stable.release.aar index 62503c1..09af8e7 100644 Binary files a/plugin/libs/godot-lib.3.2.2.stable.release.aar and b/plugin/libs/godot-lib.3.2.3.stable.release.aar differ diff --git a/plugin/src/main/assets/addons/godot_ovrmobile/OvrDisplayRefreshRate.gdns b/plugin/src/main/assets/addons/godot_ovrmobile/OvrDisplay.gdns similarity index 72% rename from plugin/src/main/assets/addons/godot_ovrmobile/OvrDisplayRefreshRate.gdns rename to plugin/src/main/assets/addons/godot_ovrmobile/OvrDisplay.gdns index 503138b..5f352bc 100644 --- a/plugin/src/main/assets/addons/godot_ovrmobile/OvrDisplayRefreshRate.gdns +++ b/plugin/src/main/assets/addons/godot_ovrmobile/OvrDisplay.gdns @@ -3,6 +3,6 @@ [ext_resource path="res://addons/godot_ovrmobile/godot_ovrmobile.gdnlib" type="GDNativeLibrary" id=1] [resource] -resource_name = "OvrDisplayRefreshRate" -class_name = "OvrDisplayRefreshRate" +resource_name = "OvrDisplay" +class_name = "OvrDisplay" library = ExtResource( 1 ) diff --git a/plugin/src/main/cpp/api/api_common.h b/plugin/src/main/cpp/api/api_common.h index 28d1a23..7027d2d 100644 --- a/plugin/src/main/cpp/api/api_common.h +++ b/plugin/src/main/cpp/api/api_common.h @@ -1,33 +1,56 @@ /** -* Created by Fredia Huya-Kouadio. -*/ + * Created by Fredia Huya-Kouadio. + */ #ifndef API_COMMON_H #define API_COMMON_H namespace ovrmobile { - // Checks that the ovr mobile session is valid and initialized prior to running the requested logic. - template - inline T check_session_initialized(OvrMobileSession *session, TrueFunc true_branch, - FalseFunc false_branch) { - if (session && session->is_initialized()) { - return true_branch(); - } else { - return false_branch(); - } +// Checks that the ovr mobile session is valid and initialized prior to running the requested logic. +template +inline T check_session_initialized(OvrMobileSession *session, TrueFunc true_branch) { + if (session && session->is_initialized()) { + return true_branch(); + } else { + return T{}; } +} - // Checks that the ovr mobile session is valid and NOT initialized prior to running the requested logic. - template - inline T check_session_not_initialized(OvrMobileSession *session, TrueFunc true_branch, - FalseFunc false_branch) { - if (session && !session->is_initialized()) { - return true_branch(); - } else { - return false_branch(); - } +// Checks that the ovr mobile session is valid and initialized prior to running the requested logic. +template +inline T +check_session_initialized(OvrMobileSession *session, TrueFunc true_branch, FalseFunc false_branch) { + if (session && session->is_initialized()) { + return true_branch(); + } else { + return false_branch(); } +} + +// Checks that the ovr mobile session is valid and NOT initialized prior to running the requested +// logic. +template +inline T check_session_not_initialized(OvrMobileSession *session, TrueFunc true_branch) { + if (session && !session->is_initialized()) { + return true_branch(); + } else { + return T{}; + } +} + +// Checks that the ovr mobile session is valid and NOT initialized prior to running the requested +// logic. +template +inline T check_session_not_initialized(OvrMobileSession *session, + TrueFunc true_branch, + FalseFunc false_branch) { + if (session && !session->is_initialized()) { + return true_branch(); + } else { + return false_branch(); + } +} } // namespace ovrmobile diff --git a/plugin/src/main/cpp/api/ovr_display.cpp b/plugin/src/main/cpp/api/ovr_display.cpp new file mode 100644 index 0000000..168cc03 --- /dev/null +++ b/plugin/src/main/cpp/api/ovr_display.cpp @@ -0,0 +1,60 @@ +// +// Created by fhuya on 9/24/2020. +// + +#include "ovr_display.h" +#include "api_common.h" + +namespace ovrmobile { +OvrDisplay::OvrDisplay() {} + +OvrDisplay::~OvrDisplay() {} + +void OvrDisplay::_init() {} + +void OvrDisplay::_register_methods() { + register_method("set_color_space", &OvrDisplay::set_color_space); + register_method("get_color_space", &OvrDisplay::get_color_space); + register_method("set_display_refresh_rate", &OvrDisplay::set_display_refresh_rate); + register_method("get_supported_display_refresh_rates", + &OvrDisplay::get_supported_display_refresh_rates); +} + +bool set_color_space(OvrMobileSession *session, ovrColorSpace color_space) { + return check_session_initialized(session, [&]() { + ovrHmdColorDesc hmd_color_desc = {}; + hmd_color_desc.ColorSpace = color_space; + + ovrResult result = + vrapi_SetClientColorDesc(session->get_ovr_mobile_context(), &hmd_color_desc); + return result == ovrSuccess; + }); +} + +ovrColorSpace get_color_space(OvrMobileSession *session) { + return check_session_initialized(session, [&]() { + return vrapi_GetHmdColorDesc(session->get_ovr_mobile_context()).ColorSpace; + }); +} + +std::vector get_supported_display_refresh_rates(OvrMobileSession *session) { + return check_session_initialized>(session, [&]() { + const int refresh_rates_count = vrapi_GetSystemPropertyInt( + session->get_ovr_java(), VRAPI_SYS_PROP_NUM_SUPPORTED_DISPLAY_REFRESH_RATES); + std::vector supported_refresh_rates(refresh_rates_count, 0.0F); + vrapi_GetSystemPropertyFloatArray(session->get_ovr_java(), + VRAPI_SYS_PROP_SUPPORTED_DISPLAY_REFRESH_RATES, + supported_refresh_rates.data(), + refresh_rates_count); + + return supported_refresh_rates; + }); +} + +bool set_display_refresh_rate(OvrMobileSession *session, float refresh_rate) { + return check_session_initialized(session, [&]() { + return vrapi_SetDisplayRefreshRate(session->get_ovr_mobile_context(), refresh_rate) == + ovrSuccess; + }); +} +} // namespace ovrmobile diff --git a/plugin/src/main/cpp/api/ovr_display.h b/plugin/src/main/cpp/api/ovr_display.h new file mode 100644 index 0000000..3c131be --- /dev/null +++ b/plugin/src/main/cpp/api/ovr_display.h @@ -0,0 +1,66 @@ +#ifndef GODOT_OCULUS_MOBILE_PLUGIN_OVR_DISPLAY_H +#define GODOT_OCULUS_MOBILE_PLUGIN_OVR_DISPLAY_H + +#include "ovr_mobile_session.h" +#include +#include + +namespace ovrmobile { +namespace { +using namespace godot; +} + +/// Utility method to update the device color space +/// For more info, see https://developer.oculus.com/documentation/native/android/mobile-colorspace/ +bool set_color_space(OvrMobileSession *session, ovrColorSpace color_space); + +/// Utility method to retrieve the device color space. +/// This is a constant for each device type. +/// See https://developer.oculus.com/documentation/native/android/mobile-colorspace/ +ovrColorSpace get_color_space(OvrMobileSession *session); + +/// Utility method to update the device display refresh rate. +bool set_display_refresh_rate(OvrMobileSession *session, float refresh_rate); + +/// Utility method to access the display refresh rates supported by the device. +std::vector get_supported_display_refresh_rates(OvrMobileSession *session); + +class OvrDisplay : public Reference { + GODOT_CLASS(OvrDisplay, Reference) + + public: + OvrDisplay(); + + ~OvrDisplay(); + + static void _register_methods(); + + void _init(); + + private: + inline bool set_color_space(uint color_space) { + return ovrmobile::set_color_space(OvrMobileSession::get_singleton_instance(), + static_cast(color_space)); + } + + inline uint get_color_space() { + return ovrmobile::get_color_space(OvrMobileSession::get_singleton_instance()); + } + + inline bool set_display_refresh_rate(float refresh_rate) { + return ovrmobile::set_display_refresh_rate(OvrMobileSession::get_singleton_instance(), + refresh_rate); + } + + inline Array get_supported_display_refresh_rates() { + std::vector refresh_rates = ovrmobile::get_supported_display_refresh_rates( + OvrMobileSession::get_singleton_instance()); + Array refresh_rates_array; + for (int i = 0; i < refresh_rates.size(); i++) { + refresh_rates_array.append(refresh_rates[i]); + } + return refresh_rates_array; + } +}; +} // namespace ovrmobile +#endif // GODOT_OCULUS_MOBILE_PLUGIN_OVR_DISPLAY_H diff --git a/plugin/src/main/cpp/api/ovr_display_refresh_rate.cpp b/plugin/src/main/cpp/api/ovr_display_refresh_rate.cpp deleted file mode 100644 index 7e5f201..0000000 --- a/plugin/src/main/cpp/api/ovr_display_refresh_rate.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "ovr_display_refresh_rate.h" -#include "api_common.h" - -namespace ovrmobile { - - std::vector get_supported_display_refresh_rates(OvrMobileSession *session) { - return check_session_initialized>(session, [&]() { - const int refresh_rates_count = vrapi_GetSystemPropertyInt( - session->get_ovr_java(), - VRAPI_SYS_PROP_NUM_SUPPORTED_DISPLAY_REFRESH_RATES); - std::vector supported_refresh_rates(refresh_rates_count, 0.0F); - vrapi_GetSystemPropertyFloatArray(session->get_ovr_java(), - VRAPI_SYS_PROP_SUPPORTED_DISPLAY_REFRESH_RATES, - supported_refresh_rates.data(), refresh_rates_count); - - return supported_refresh_rates; - }, []() { return std::vector(); }); - } - - bool set_display_refresh_rate(OvrMobileSession *session, float refresh_rate) { - return check_session_initialized(session, [&]() { - return vrapi_SetDisplayRefreshRate(session->get_ovr_mobile_context(), - refresh_rate) == ovrSuccess; - }, []() { return false; }); - - } - -} // namespace ovrmobile \ No newline at end of file diff --git a/plugin/src/main/cpp/api/ovr_display_refresh_rate.h b/plugin/src/main/cpp/api/ovr_display_refresh_rate.h deleted file mode 100644 index 216a870..0000000 --- a/plugin/src/main/cpp/api/ovr_display_refresh_rate.h +++ /dev/null @@ -1,21 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////////////////////// -// Implements the section of the Oculus runtime api. - -#ifndef OVR_DISPLAY_REFRESH_RATE_H -#define OVR_DISPLAY_REFRESH_RATE_H - -#include - -#include "VrApi_Types.h" -#include "ovr_mobile_session.h" - -namespace ovrmobile { - // Implements VrApi.h: ovrResult vrapi_SetDisplayRefreshRate(ovrMobile * ovr, const float refreshRate); - bool set_display_refresh_rate(OvrMobileSession *session, float refresh_rate); - - // Utility method to access the display refresh rates supported by the device. - std::vector get_supported_display_refresh_rates(OvrMobileSession *session); - -} // namespace ovrmobile - -#endif // OVR_DISPLAY_REFRESH_RATE_H diff --git a/plugin/src/main/cpp/api/ovr_input.cpp b/plugin/src/main/cpp/api/ovr_input.cpp index 404d659..5f11089 100644 --- a/plugin/src/main/cpp/api/ovr_input.cpp +++ b/plugin/src/main/cpp/api/ovr_input.cpp @@ -11,35 +11,49 @@ void OvrInput::_init() {} void OvrInput::_register_methods() { register_method("get_primary_controller_id", &OvrInput::get_primary_controller_id); + register_method("get_primary_controller_type", &OvrInput::get_primary_controller_type); } -int OvrInput::get_primary_controller_id() { - return ovrmobile::get_primary_controller_id(OvrMobileSession::get_singleton_instance()); -} - -bool vibrate_controller(OvrMobileSession* session, +bool vibrate_controller(OvrMobileSession *session, int controller_id, int duration_in_ms, float intensity) { return check_session_initialized(session, [&]() { - bool result = false; - OvrMobileController* controller = session->get_ovr_mobile_controller(); - if (controller) { - controller->vibrate_controller(controller_id, duration_in_ms, intensity); - result = true; - } - return result; - }, []() { return false; }); + bool result = false; + OvrMobileController *controller = session->get_ovr_mobile_controller(); + if (controller) { + controller->vibrate_controller(controller_id, duration_in_ms, intensity); + result = true; + } + return result; + }); +} + +int get_primary_controller_id(OvrMobileSession *session) { + return check_session_initialized( + session, + [&]() { + int controller_id = kInvalidGodotControllerId; + OvrMobileController *controller = session->get_ovr_mobile_controller(); + if (controller) { + controller_id = controller->get_active_controller_id(); + } + return controller_id; + }, + []() { return kInvalidGodotControllerId; }); } -int get_primary_controller_id(OvrMobileSession* session) { - return check_session_initialized(session, [&]() { - int controller_id = kInvalidGodotControllerId; - OvrMobileController* controller = session->get_ovr_mobile_controller(); - if (controller) { - controller_id = controller->get_active_controller_id(); - } - return controller_id; - }, []() { return kInvalidGodotControllerId; }); +ovrControllerType get_primary_controller_type(OvrMobileSession *session) { + return check_session_initialized(session, [&]() { + OvrMobileController *controller = session->get_ovr_mobile_controller(); + if (controller) { + const OvrMobileController::ControllerState *controller_state = + controller->get_controller_state_by_id(kPrimaryControllerId); + if (controller_state) { + return controller_state->capability_header.Type; + } + } + return ovrControllerType::ovrControllerType_None; + }); } } // namespace ovrmobile diff --git a/plugin/src/main/cpp/api/ovr_input.h b/plugin/src/main/cpp/api/ovr_input.h index 2b574ea..b9f6de0 100644 --- a/plugin/src/main/cpp/api/ovr_input.h +++ b/plugin/src/main/cpp/api/ovr_input.h @@ -1,5 +1,5 @@ -#ifndef OVR_INPUT_H -#define OVR_INPUT_H +#ifndef GODOT_OCULUS_MOBILE_PLUGIN_OVR_INPUT_H +#define GODOT_OCULUS_MOBILE_PLUGIN_OVR_INPUT_H #include "ovr_mobile_session.h" @@ -8,30 +8,39 @@ namespace { using namespace godot; } +/// Vibrate the controller matching the given controller ID. +/// Returns true if the controller was vibrated, false otherwise. +bool vibrate_controller(OvrMobileSession *session, + int controller_id, + int duration_in_ms, + float intensity); + +/// Return the id for the primary controller. +int get_primary_controller_id(OvrMobileSession *session); + +/// Return the type for the primary controller. +ovrControllerType get_primary_controller_type(OvrMobileSession *session); + class OvrInput : public Reference { - GODOT_CLASS(OvrInput, Reference) + GODOT_CLASS(OvrInput, Reference) public: - OvrInput(); + OvrInput(); - ~OvrInput(); + ~OvrInput(); - static void _register_methods(); + static void _register_methods(); - void _init(); + void _init(); - int get_primary_controller_id(); -}; + inline int get_primary_controller_id() { + return ovrmobile::get_primary_controller_id(OvrMobileSession::get_singleton_instance()); + } -/// Vibrate the controller matching the given controller ID. -/// Returns true if the controller was vibrated, false otherwise. -bool vibrate_controller(OvrMobileSession* session, - int controller_id, - int duration_in_ms, - float intensity); - -/// Return the id for the primary controller. -int get_primary_controller_id(OvrMobileSession* session); + inline int get_primary_controller_type() { + return ovrmobile::get_primary_controller_type(OvrMobileSession::get_singleton_instance()); + } +}; } // namespace ovrmobile -#endif // OVR_INPUT_H +#endif // GODOT_OCULUS_MOBILE_PLUGIN_OVR_INPUT_H diff --git a/plugin/src/main/cpp/gdnative/godot_ovrmobile.cpp b/plugin/src/main/cpp/gdnative/godot_ovrmobile.cpp index 3e66349..6bc1d16 100644 --- a/plugin/src/main/cpp/gdnative/godot_ovrmobile.cpp +++ b/plugin/src/main/cpp/gdnative/godot_ovrmobile.cpp @@ -4,53 +4,51 @@ // Written by Bastiaan "Mux213" Olij and Paritosh Sharma, // with loads of help from Thomas "Karroffel" Herzog -#include -#include #include "godot_ovrmobile.h" - -#include "arvr_interface.h" - +#include "api/ovr_display.h" #include "api/ovr_input.h" -#include "gdnative/nativescript/ovr_display_refresh_rate_ns.h" +#include "arvr_interface.h" #include "gdnative/nativescript/ovr_guardian_system_ns.h" +#include "gdnative/nativescript/ovr_hand_tracking_ns.h" #include "gdnative/nativescript/ovr_init_config_ns.h" #include "gdnative/nativescript/ovr_performance_ns.h" #include "gdnative/nativescript/ovr_tracking_transform_ns.h" #include "gdnative/nativescript/ovr_utilities_ns.h" -#include "gdnative/nativescript/ovr_hand_tracking_ns.h" +#include +#include // experimental low-level VrApi access #include "gdnative/nativescript/ovr_vr_api_proxy_ns.h" void GDN_EXPORT godot_ovrmobile_gdnative_init(godot_gdnative_init_options *options) { - godot::Godot::gdnative_init(options); + godot::Godot::gdnative_init(options); } void GDN_EXPORT godot_ovrmobile_gdnative_singleton() { - if (godot::arvr_api != nullptr) { - godot::arvr_api->godot_arvr_register_interface(&interface_struct); - } + if (godot::arvr_api != nullptr) { + godot::arvr_api->godot_arvr_register_interface(&interface_struct); + } } void GDN_EXPORT godot_ovrmobile_nativescript_init(void *handle) { - godot::Godot::nativescript_init(handle); - - register_gdnative_display_refresh_rate(handle); - register_gdnative_guardian_system(handle); - register_gdnative_init_config(handle); - register_gdnative_performance(handle); - register_gdnative_tracking_transform(handle); - register_gdnative_utilities(handle); - register_gdnative_hand_tracking(handle); - register_gdnative_vr_api_proxy(handle); - - godot::register_class(); + godot::Godot::nativescript_init(handle); + + register_gdnative_guardian_system(handle); + register_gdnative_init_config(handle); + register_gdnative_performance(handle); + register_gdnative_tracking_transform(handle); + register_gdnative_utilities(handle); + register_gdnative_hand_tracking(handle); + register_gdnative_vr_api_proxy(handle); + + godot::register_class(); + godot::register_class(); } void GDN_EXPORT godot_ovrmobile_nativescript_terminate(void *handle) { - godot::Godot::nativescript_terminate(handle); + godot::Godot::nativescript_terminate(handle); } void GDN_EXPORT godot_ovrmobile_gdnative_terminate(godot_gdnative_terminate_options *options) { - godot::Godot::gdnative_terminate(options); + godot::Godot::gdnative_terminate(options); } diff --git a/plugin/src/main/cpp/gdnative/nativescript/ovr_display_refresh_rate_ns.cpp b/plugin/src/main/cpp/gdnative/nativescript/ovr_display_refresh_rate_ns.cpp deleted file mode 100644 index e0363bf..0000000 --- a/plugin/src/main/cpp/gdnative/nativescript/ovr_display_refresh_rate_ns.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "ovr_display_refresh_rate_ns.h" -#include -#include "api/ovr_display_refresh_rate.h" - -static const char *kClassName = "OvrDisplayRefreshRate"; - -void register_gdnative_display_refresh_rate(void *handle) { - // register the constructor and destructor of the OvrDisplayRefreshRate class for use in GDScript - godot_instance_create_func create = { NULL, NULL, NULL }; - create.create_func = &ovr_display_refresh_rate_constructor; - - godot_instance_destroy_func destroy = { NULL, NULL, NULL }; - destroy.destroy_func = &ovr_display_refresh_rate_destructor; - - godot::nativescript_api->godot_nativescript_register_class(handle, kClassName, "Reference", create, destroy); - - // register all the functions that we want to expose via the OvrDisplayRefreshRate class in GDScript - godot_instance_method method = { NULL, NULL, NULL }; - godot_method_attributes attributes = { GODOT_METHOD_RPC_MODE_DISABLED }; - - method.method = &get_supported_display_refresh_rates; - godot::nativescript_api->godot_nativescript_register_method(handle, kClassName, "get_supported_display_refresh_rates", attributes, method); - - method.method = &set_display_refresh_rate; - godot::nativescript_api->godot_nativescript_register_method(handle, kClassName, "set_display_refresh_rate", attributes, method); -} - -GDCALLINGCONV void *ovr_display_refresh_rate_constructor(godot_object *instance, void *method_data) { - return init_ovr_config_data_struct(); -} - -GDCALLINGCONV void ovr_display_refresh_rate_destructor(godot_object *instance, void *method_data, void *user_data) { - if (user_data) { - reset_ovr_config_data_struct(static_cast(user_data)); - } -} - -GDCALLINGCONV godot_variant get_supported_display_refresh_rates(godot_object *instance, void *method_data, void *p_user_data, int num_args, godot_variant **args) { - CHECK_USER_DATA( - std::vector supported_refresh_rates = ovrmobile::get_supported_display_refresh_rates(ovr_mobile_session); - - godot_array gd_return_array; - godot::api->godot_array_new(&gd_return_array); - - for (int i = 0; i < supported_refresh_rates.size(); i++) { - godot_variant refresh_rate; - godot::api->godot_variant_new_real(&refresh_rate, supported_refresh_rates[i]); - godot::api->godot_array_push_back(&gd_return_array, &refresh_rate); - godot::api->godot_variant_destroy(&refresh_rate); - } - - godot::api->godot_variant_new_array(&ret, &gd_return_array); - godot::api->godot_array_destroy(&gd_return_array); - - ) -} - -GDCALLINGCONV godot_variant set_display_refresh_rate(godot_object *instance, void *method_data, void *p_user_data, int num_args, godot_variant **args) { - CHECK_USER_DATA( - const double refresh_rate = godot::api->godot_variant_as_real(args[0]); - godot::api->godot_variant_new_bool(&ret, ovrmobile::set_display_refresh_rate(ovr_mobile_session, refresh_rate)); - ) -} \ No newline at end of file diff --git a/plugin/src/main/cpp/gdnative/nativescript/ovr_display_refresh_rate_ns.h b/plugin/src/main/cpp/gdnative/nativescript/ovr_display_refresh_rate_ns.h deleted file mode 100644 index 3a3e28e..0000000 --- a/plugin/src/main/cpp/gdnative/nativescript/ovr_display_refresh_rate_ns.h +++ /dev/null @@ -1,32 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////////////////////// -// GDNative module that exposes part of the oculus runtime api. -// Each exported class implements one section of the VrApi.h. -// This implements the section. - -#ifndef OVR_DISPLAY_REFRESH_RATE_NS_H -#define OVR_DISPLAY_REFRESH_RATE_NS_H - -#include "nativescript_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Registers the OvrDisplayRefreshRate class and functions to GDNative. -// This method should be called from godot_ovrmobile_nativescript_init. -void register_gdnative_display_refresh_rate(void *handle); - -GDCALLINGCONV void *ovr_display_refresh_rate_constructor(godot_object *instance, void *method_data); -GDCALLINGCONV void ovr_display_refresh_rate_destructor(godot_object *instance, void *method_data, void *user_data); - -// implements VrApi.h: ovrResult vrapi_SetDisplayRefreshRate(ovrMobile * ovr, const float refreshRate); -GDCALLINGCONV godot_variant set_display_refresh_rate(godot_object *instance, void *method_data, void *user_data, int num_args, godot_variant **args); - -// Utility method to access the display refresh rates supported by the device. -GDCALLINGCONV godot_variant get_supported_display_refresh_rates(godot_object *instance, void *method_data, void *user_data, int num_args, godot_variant **args); - -#ifdef __cplusplus -} -#endif - -#endif // OVR_DISPLAY_REFRESH_RATE_NS_H diff --git a/plugin/src/main/cpp/jni/ovr_display_jni.cpp b/plugin/src/main/cpp/jni/ovr_display_jni.cpp new file mode 100644 index 0000000..b2b858a --- /dev/null +++ b/plugin/src/main/cpp/jni/ovr_display_jni.cpp @@ -0,0 +1,42 @@ +/** + * Created by Fredia Huya-Kouadio. + */ + +#include "api/ovr_display.h" +#include "jni_common.h" +#include + +#undef JNI_PACKAGE_NAME +#define JNI_PACKAGE_NAME org_godotengine_plugin_vr_oculus_mobile_api + +#undef JNI_CLASS_NAME +#define JNI_CLASS_NAME OvrDisplay + +extern "C" { + +JNIEXPORT jboolean JNICALL JNI_METHOD(nativeSetColorSpace)(JNIEnv *env, jclass, jint color_space) { + return ovrmobile::set_color_space(get_session(), static_cast(color_space)); +} + +JNIEXPORT jint JNICALL JNI_METHOD(nativeGetColorSpace)(JNIEnv *env, jclass) { + return ovrmobile::get_color_space(get_session()); +} + +JNIEXPORT jboolean JNICALL JNI_METHOD(nativeSetDisplayRefreshRate)(JNIEnv *env, + jclass clazz, + jfloat refresh_rate) { + return static_cast(ovrmobile::set_display_refresh_rate(get_session(), refresh_rate)); +} + +JNIEXPORT jfloatArray JNICALL JNI_METHOD(nativeGetSupportedDisplayRefreshRates)(JNIEnv *env, + jclass clazz) { + std::vector refresh_rates = + ovrmobile::get_supported_display_refresh_rates(get_session()); + + unsigned long count = refresh_rates.size(); + jfloatArray result = env->NewFloatArray(count); + env->SetFloatArrayRegion(result, 0, count, refresh_rates.data()); + + return result; +} +}; diff --git a/plugin/src/main/cpp/jni/ovr_display_refresh_rate_jni.cpp b/plugin/src/main/cpp/jni/ovr_display_refresh_rate_jni.cpp deleted file mode 100644 index aa268b1..0000000 --- a/plugin/src/main/cpp/jni/ovr_display_refresh_rate_jni.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/** -* Created by Fredia Huya-Kouadio. -*/ - -#include - -#include "api/ovr_display_refresh_rate.h" -#include "jni_common.h" - -#undef JNI_PACKAGE_NAME -#define JNI_PACKAGE_NAME org_godotengine_plugin_vr_oculus_mobile_api - -#undef JNI_CLASS_NAME -#define JNI_CLASS_NAME OvrDisplayRefreshRate - -extern "C" { -JNIEXPORT jboolean JNICALL -JNI_METHOD(nativeSetDisplayRefreshRate)(JNIEnv *env, jclass clazz, jfloat refresh_rate) { - return static_cast(ovrmobile::set_display_refresh_rate(get_session(), - refresh_rate)); -} - -JNIEXPORT jfloatArray JNICALL -JNI_METHOD(nativeGetSupportedDisplayRefreshRates)(JNIEnv *env, jclass clazz) { - std::vector refresh_rates = ovrmobile::get_supported_display_refresh_rates( - get_session()); - - unsigned long count = refresh_rates.size(); - jfloatArray result = env->NewFloatArray(count); - env->SetFloatArrayRegion(result, 0, count, refresh_rates.data()); - - return result; -} -}; \ No newline at end of file diff --git a/plugin/src/main/cpp/jni/ovr_input_jni.cpp b/plugin/src/main/cpp/jni/ovr_input_jni.cpp index 2e527d0..6a07975 100644 --- a/plugin/src/main/cpp/jni/ovr_input_jni.cpp +++ b/plugin/src/main/cpp/jni/ovr_input_jni.cpp @@ -1,10 +1,10 @@ /** -* Created by Fredia Huya-Kouadio. -*/ + * Created by Fredia Huya-Kouadio. + */ -#include #include "api/ovr_input.h" #include "jni_common.h" +#include #undef JNI_PACKAGE_NAME #define JNI_PACKAGE_NAME org_godotengine_plugin_vr_oculus_mobile_api @@ -14,18 +14,20 @@ extern "C" { -JNIEXPORT void JNICALL -JNI_METHOD(vibrateController)(JNIEnv*, - jclass, - jobject, - jint controller_id, - jint duration_in_ms, - jfloat intensity) { +JNIEXPORT void JNICALL JNI_METHOD(vibrateController)(JNIEnv *, + jclass, + jobject, + jint controller_id, + jint duration_in_ms, + jfloat intensity) { ovrmobile::vibrate_controller(get_session(), controller_id, duration_in_ms, intensity); } -JNIEXPORT jint JNICALL JNI_METHOD(getPrimaryControllerId)(JNIEnv*, jclass, jobject) { +JNIEXPORT jint JNICALL JNI_METHOD(getPrimaryControllerId)(JNIEnv *, jclass, jobject) { return ovrmobile::get_primary_controller_id(get_session()); } +JNIEXPORT jint JNICALL JNI_METHOD(nativeGetPrimaryControllerType)(JNIEnv *, jclass) { + return ovrmobile::get_primary_controller_type(get_session()); +} }; diff --git a/plugin/src/main/cpp/ovr_mobile_controller.cpp b/plugin/src/main/cpp/ovr_mobile_controller.cpp index ac0c50b..ca78ff9 100644 --- a/plugin/src/main/cpp/ovr_mobile_controller.cpp +++ b/plugin/src/main/cpp/ovr_mobile_controller.cpp @@ -1,6 +1,6 @@ /** -* Created by Fredia Huya-Kouadio. -*/ + * Created by Fredia Huya-Kouadio. + */ #include "ovr_mobile_controller.h" @@ -35,39 +35,42 @@ OvrMobileController::OvrMobileController() = default; OvrMobileController::~OvrMobileController() = default; void OvrMobileController::process(ovrMobile *ovr, ovrJava *java, double predicted_display_time) { - update_controllers_connection_state(ovr, java); - for (auto &controller : controllers) { - update_controller_tracking_state(ovr, controller, predicted_display_time); - update_controller_input_state(ovr, controller); - update_controller_vibration(ovr, controller); - } + update_controllers_connection_state(ovr, java); + for (auto &controller : controllers) { + update_controller_tracking_state(ovr, controller, predicted_display_time); + update_controller_input_state(ovr, controller); + update_controller_vibration(ovr, controller); + } } -void OvrMobileController::update_controller_vibration(ovrMobile *ovr, ControllerState& controller_state) { - if (!controller_state.connected || controller_state.godot_controller_id == kInvalidGodotControllerId) { - return; - } +void OvrMobileController::update_controller_vibration(ovrMobile *ovr, + ControllerState &controller_state) { + if (!controller_state.connected || + controller_state.godot_controller_id == kInvalidGodotControllerId) { + return; + } - if (!(controller_state.capability_header.Type == ovrControllerType_TrackedRemote) - || !supports_haptic_vibration(controller_state.remote_capabilities)) { + if (!(controller_state.capability_header.Type == ovrControllerType_TrackedRemote) || + !supports_haptic_vibration(controller_state.remote_capabilities)) { // unsupported controller return; } // Get the controller rumble intensity. This will override previous controller vibration // requests as this takes precedence. - const float intensity = godot::arvr_api->godot_arvr_get_controller_rumble(controller_state.godot_controller_id); - vibrate_controller(controller_state.godot_controller_id, kControllerRumbleDurationInMs, intensity); + const float intensity = + godot::arvr_api->godot_arvr_get_controller_rumble(controller_state.godot_controller_id); + vibrate_controller( + controller_state.godot_controller_id, kControllerRumbleDurationInMs, intensity); // Process controller vibrations. - ControllerVibration& vibration = controllers_vibrations[controller_state.godot_controller_id]; + ControllerVibration &vibration = controllers_vibrations[controller_state.godot_controller_id]; double current_time_in_ms = get_time_in_ms(); - if (vibration.is_vibrating - && (vibration.end_time_in_ms < (current_time_in_ms + kEspilonTimeInMs))) { + if (vibration.is_vibrating && + (vibration.end_time_in_ms < (current_time_in_ms + kEspilonTimeInMs))) { // Stop vibrating - vrapi_SetHapticVibrationSimple(ovr, - controller_state.remote_capabilities.Header.DeviceID, - 0.0f); + vrapi_SetHapticVibrationSimple( + ovr, controller_state.remote_capabilities.Header.DeviceID, 0.0f); // Reset the vibration parameters vibration.end_time_in_ms = 0; @@ -77,254 +80,410 @@ void OvrMobileController::update_controller_vibration(ovrMobile *ovr, Controller } if (vibration.end_time_in_ms > 0) { - vrapi_SetHapticVibrationSimple(ovr, - controller_state.remote_capabilities.Header.DeviceID, - vibration.intensity); + vrapi_SetHapticVibrationSimple( + ovr, controller_state.remote_capabilities.Header.DeviceID, vibration.intensity); vibration.is_vibrating = true; } } -void OvrMobileController::update_controller_input_state(ovrMobile *ovr,ControllerState& controller_state) { - if (!controller_state.connected || controller_state.godot_controller_id == kInvalidGodotControllerId) { - return; - } - - if (controller_state.capability_header.Type == ovrControllerType_TrackedRemote) { - update_controller_input_state_tracked_remote(ovr, controller_state); - } else if (controller_state.capability_header.Type == ovrControllerType_Hand) { - update_controller_input_state_hand(ovr, controller_state); - } else { - // unsupported controller - } -} +void OvrMobileController::update_controller_input_state(ovrMobile *ovr, + ControllerState &controller_state) { + if (!controller_state.connected || + controller_state.godot_controller_id == kInvalidGodotControllerId) { + return; + } -void OvrMobileController::update_controller_input_state_tracked_remote(ovrMobile *ovr, ControllerState& controller_state) { - // Get the device input state. - controller_state.input_header.ControllerType = ovrControllerType_TrackedRemote; - if (vrapi_GetCurrentInputState(ovr, controller_state.remote_capabilities.Header.DeviceID, &controller_state.input_header) < 0) { - return; - } - - ovrInputStateTrackedRemote& input_state = controller_state.input_tracked_remote; - - // Update the controller axis. - if (has_joystick(controller_state.remote_capabilities)) { - // X axis - godot::arvr_api->godot_arvr_set_controller_axis(controller_state.godot_controller_id, kXAxis, input_state.Joystick.x, true /* can_be_negative */); - // Y axis - godot::arvr_api->godot_arvr_set_controller_axis(controller_state.godot_controller_id, kYAxis, input_state.Joystick.y, true /* can_be_negative */); - } - - if (has_trackpad(controller_state.remote_capabilities)) { - // X axis - float positionX = input_state.TrackpadStatus ? input_state.TrackpadPosition.x / controller_state.remote_capabilities.TrackpadMaxX : 0.5f; - godot::arvr_api->godot_arvr_set_controller_axis(controller_state.godot_controller_id, kXAxis, positionX, false /* can_be_negative */); - // Y axis - float positionY = input_state.TrackpadStatus ? input_state.TrackpadPosition.y / controller_state.remote_capabilities.TrackpadMaxY : 0.5f; - godot::arvr_api->godot_arvr_set_controller_axis(controller_state.godot_controller_id, kYAxis, positionY, false /* can_be_negative */); - } - - if (has_analog_index_trigger(controller_state.remote_capabilities)) { - godot::arvr_api->godot_arvr_set_controller_axis(controller_state.godot_controller_id, kAnalogIndexTriggerAxis, input_state.IndexTrigger, false /* can_be_negative */); - } - - if (has_analog_grip_trigger(controller_state.remote_capabilities)) { - godot::arvr_api->godot_arvr_set_controller_axis(controller_state.godot_controller_id, kAnalogGripTriggerAxis, input_state.GripTrigger, false /* can_be_negative */); - } - - // Update the controller button state. The button mappings for Godot will differ based on the Oculus mobile device. - if (is_oculus_touch_controller(controller_state.remote_capabilities)) { - // For now, keep the button assignments the same as for the Oculus Rift. - // 9 -> thumb rest. The Oculus Quest touch controllers no longer have the thumb rest. - godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, 2, input_state.GripTrigger > kGripTriggerPressedThreshold); - godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, 10, check_bit(input_state.Touches, ovrTouch_ThumbUp)); - godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, 11, check_bit(input_state.Touches, ovrTouch_IndexTrigger)); - godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, 12, check_bit(input_state.Touches, ovrTouch_IndexPointing)); - godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, 15, input_state.IndexTrigger > kIndexTriggerPressedThreshold); - - if (is_left_hand_controller(controller_state.remote_capabilities)) { - godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, 3, check_bit(input_state.Buttons, ovrButton_Enter)); // menu button - godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, 14, check_bit(input_state.Buttons, ovrButton_LThumb)); - godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, 7, check_bit(input_state.Buttons, ovrButton_X)); - godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, 5, check_bit(input_state.Touches, ovrTouch_X)); - godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, 1, check_bit(input_state.Buttons, ovrButton_Y)); - godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, 6, check_bit(input_state.Touches, ovrTouch_Y)); - } - - if (is_right_hand_controller(controller_state.remote_capabilities)) { - // 3 -> home button. The home button is not available for applications. - godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, 7, check_bit(input_state.Buttons, ovrButton_A)); - godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, 5, check_bit(input_state.Touches, ovrTouch_A)); - godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, 1, check_bit(input_state.Buttons, ovrButton_B)); - godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, 6, check_bit(input_state.Touches, ovrTouch_B)); - godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, 14, check_bit(input_state.Buttons, ovrButton_RThumb)); - } - } - - if (is_oculus_go_controller(controller_state.remote_capabilities) || - is_gear_vr_controller(controller_state.remote_capabilities)) { - godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, 1, check_bit(input_state.Buttons, ovrButton_Back)); // Back button - godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, 3, check_bit(input_state.Buttons, ovrButton_Enter)); // Touchpad click - godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, 7, check_bit(input_state.Buttons, ovrButton_A)); // Set for trigger button - } + if (controller_state.capability_header.Type == ovrControllerType_TrackedRemote) { + update_controller_input_state_tracked_remote(ovr, controller_state); + } else if (controller_state.capability_header.Type == ovrControllerType_Hand) { + update_controller_input_state_hand(ovr, controller_state); + } else { + // unsupported controller + } } -void OvrMobileController::update_controller_input_state_hand(ovrMobile *ovr, ControllerState& controller_state) { - controller_state.input_header.ControllerType = ovrControllerType_Hand; +void OvrMobileController::update_controller_input_state_tracked_remote( + ovrMobile *ovr, + ControllerState &controller_state) { + // Get the device input state. + controller_state.input_header.ControllerType = ovrControllerType_TrackedRemote; + if (vrapi_GetCurrentInputState(ovr, + controller_state.remote_capabilities.Header.DeviceID, + &controller_state.input_header) < 0) { + return; + } - if (vrapi_GetCurrentInputState(ovr, controller_state.remote_capabilities.Header.DeviceID, &controller_state.input_header) < 0) { - return; - } + ovrInputStateTrackedRemote &input_state = controller_state.input_tracked_remote; + + // Update the controller axis. + if (has_joystick(controller_state.remote_capabilities)) { + // X axis + godot::arvr_api->godot_arvr_set_controller_axis(controller_state.godot_controller_id, + kXAxis, + input_state.Joystick.x, + true /* can_be_negative */); + // Y axis + godot::arvr_api->godot_arvr_set_controller_axis(controller_state.godot_controller_id, + kYAxis, + input_state.Joystick.y, + true /* can_be_negative */); + } - ovrInputStateHand& input_state = controller_state.input_hand; + if (has_trackpad(controller_state.remote_capabilities)) { + // X axis + float positionX = input_state.TrackpadStatus ? + input_state.TrackpadPosition.x / + controller_state.remote_capabilities.TrackpadMaxX : + 0.5f; + godot::arvr_api->godot_arvr_set_controller_axis(controller_state.godot_controller_id, + kXAxis, + positionX, + false /* can_be_negative */); + // Y axis + float positionY = input_state.TrackpadStatus ? + input_state.TrackpadPosition.y / + controller_state.remote_capabilities.TrackpadMaxY : + 0.5f; + godot::arvr_api->godot_arvr_set_controller_axis(controller_state.godot_controller_id, + kYAxis, + positionY, + false /* can_be_negative */); + } - // we map pinch index and middle to button presses with same id as X/Y and A/B - godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, 7, check_bit(input_state.InputStateStatus, ovrInputStateHandStatus_IndexPinching)); - godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, 1, check_bit(input_state.InputStateStatus, ovrInputStateHandStatus_MiddlePinching)); + if (has_analog_index_trigger(controller_state.remote_capabilities)) { + godot::arvr_api->godot_arvr_set_controller_axis(controller_state.godot_controller_id, + kAnalogIndexTriggerAxis, + input_state.IndexTrigger, + false /* can_be_negative */); + } - // pinch ring and pinky are mapped to grip (2) and index (15) triggers for now - godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, 2, check_bit(input_state.InputStateStatus, ovrInputStateHandStatus_RingPinching)); - godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, 15, check_bit(input_state.InputStateStatus, ovrInputStateHandStatus_PinkyPinching)); + if (has_analog_grip_trigger(controller_state.remote_capabilities)) { + godot::arvr_api->godot_arvr_set_controller_axis(controller_state.godot_controller_id, + kAnalogGripTriggerAxis, + input_state.GripTrigger, + false /* can_be_negative */); + } - // to allow accessing the pinch state as provided by the API we map them here to the joystick axis of the controller - // this will give the ability to access the basic hand tracking gestures without the need to query specific APIs - godot::arvr_api->godot_arvr_set_controller_axis(controller_state.godot_controller_id, kXAxis, input_state.PinchStrength[ovrHandPinchStrength_Index], false); - godot::arvr_api->godot_arvr_set_controller_axis(controller_state.godot_controller_id, kYAxis, input_state.PinchStrength[ovrHandPinchStrength_Middle], false); - godot::arvr_api->godot_arvr_set_controller_axis(controller_state.godot_controller_id, kAnalogIndexTriggerAxis, input_state.PinchStrength[ovrHandPinchStrength_Ring], false); - godot::arvr_api->godot_arvr_set_controller_axis(controller_state.godot_controller_id, kAnalogGripTriggerAxis, input_state.PinchStrength[ovrHandPinchStrength_Pinky], false); + // Update the controller button state. The button mappings for Godot will differ based on the + // Oculus mobile device. + if (is_oculus_touch_controller(controller_state.remote_capabilities)) { + // For now, keep the button assignments the same as for the Oculus Rift. + // 9 -> thumb rest. The Oculus Quest touch controllers no longer have the thumb rest. + godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, + 2, + input_state.GripTrigger > + kGripTriggerPressedThreshold); + godot::arvr_api->godot_arvr_set_controller_button( + controller_state.godot_controller_id, + 10, + check_bit(input_state.Touches, ovrTouch_ThumbUp)); + godot::arvr_api->godot_arvr_set_controller_button( + controller_state.godot_controller_id, + 11, + check_bit(input_state.Touches, ovrTouch_IndexTrigger)); + godot::arvr_api->godot_arvr_set_controller_button( + controller_state.godot_controller_id, + 12, + check_bit(input_state.Touches, ovrTouch_IndexPointing)); + godot::arvr_api->godot_arvr_set_controller_button(controller_state.godot_controller_id, + 15, + input_state.IndexTrigger > + kIndexTriggerPressedThreshold); + + if (is_left_touch_controller(controller_state.remote_capabilities)) { + godot::arvr_api->godot_arvr_set_controller_button( + controller_state.godot_controller_id, + 3, + check_bit(input_state.Buttons, ovrButton_Enter)); // menu button + godot::arvr_api->godot_arvr_set_controller_button( + controller_state.godot_controller_id, + 14, + check_bit(input_state.Buttons, ovrButton_LThumb)); + godot::arvr_api->godot_arvr_set_controller_button( + controller_state.godot_controller_id, + 7, + check_bit(input_state.Buttons, ovrButton_X)); + godot::arvr_api->godot_arvr_set_controller_button( + controller_state.godot_controller_id, + 5, + check_bit(input_state.Touches, ovrTouch_X)); + godot::arvr_api->godot_arvr_set_controller_button( + controller_state.godot_controller_id, + 1, + check_bit(input_state.Buttons, ovrButton_Y)); + godot::arvr_api->godot_arvr_set_controller_button( + controller_state.godot_controller_id, + 6, + check_bit(input_state.Touches, ovrTouch_Y)); + } + + if (is_right_touch_controller(controller_state.remote_capabilities)) { + // 3 -> home button. The home button is not available for applications. + godot::arvr_api->godot_arvr_set_controller_button( + controller_state.godot_controller_id, + 7, + check_bit(input_state.Buttons, ovrButton_A)); + godot::arvr_api->godot_arvr_set_controller_button( + controller_state.godot_controller_id, + 5, + check_bit(input_state.Touches, ovrTouch_A)); + godot::arvr_api->godot_arvr_set_controller_button( + controller_state.godot_controller_id, + 1, + check_bit(input_state.Buttons, ovrButton_B)); + godot::arvr_api->godot_arvr_set_controller_button( + controller_state.godot_controller_id, + 6, + check_bit(input_state.Touches, ovrTouch_B)); + godot::arvr_api->godot_arvr_set_controller_button( + controller_state.godot_controller_id, + 14, + check_bit(input_state.Buttons, ovrButton_RThumb)); + } + } + + if (is_oculus_go_controller(controller_state.remote_capabilities) || + is_gear_vr_controller(controller_state.remote_capabilities)) { + godot::arvr_api->godot_arvr_set_controller_button( + controller_state.godot_controller_id, + 1, + check_bit(input_state.Buttons, ovrButton_Back)); // Back button + godot::arvr_api->godot_arvr_set_controller_button( + controller_state.godot_controller_id, + 3, + check_bit(input_state.Buttons, ovrButton_Enter)); // Touchpad click + godot::arvr_api->godot_arvr_set_controller_button( + controller_state.godot_controller_id, + 7, + check_bit(input_state.Buttons, ovrButton_A)); // Set for trigger button + } } +void OvrMobileController::update_controller_input_state_hand(ovrMobile *ovr, + ControllerState &controller_state) { + controller_state.input_header.ControllerType = ovrControllerType_Hand; -void OvrMobileController::update_controller_tracking_state(ovrMobile *ovr, ControllerState& controller_state, double predicted_display_time) { - if (!controller_state.connected || controller_state.godot_controller_id == kInvalidGodotControllerId) { - return; - } + if (vrapi_GetCurrentInputState(ovr, + controller_state.remote_capabilities.Header.DeviceID, + &controller_state.input_header) < 0) { + return; + } - if (controller_state.capability_header.Type == ovrControllerType_TrackedRemote) { - update_controller_tracking_state_tracked_remote(ovr, controller_state, predicted_display_time); - } else if (controller_state.capability_header.Type == ovrControllerType_Hand) { - update_controller_tracking_state_hand(ovr, controller_state, predicted_display_time); - } else { - // unsupported controller type - } + ovrInputStateHand &input_state = controller_state.input_hand; + + // we map pinch index and middle to button presses with same id as X/Y and A/B + godot::arvr_api->godot_arvr_set_controller_button( + controller_state.godot_controller_id, + 7, + check_bit(input_state.InputStateStatus, ovrInputStateHandStatus_IndexPinching)); + godot::arvr_api->godot_arvr_set_controller_button( + controller_state.godot_controller_id, + 1, + check_bit(input_state.InputStateStatus, ovrInputStateHandStatus_MiddlePinching)); + + // pinch ring and pinky are mapped to grip (2) and index (15) triggers for now + godot::arvr_api->godot_arvr_set_controller_button( + controller_state.godot_controller_id, + 2, + check_bit(input_state.InputStateStatus, ovrInputStateHandStatus_RingPinching)); + godot::arvr_api->godot_arvr_set_controller_button( + controller_state.godot_controller_id, + 15, + check_bit(input_state.InputStateStatus, ovrInputStateHandStatus_PinkyPinching)); + + // to allow accessing the pinch state as provided by the API we map them here to the joystick + // axis of the controller this will give the ability to access the basic hand tracking gestures + // without the need to query specific APIs + godot::arvr_api->godot_arvr_set_controller_axis( + controller_state.godot_controller_id, + kXAxis, + input_state.PinchStrength[ovrHandPinchStrength_Index], + false); + godot::arvr_api->godot_arvr_set_controller_axis( + controller_state.godot_controller_id, + kYAxis, + input_state.PinchStrength[ovrHandPinchStrength_Middle], + false); + godot::arvr_api->godot_arvr_set_controller_axis( + controller_state.godot_controller_id, + kAnalogIndexTriggerAxis, + input_state.PinchStrength[ovrHandPinchStrength_Ring], + false); + godot::arvr_api->godot_arvr_set_controller_axis( + controller_state.godot_controller_id, + kAnalogGripTriggerAxis, + input_state.PinchStrength[ovrHandPinchStrength_Pinky], + false); } -void OvrMobileController::update_controller_tracking_state_tracked_remote(ovrMobile *ovr, ControllerState& controller_state, double predicted_display_time) { - // Tracked remote is connected. Get the device tracking state. - if (vrapi_GetInputTrackingState(ovr, controller_state.remote_capabilities.Header.DeviceID, predicted_display_time, &controller_state.tracking_state) < 0) { - return; - } - - // Update the controller transform. - godot_transform transform; - godot_transform_from_ovr_pose(&transform, controller_state.tracking_state.HeadPose.Pose, 1.0); // worldscale is already applied in godot_arvr_set_controller_transform - godot::arvr_api->godot_arvr_set_controller_transform(controller_state.godot_controller_id, &transform, - has_orientation_tracking(controller_state.remote_capabilities), - has_position_tracking(controller_state.remote_capabilities) || is_oculus_go_controller(controller_state.remote_capabilities)); - // while the Oculus Go controller is not tracked (has_position_tracking == false), the Oculus API provides a position for it based on a simulated arm model -} +void OvrMobileController::update_controller_tracking_state(ovrMobile *ovr, + ControllerState &controller_state, + double predicted_display_time) { + if (!controller_state.connected || + controller_state.godot_controller_id == kInvalidGodotControllerId) { + return; + } -void OvrMobileController::update_controller_tracking_state_hand(ovrMobile *ovr, ControllerState& controller_state, double predicted_display_time) { - if (vrapi_GetInputTrackingState(ovr, controller_state.capability_header.DeviceID, predicted_display_time, &controller_state.tracking_state) < 0) { - return; - } + if (controller_state.capability_header.Type == ovrControllerType_TrackedRemote) { + update_controller_tracking_state_tracked_remote( + ovr, controller_state, predicted_display_time); + } else if (controller_state.capability_header.Type == ovrControllerType_Hand) { + update_controller_tracking_state_hand(ovr, controller_state, predicted_display_time); + } else { + // unsupported controller type + } +} - controller_state.hand_pose.Header.Version = ovrHandVersion_1; //!!TODO: set in initialization - vrapi_GetHandPose(ovr, controller_state.capability_header.DeviceID, predicted_display_time, &controller_state.hand_pose.Header); +void OvrMobileController::update_controller_tracking_state_tracked_remote( + ovrMobile *ovr, + ControllerState &controller_state, + double predicted_display_time) { + // Tracked remote is connected. Get the device tracking state. + if (vrapi_GetInputTrackingState(ovr, + controller_state.remote_capabilities.Header.DeviceID, + predicted_display_time, + &controller_state.tracking_state) < 0) { + return; + } - // Update the controller transform. - godot_transform transform; - //godot_transform_from_ovr_pose(&transform, controller_state.tracking_state.HeadPose.Pose, godot::arvr_api->godot_arvr_get_worldscale()); - godot_transform_from_ovr_pose(&transform, controller_state.hand_pose.RootPose, 1.0); // worldscale is already applied in godot_arvr_set_controller_transform - godot::arvr_api->godot_arvr_set_controller_transform(controller_state.godot_controller_id, &transform, true, true); + // Update the controller transform. + godot_transform transform; + godot_transform_from_ovr_pose( + &transform, + controller_state.tracking_state.HeadPose.Pose, + 1.0); // worldscale is already applied in godot_arvr_set_controller_transform + godot::arvr_api->godot_arvr_set_controller_transform( + controller_state.godot_controller_id, + &transform, + has_orientation_tracking(controller_state.remote_capabilities), + has_position_tracking(controller_state.remote_capabilities) || + is_oculus_go_controller(controller_state.remote_capabilities)); + // while the Oculus Go controller is not tracked (has_position_tracking == false), the Oculus + // API provides a position for it based on a simulated arm model } +void OvrMobileController::update_controller_tracking_state_hand(ovrMobile *ovr, + ControllerState &controller_state, + double predicted_display_time) { + if (vrapi_GetInputTrackingState(ovr, + controller_state.capability_header.DeviceID, + predicted_display_time, + &controller_state.tracking_state) < 0) { + return; + } + + controller_state.hand_pose.Header.Version = ovrHandVersion_1; //!!TODO: set in initialization + vrapi_GetHandPose(ovr, + controller_state.capability_header.DeviceID, + predicted_display_time, + &controller_state.hand_pose.Header); + + // Update the controller transform. + godot_transform transform; + // godot_transform_from_ovr_pose(&transform, controller_state.tracking_state.HeadPose.Pose, + // godot::arvr_api->godot_arvr_get_worldscale()); + godot_transform_from_ovr_pose( + &transform, + controller_state.hand_pose.RootPose, + 1.0); // worldscale is already applied in godot_arvr_set_controller_transform + godot::arvr_api->godot_arvr_set_controller_transform( + controller_state.godot_controller_id, &transform, true, true); +} void OvrMobileController::update_controllers_connection_state(ovrMobile *ovr, ovrJava *java) { - // Reset the controllers connected and primary state. - for (auto &controller : controllers) { - controller.connected = false; - controller.primary = false; - } - - // Check controller(s) connection state. - ovrInputCapabilityHeader capability_header; - for (uint32_t device_index = 0; vrapi_EnumerateInputDevices(ovr, device_index, &capability_header) >= 0; device_index++) { - // Tracked remote (e.g: Gear VR, Oculus Go, Oculus Quest controllers). - if (capability_header.Type == ovrControllerType_TrackedRemote) { - ovrInputTrackedRemoteCapabilities tracked_remote_capabilities; - tracked_remote_capabilities.Header = capability_header; - if (vrapi_GetInputDeviceCapabilities(ovr, &tracked_remote_capabilities.Header) < 0) { - continue; - } - - ControllerHand handedness; - if (is_oculus_touch_controller(tracked_remote_capabilities)) { - handedness = get_controller_handedness(tracked_remote_capabilities); - } else { - // We're handling a Gear VR or Oculus Go controller. Let's query the user dominant hand to find out where to - // assign the controller. - auto dominant_hand = static_cast(vrapi_GetSystemPropertyInt(java, VRAPI_SYS_PROP_DOMINANT_HAND)); - handedness = dominant_hand == VRAPI_HAND_LEFT ? LEFT_HAND : RIGHT_HAND; - } - - // this check forces a reconnect below because the type of the controller changed - if (controllers[handedness].capability_header.Type != ovrControllerType_TrackedRemote && controllers[handedness].godot_controller_id != kInvalidGodotControllerId) { - godot::arvr_api->godot_arvr_remove_controller(controllers[handedness].godot_controller_id); - ALOGV("Removed Controller Tracked Remote (Godot id %d)", controllers[handedness].godot_controller_id); - controllers[handedness].godot_controller_id = kInvalidGodotControllerId; - } - - controllers[handedness].connected = true; - controllers[handedness].remote_capabilities = tracked_remote_capabilities; - } else if (capability_header.Type == ovrControllerType_Hand) { - ovrInputHandCapabilities tracked_hand_capabilities; - tracked_hand_capabilities.Header = capability_header; - if (vrapi_GetInputDeviceCapabilities(ovr, &tracked_hand_capabilities.Header) < 0) { - continue; - } - - ControllerHand handedness = get_controller_handedness(tracked_hand_capabilities); - - // this check forces a reconnect below because the type of the controller changed - if (controllers[handedness].capability_header.Type != ovrControllerType_Hand && controllers[handedness].godot_controller_id != kInvalidGodotControllerId) { - godot::arvr_api->godot_arvr_remove_controller(controllers[handedness].godot_controller_id); - ALOGV("Removed Tracked Hand (Godot id %d)", controllers[handedness].godot_controller_id); - controllers[handedness].godot_controller_id = kInvalidGodotControllerId; - } - controllers[handedness].connected = true; - controllers[handedness].hand_capabilities = tracked_hand_capabilities; - } else { - // unsupported at the moment - } - } - - // Get the primary input device id. - int primary_input_device_id = -1; - vrapi_GetPropertyInt(java, VRAPI_ACTIVE_INPUT_DEVICE_ID, &primary_input_device_id); - - for (int hand = 0; hand < MAX_HANDS; hand++) { - ControllerState *controller = &controllers[hand]; - - // Notify Godot of the updated connection states. - if (controller->connected) { - controller->primary = controller->capability_header.DeviceID == primary_input_device_id; + // Reset the controllers connected and primary state. + for (auto &controller : controllers) { + controller.connected = false; + controller.primary = false; + } + + // Check controller(s) connection state. + ovrInputCapabilityHeader capability_header; + for (uint32_t device_index = 0; + vrapi_EnumerateInputDevices(ovr, device_index, &capability_header) >= 0; + device_index++) { + // Tracked remote (e.g: Gear VR, Oculus Go, Oculus Quest controllers). + if (capability_header.Type == ovrControllerType_TrackedRemote) { + ovrInputTrackedRemoteCapabilities tracked_remote_capabilities; + tracked_remote_capabilities.Header = capability_header; + if (vrapi_GetInputDeviceCapabilities(ovr, &tracked_remote_capabilities.Header) < 0) { + continue; + } + + ControllerHand handedness; + if (is_oculus_touch_controller(tracked_remote_capabilities)) { + handedness = get_controller_handedness(tracked_remote_capabilities); + } else { + // We're handling a Gear VR or Oculus Go controller. Let's query the user dominant + // hand to find out where to assign the controller. + auto dominant_hand = static_cast( + vrapi_GetSystemPropertyInt(java, VRAPI_SYS_PROP_DOMINANT_HAND)); + handedness = dominant_hand == VRAPI_HAND_LEFT ? LEFT_HAND : RIGHT_HAND; + } + + // this check forces a reconnect below because the type of the controller changed + if (controllers[handedness].capability_header.Type != ovrControllerType_TrackedRemote && + controllers[handedness].godot_controller_id != kInvalidGodotControllerId) { + godot::arvr_api->godot_arvr_remove_controller( + controllers[handedness].godot_controller_id); + ALOGV("Removed Controller Tracked Remote (Godot id %d)", + controllers[handedness].godot_controller_id); + controllers[handedness].godot_controller_id = kInvalidGodotControllerId; + } + + controllers[handedness].connected = true; + controllers[handedness].remote_capabilities = tracked_remote_capabilities; + } else if (capability_header.Type == ovrControllerType_Hand) { + ovrInputHandCapabilities tracked_hand_capabilities; + tracked_hand_capabilities.Header = capability_header; + if (vrapi_GetInputDeviceCapabilities(ovr, &tracked_hand_capabilities.Header) < 0) { + continue; + } + + ControllerHand handedness = get_controller_handedness(tracked_hand_capabilities); + + // this check forces a reconnect below because the type of the controller changed + if (controllers[handedness].capability_header.Type != ovrControllerType_Hand && + controllers[handedness].godot_controller_id != kInvalidGodotControllerId) { + godot::arvr_api->godot_arvr_remove_controller( + controllers[handedness].godot_controller_id); + ALOGV("Removed Tracked Hand (Godot id %d)", + controllers[handedness].godot_controller_id); + controllers[handedness].godot_controller_id = kInvalidGodotControllerId; + } + controllers[handedness].connected = true; + controllers[handedness].hand_capabilities = tracked_hand_capabilities; + } else { + // unsupported at the moment + } + } + + // Get the primary input device id. + int primary_input_device_id = -1; + vrapi_GetPropertyInt(java, VRAPI_ACTIVE_INPUT_DEVICE_ID, &primary_input_device_id); + + for (int hand = 0; hand < MAX_HANDS; hand++) { + ControllerState *controller = &controllers[hand]; + + // Notify Godot of the updated connection states. + if (controller->connected) { + controller->primary = controller->capability_header.DeviceID == primary_input_device_id; if (controller->godot_controller_id == kInvalidGodotControllerId) { // Register the controller with Godot. if (controller->capability_header.Type == ovrControllerType_TrackedRemote) { controller->godot_controller_id = godot::arvr_api->godot_arvr_add_controller( - const_cast(get_controller_model_name(*controller)), - get_godot_hand(static_cast(hand)), - has_orientation_tracking(controller->remote_capabilities), - has_position_tracking(controller->remote_capabilities)); + const_cast(get_controller_model_name(*controller)), + get_godot_hand(static_cast(hand)), + has_orientation_tracking(controller->remote_capabilities), + has_position_tracking(controller->remote_capabilities)); } else if (controller->capability_header.Type == ovrControllerType_Hand) { controller->godot_controller_id = godot::arvr_api->godot_arvr_add_controller( - const_cast(get_controller_model_name(*controller)), - get_godot_hand(static_cast(hand)), - true, - true); + const_cast(get_controller_model_name(*controller)), + get_godot_hand(static_cast(hand)), + true, + true); } ALOGV("Updated Controller '%s' (Godot id %d; Oculus id %d)", get_controller_model_name(*controller), @@ -332,43 +491,47 @@ void OvrMobileController::update_controllers_connection_state(ovrMobile *ovr, ov hand); } } else if (controller->godot_controller_id != kInvalidGodotControllerId) { - // Unregister the controller from Godot. - ALOGV("Unregistered Controller '%s' (Godot id %d; Oculus id %d)", get_controller_model_name(*controller), controller->godot_controller_id, hand); - godot::arvr_api->godot_arvr_remove_controller(controller->godot_controller_id); - controller->godot_controller_id = kInvalidGodotControllerId; - } - } + // Unregister the controller from Godot. + ALOGV("Unregistered Controller '%s' (Godot id %d; Oculus id %d)", + get_controller_model_name(*controller), + controller->godot_controller_id, + hand); + godot::arvr_api->godot_arvr_remove_controller(controller->godot_controller_id); + controller->godot_controller_id = kInvalidGodotControllerId; + } + } } -const char *OvrMobileController::get_controller_model_name(const ControllerState& controller_state) { - if (controller_state.capability_header.Type == ovrControllerType_TrackedRemote) { - if (is_gear_vr_controller(controller_state.remote_capabilities)) { - return kGearVRController; - } - - if (is_oculus_go_controller(controller_state.remote_capabilities)) { - return kOculusGoController; - } - - if (is_oculus_touch_controller(controller_state.remote_capabilities)) { - if (is_left_hand_controller(controller_state.remote_capabilities)) { - return kOculusTouchLeftController; - } - - if (is_right_hand_controller(controller_state.remote_capabilities)) { - return kOculusTouchRightController; - } - } - } else if (controller_state.capability_header.Type == ovrControllerType_Hand) { - if (is_left_hand_controller(controller_state.hand_capabilities)) { - return kOculusTrackedLeftHand; - } - if (is_right_hand_controller(controller_state.hand_capabilities)) { - return kOculusTrackedRightHand; - } - } - - return kUnsupportedController; +const char * +OvrMobileController::get_controller_model_name(const ControllerState &controller_state) { + if (controller_state.capability_header.Type == ovrControllerType_TrackedRemote) { + if (is_gear_vr_controller(controller_state.remote_capabilities)) { + return kGearVRController; + } + + if (is_oculus_go_controller(controller_state.remote_capabilities)) { + return kOculusGoController; + } + + if (is_oculus_touch_controller(controller_state.remote_capabilities)) { + if (is_left_touch_controller(controller_state.remote_capabilities)) { + return kOculusTouchLeftController; + } + + if (is_right_touch_controller(controller_state.remote_capabilities)) { + return kOculusTouchRightController; + } + } + } else if (controller_state.capability_header.Type == ovrControllerType_Hand) { + if (is_left_hand_controller(controller_state.hand_capabilities)) { + return kOculusTrackedLeftHand; + } + if (is_right_hand_controller(controller_state.hand_capabilities)) { + return kOculusTrackedRightHand; + } + } + + return kUnsupportedController; } } // namespace ovrmobile diff --git a/plugin/src/main/cpp/ovr_mobile_controller.h b/plugin/src/main/cpp/ovr_mobile_controller.h index c2ad638..63ebb6a 100644 --- a/plugin/src/main/cpp/ovr_mobile_controller.h +++ b/plugin/src/main/cpp/ovr_mobile_controller.h @@ -1,16 +1,15 @@ /** -* Created by Fredia Huya-Kouadio. -*/ + * Created by Fredia Huya-Kouadio. + */ #ifndef OVRMOBILE_OVR_MOBILE_CONTROLLER_H #define OVRMOBILE_OVR_MOBILE_CONTROLLER_H -#include - #include "VrApi.h" #include "VrApi_Input.h" #include "VrApi_Types.h" #include "common.h" +#include namespace ovrmobile { @@ -18,167 +17,187 @@ namespace { const int kInvalidGodotControllerId = 0; const int kPrimaryControllerId = -1; -} +} // namespace class OvrMobileController { -public: - struct ControllerState { - bool connected = false; - // Shows which controller is primary or most 'active'. See VRAPI_ACTIVE_INPUT_DEVICE_ID for reference. - bool primary = false; - int godot_controller_id = 0; - union { - ovrInputCapabilityHeader capability_header; - ovrInputTrackedRemoteCapabilities remote_capabilities; - ovrInputHandCapabilities hand_capabilities; - }; - union { - ovrInputStateHeader input_header; - ovrInputStateHand input_hand; - ovrInputStateTrackedRemote input_tracked_remote; - }; - ovrTracking tracking_state; - ovrHandPose hand_pose; - }; - - OvrMobileController(); - - ~OvrMobileController(); - - void process(ovrMobile *ovr, ovrJava *java, double predicted_display_time); - - const ControllerState* get_controller_state_by_id(int controller_id) const { - controller_id = controller_id == kPrimaryControllerId ? get_active_controller_id() - : controller_id; - - for (int hand = 0; hand < MAX_HANDS; hand++) { - auto* controller = &controllers[hand]; - if (controller->connected && controller->godot_controller_id == controller_id) { - return controller; - } - } - return nullptr; - } - - static inline bool supports_haptic_vibration(const ovrInputTrackedRemoteCapabilities &capabilities) { - return check_bit(capabilities.ControllerCapabilities, ovrControllerCaps_HasSimpleHapticVibration); - } - - void vibrate_controller(int controller_id, int duration_in_ms, float intensity) { - controller_id = controller_id == kPrimaryControllerId ? get_active_controller_id() - : controller_id; - // Update the controller vibration state. Actual vibration will start in the next frame via - // OvrMobileController::update_controller_vibration(...). - if (duration_in_ms > 0 && intensity > 0.0f) { - ControllerVibration vibration = - {.is_vibrating = false, .end_time_in_ms = get_time_in_ms() + duration_in_ms, .intensity = intensity}; - controllers_vibrations[controller_id] = vibration; - } - } - - int get_active_controller_id() const { - for (int hand = 0; hand < MAX_HANDS; hand++) { - auto* controller = &controllers[hand]; - if (controller->connected && controller->primary) { - return controller->godot_controller_id; - } - } - return kInvalidGodotControllerId; - } - -private: - struct ControllerVibration { - float intensity; - double end_time_in_ms; - bool is_vibrating; - }; - - enum ControllerHand { - LEFT_HAND, - RIGHT_HAND, - MAX_HANDS - }; - - ControllerState controllers[MAX_HANDS]; - std::map controllers_vibrations; - - inline bool has_analog_grip_trigger(const ovrInputTrackedRemoteCapabilities &capabilities) const { - return check_bit(capabilities.ControllerCapabilities, ovrControllerCaps_HasAnalogGripTrigger); - } - - inline bool has_analog_index_trigger(const ovrInputTrackedRemoteCapabilities &capabilities) const { - return check_bit(capabilities.ControllerCapabilities, ovrControllerCaps_HasAnalogIndexTrigger); - } - - inline bool has_joystick(const ovrInputTrackedRemoteCapabilities &capabilities) const { - return check_bit(capabilities.ControllerCapabilities, ovrControllerCaps_HasJoystick); - } - - inline bool has_orientation_tracking(const ovrInputTrackedRemoteCapabilities &capabilities) const { - return check_bit(capabilities.ControllerCapabilities, ovrControllerCaps_HasOrientationTracking); - } - - inline bool has_position_tracking(const ovrInputTrackedRemoteCapabilities &capabilities) const { - return check_bit(capabilities.ControllerCapabilities, ovrControllerCaps_HasPositionTracking); - } - - inline bool has_trackpad(const ovrInputTrackedRemoteCapabilities &capabilities) const { - return check_bit(capabilities.ControllerCapabilities, ovrControllerCaps_HasTrackpad); - } - - inline bool is_gear_vr_controller(const ovrInputTrackedRemoteCapabilities &capabilities) const { - return check_bit(capabilities.ControllerCapabilities, ovrControllerCaps_ModelGearVR); - } - - inline bool is_oculus_go_controller(const ovrInputTrackedRemoteCapabilities &capabilities) const { - return check_bit(capabilities.ControllerCapabilities, ovrControllerCaps_ModelOculusGo); - } - - inline bool is_oculus_touch_controller(const ovrInputTrackedRemoteCapabilities &capabilities) const { - return check_bit(capabilities.ControllerCapabilities, ovrControllerCaps_ModelOculusTouch); - } - - inline bool is_left_hand_controller(const ovrInputTrackedRemoteCapabilities &capabilities) const { - return check_bit(capabilities.ControllerCapabilities, ovrControllerCaps_LeftHand); - } - - inline bool is_left_hand_controller(const ovrInputHandCapabilities &capabilities) const { - return check_bit(capabilities.HandCapabilities, ovrHandCaps_LeftHand); - } - - inline bool is_right_hand_controller(const ovrInputTrackedRemoteCapabilities &capabilities) const { - return check_bit(capabilities.ControllerCapabilities, ovrControllerCaps_RightHand); - } - - inline bool is_right_hand_controller(const ovrInputHandCapabilities &capabilities) const { - return check_bit(capabilities.HandCapabilities, ovrHandCaps_RightHand); - } - - inline ControllerHand get_controller_handedness(const ovrInputHandCapabilities &capabilities) const { - return is_left_hand_controller(capabilities) ? LEFT_HAND : RIGHT_HAND; - } - - inline ControllerHand get_controller_handedness(const ovrInputTrackedRemoteCapabilities &capabilities) const { - return is_left_hand_controller(capabilities) ? LEFT_HAND : RIGHT_HAND; - } - - inline int get_godot_hand(ControllerHand hand) { - return hand == LEFT_HAND ? /* TRACKER_LEFT_HAND */ 1 : /* TRACKER_RIGHT_HAND */ 2; - } - - const char *get_controller_model_name(const ControllerState& controller_state); - - void update_controllers_connection_state(ovrMobile *ovr, ovrJava *java); - - void update_controller_tracking_state(ovrMobile *ovr, ControllerState& controller_state, double predicted_display_time); - void update_controller_tracking_state_tracked_remote(ovrMobile *ovr, ControllerState& controller_state, double predicted_display_time); - void update_controller_tracking_state_hand(ovrMobile *ovr, ControllerState& controller_state, double predicted_display_time); - - void update_controller_input_state(ovrMobile *ovr, ControllerState& controller_state); - void update_controller_input_state_tracked_remote(ovrMobile *ovr, ControllerState& controller_state); - void update_controller_input_state_hand(ovrMobile *ovr, ControllerState& controller_state); - - void update_controller_vibration(ovrMobile *ovr, ControllerState& controller_state); + public: + struct ControllerState { + bool connected = false; + // Shows which controller is primary or most 'active'. See VRAPI_ACTIVE_INPUT_DEVICE_ID for + // reference. + bool primary = false; + int godot_controller_id = 0; + union { + ovrInputCapabilityHeader capability_header; + ovrInputTrackedRemoteCapabilities remote_capabilities; + ovrInputHandCapabilities hand_capabilities; + }; + union { + ovrInputStateHeader input_header; + ovrInputStateHand input_hand; + ovrInputStateTrackedRemote input_tracked_remote; + }; + ovrTracking tracking_state; + ovrHandPose hand_pose; + }; + + OvrMobileController(); + + ~OvrMobileController(); + + void process(ovrMobile *ovr, ovrJava *java, double predicted_display_time); + + const ControllerState *get_controller_state_by_id(int controller_id) const { + controller_id = + controller_id == kPrimaryControllerId ? get_active_controller_id() : controller_id; + + for (int hand = 0; hand < MAX_HANDS; hand++) { + auto *controller = &controllers[hand]; + if (controller->connected && controller->godot_controller_id == controller_id) { + return controller; + } + } + return nullptr; + } + + static inline bool + supports_haptic_vibration(const ovrInputTrackedRemoteCapabilities &capabilities) { + return check_bit(capabilities.ControllerCapabilities, + ovrControllerCaps_HasSimpleHapticVibration); + } + + void vibrate_controller(int controller_id, int duration_in_ms, float intensity) { + controller_id = + controller_id == kPrimaryControllerId ? get_active_controller_id() : controller_id; + // Update the controller vibration state. Actual vibration will start in the next frame via + // OvrMobileController::update_controller_vibration(...). + if (duration_in_ms > 0 && intensity > 0.0f) { + ControllerVibration vibration = { .is_vibrating = false, + .end_time_in_ms = get_time_in_ms() + duration_in_ms, + .intensity = intensity }; + controllers_vibrations[controller_id] = vibration; + } + } + + int get_active_controller_id() const { + for (int hand = 0; hand < MAX_HANDS; hand++) { + auto *controller = &controllers[hand]; + if (controller->connected && controller->primary) { + return controller->godot_controller_id; + } + } + return kInvalidGodotControllerId; + } + + private: + struct ControllerVibration { + float intensity; + double end_time_in_ms; + bool is_vibrating; + }; + + enum ControllerHand { LEFT_HAND, RIGHT_HAND, MAX_HANDS }; + + ControllerState controllers[MAX_HANDS]; + std::map controllers_vibrations; + + inline bool + has_analog_grip_trigger(const ovrInputTrackedRemoteCapabilities &capabilities) const { + return check_bit(capabilities.ControllerCapabilities, + ovrControllerCaps_HasAnalogGripTrigger); + } + + inline bool + has_analog_index_trigger(const ovrInputTrackedRemoteCapabilities &capabilities) const { + return check_bit(capabilities.ControllerCapabilities, + ovrControllerCaps_HasAnalogIndexTrigger); + } + + inline bool has_joystick(const ovrInputTrackedRemoteCapabilities &capabilities) const { + return check_bit(capabilities.ControllerCapabilities, ovrControllerCaps_HasJoystick); + } + + inline bool + has_orientation_tracking(const ovrInputTrackedRemoteCapabilities &capabilities) const { + return check_bit(capabilities.ControllerCapabilities, + ovrControllerCaps_HasOrientationTracking); + } + + inline bool has_position_tracking(const ovrInputTrackedRemoteCapabilities &capabilities) const { + return check_bit(capabilities.ControllerCapabilities, + ovrControllerCaps_HasPositionTracking); + } + + inline bool has_trackpad(const ovrInputTrackedRemoteCapabilities &capabilities) const { + return check_bit(capabilities.ControllerCapabilities, ovrControllerCaps_HasTrackpad); + } + + inline bool is_gear_vr_controller(const ovrInputTrackedRemoteCapabilities &capabilities) const { + return check_bit(capabilities.ControllerCapabilities, ovrControllerCaps_ModelGearVR); + } + + inline bool + is_oculus_go_controller(const ovrInputTrackedRemoteCapabilities &capabilities) const { + return check_bit(capabilities.ControllerCapabilities, ovrControllerCaps_ModelOculusGo); + } + + inline bool + is_oculus_touch_controller(const ovrInputTrackedRemoteCapabilities &capabilities) const { + return check_bit(capabilities.ControllerCapabilities, ovrControllerCaps_ModelOculusTouch); + } + + inline bool + is_left_touch_controller(const ovrInputTrackedRemoteCapabilities &capabilities) const { + return check_bit(capabilities.ControllerCapabilities, ovrControllerCaps_LeftHand); + } + + inline bool is_left_hand_controller(const ovrInputHandCapabilities &capabilities) const { + return check_bit(capabilities.HandCapabilities, ovrHandCaps_LeftHand); + } + + inline bool + is_right_touch_controller(const ovrInputTrackedRemoteCapabilities &capabilities) const { + return check_bit(capabilities.ControllerCapabilities, ovrControllerCaps_RightHand); + } + + inline bool is_right_hand_controller(const ovrInputHandCapabilities &capabilities) const { + return check_bit(capabilities.HandCapabilities, ovrHandCaps_RightHand); + } + + inline ControllerHand + get_controller_handedness(const ovrInputHandCapabilities &capabilities) const { + return is_left_hand_controller(capabilities) ? LEFT_HAND : RIGHT_HAND; + } + + inline ControllerHand + get_controller_handedness(const ovrInputTrackedRemoteCapabilities &capabilities) const { + return is_left_touch_controller(capabilities) ? LEFT_HAND : RIGHT_HAND; + } + + inline int get_godot_hand(ControllerHand hand) { + return hand == LEFT_HAND ? /* TRACKER_LEFT_HAND */ 1 : /* TRACKER_RIGHT_HAND */ 2; + } + + const char *get_controller_model_name(const ControllerState &controller_state); + + void update_controllers_connection_state(ovrMobile *ovr, ovrJava *java); + + void update_controller_tracking_state(ovrMobile *ovr, + ControllerState &controller_state, + double predicted_display_time); + void update_controller_tracking_state_tracked_remote(ovrMobile *ovr, + ControllerState &controller_state, + double predicted_display_time); + void update_controller_tracking_state_hand(ovrMobile *ovr, + ControllerState &controller_state, + double predicted_display_time); + + void update_controller_input_state(ovrMobile *ovr, ControllerState &controller_state); + void update_controller_input_state_tracked_remote(ovrMobile *ovr, + ControllerState &controller_state); + void update_controller_input_state_hand(ovrMobile *ovr, ControllerState &controller_state); + + void update_controller_vibration(ovrMobile *ovr, ControllerState &controller_state); }; } // namespace ovrmobile diff --git a/plugin/src/main/java/org/godotengine/plugin/vr/oculus/mobile/api/OvrDisplay.kt b/plugin/src/main/java/org/godotengine/plugin/vr/oculus/mobile/api/OvrDisplay.kt new file mode 100644 index 0000000..d5e65f3 --- /dev/null +++ b/plugin/src/main/java/org/godotengine/plugin/vr/oculus/mobile/api/OvrDisplay.kt @@ -0,0 +1,82 @@ +@file:JvmName("OvrDisplay") + +package org.godotengine.plugin.vr.oculus.mobile.api + +import org.godotengine.plugin.vr.oculus.mobile.OvrMobilePlugin + +/** + * Color space types for HMDs + * @see https://developer.oculus.com/documentation/native/android/mobile-colorspace/ + */ +enum class ColorSpace(internal val value: Int) { + /** No color correction, not recommended for production use. See notes above for more info */ + COLOR_SPACE_UNMANAGED(0), + + /** Preferred color space for standardized color across all Oculus HMDs with D65 white point */ + COLOR_SPACE_REC_2020(1), + + /** Rec. 709 is used on Oculus Go and shares the same primary color coordinates as sRGB */ + COLOR_SPACE_REC_709(2), + + /** Oculus Rift CV1 uses a unique color space, see enum description for more info */ + COLOR_SPACE_RIFT_CV1(3), + + /** Oculus Rift S uses a unique color space, see enum description for more info */ + COLOR_SPACE_RIFT_S(4), + + /** Oculus Quest's native color space is slightly different than Rift CV1 */ + COLOR_SPACE_QUEST(5), + + /** Similar to DCI-P3. See notes above for more details on P3 */ + COLOR_SPACE_P3(6), + + /** Similar to sRGB but with deeper greens using D65 white point */ + COLOR_SPACE_ADOBE_RGB(7); + + companion object { + fun toColorSpace(value: Int): ColorSpace { + for (colorSpace in values()) { + if (colorSpace.value == value) { + return colorSpace + } + } + return COLOR_SPACE_UNMANAGED + } + } +} + +/** + * Used to retrieve the device color space. + * This is a constant for each device type. + * @see https://developer.oculus.com/documentation/native/android/mobile-colorspace/ + */ +fun OvrMobilePlugin.getColorSpace() = ColorSpace.toColorSpace(nativeGetColorSpace()) + +/** + * Used to update the device color space. + * + * @param[colorSpace] The new target color space. + * @return True if the device's color space was updated, false otherwise. + */ +fun OvrMobilePlugin.setColorSpace(colorSpace: ColorSpace) = nativeSetColorSpace(colorSpace.value) + +/** + * Used to access the display refresh rates supported by the device. + */ +fun OvrMobilePlugin.getSupportedDisplayRefreshRates() = nativeGetSupportedDisplayRefreshRates() + +/** + * Used to update the device display refresh rate. + * + * @param[refreshRate] Target refresh rate. Must be one of the supported values returned by + * [getSupportedDisplayRefreshRates]. + */ +fun OvrMobilePlugin.setDisplayRefreshRate(refreshRate: Float) = nativeSetDisplayRefreshRate(refreshRate) + +private external fun nativeSetColorSpace(colorSpace: Int): Boolean + +private external fun nativeGetColorSpace(): Int + +private external fun nativeSetDisplayRefreshRate(refreshRate: Float): Boolean + +private external fun nativeGetSupportedDisplayRefreshRates(): FloatArray diff --git a/plugin/src/main/java/org/godotengine/plugin/vr/oculus/mobile/api/OvrDisplayRefreshRate.kt b/plugin/src/main/java/org/godotengine/plugin/vr/oculus/mobile/api/OvrDisplayRefreshRate.kt deleted file mode 100644 index 31257b0..0000000 --- a/plugin/src/main/java/org/godotengine/plugin/vr/oculus/mobile/api/OvrDisplayRefreshRate.kt +++ /dev/null @@ -1,13 +0,0 @@ -@file:JvmName("OvrDisplayRefreshRate") - -package org.godotengine.plugin.vr.oculus.mobile.api - -import org.godotengine.plugin.vr.oculus.mobile.OvrMobilePlugin - -fun OvrMobilePlugin.getSupportedDisplayRefreshRates() = nativeGetSupportedDisplayRefreshRates() - -fun OvrMobilePlugin.setDisplayRefreshRate(refreshRate: Float) = nativeSetDisplayRefreshRate(refreshRate) - -private external fun nativeSetDisplayRefreshRate(refreshRate: Float): Boolean - -private external fun nativeGetSupportedDisplayRefreshRates(): FloatArray \ No newline at end of file diff --git a/plugin/src/main/java/org/godotengine/plugin/vr/oculus/mobile/api/OvrInput.kt b/plugin/src/main/java/org/godotengine/plugin/vr/oculus/mobile/api/OvrInput.kt index 186bc74..2c40c11 100644 --- a/plugin/src/main/java/org/godotengine/plugin/vr/oculus/mobile/api/OvrInput.kt +++ b/plugin/src/main/java/org/godotengine/plugin/vr/oculus/mobile/api/OvrInput.kt @@ -9,6 +9,42 @@ import org.godotengine.plugin.vr.oculus.mobile.OvrMobilePlugin private const val PRIMARY_CONTROLLER_ID = -1 +/** + * Specifies which controller is connected + */ +enum class ControllerType(internal val value: Int) { + CONTROLLER_TYPE_NONE(0), + + /** + * < LTouch in CAPI + */ + CONTROLLER_TYPE_RESERVED_0(1 shl 0), + + /** + * < RTouch in CAPI + */ + CONTROLLER_TYPE_RESERVED_1(1 shl 1), + CONTROLLER_TYPE_TRACKED_REMOTE(1 shl 2), + + /** + * Deprecated, will be removed in a future release + */ + CONTROLLER_TYPE_GAMEPAD(1 shl 4), + CONTROLLER_TYPE_HAND(1 shl 5), + CONTROLLER_TYPE_STANDARD_POINTER(1 shl 7); + + companion object { + fun toControllerType(value: Int): ControllerType { + for (controllerType in values()) { + if (controllerType.value == value) { + return controllerType + } + } + return CONTROLLER_TYPE_NONE + } + } +} + /** * Vibrate the controller at the given intensity. * @param controllerId Id of the controller to vibrate. Defaults to the primary controller id. @@ -23,3 +59,11 @@ external fun OvrMobilePlugin.vibrateController(controllerId: Int = PRIMARY_CONTR * Returns -1 if there is no primary controller. */ external fun OvrMobilePlugin.getPrimaryControllerId(): Int + +/** + * Return the [ControllerType] type of the primary controller. + */ +fun OvrMobilePlugin.getPrimaryControllerType() = + ControllerType.toControllerType(nativeGetPrimaryControllerType()) + +private external fun nativeGetPrimaryControllerType(): Int diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..c140f5b --- /dev/null +++ b/settings.gradle @@ -0,0 +1,4 @@ +rootProject.name = "Godot Oculus Mobile Plugin" + +include ":OVRMobile" +project(":OVRMobile").projectDir = file("plugin") diff --git a/settings.gradle.kts b/settings.gradle.kts deleted file mode 100644 index 5645c3b..0000000 --- a/settings.gradle.kts +++ /dev/null @@ -1,4 +0,0 @@ -rootProject.name = "Godot Oculus Mobile Plugin" - -include(":OVRMobile") -project(":OVRMobile").projectDir = File("plugin")