From e4b7c25e721ce3435a029087e3917a30aa73f06b Mon Sep 17 00:00:00 2001 From: David Snopek Date: Thu, 27 Mar 2025 07:30:02 -0500 Subject: [PATCH 01/41] gdextension: Sync with upstream commit 49a5bc7b616bd04689a2c89e89bda41f50241464 (4.4.1-stable) --- gdextension/extension_api.json | 72 +++++++++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 6 deletions(-) diff --git a/gdextension/extension_api.json b/gdextension/extension_api.json index d80c52cff..a4a1b5631 100644 --- a/gdextension/extension_api.json +++ b/gdextension/extension_api.json @@ -2,10 +2,10 @@ "header": { "version_major": 4, "version_minor": 4, - "version_patch": 0, + "version_patch": 1, "version_status": "stable", "version_build": "official", - "version_full_name": "Godot Engine v4.4.stable.official" + "version_full_name": "Godot Engine v4.4.1.stable.official" }, "builtin_class_sizes": [ { @@ -165923,6 +165923,10 @@ "name": "NOTIFICATION_VP_MOUSE_EXIT", "value": 1011 }, + { + "name": "NOTIFICATION_WM_POSITION_CHANGED", + "value": 1012 + }, { "name": "NOTIFICATION_OS_MEMORY_WARNING", "value": 2009 @@ -174693,7 +174697,7 @@ "is_refcounted": false, "is_instantiable": true, "inherits": "PanelContainer", - "api_type": "core", + "api_type": "editor", "methods": [ { "name": "get_binding_modifier", @@ -176926,14 +176930,14 @@ "is_refcounted": false, "is_instantiable": true, "inherits": "OpenXRInteractionProfileEditorBase", - "api_type": "core" + "api_type": "editor" }, { "name": "OpenXRInteractionProfileEditorBase", "is_refcounted": false, "is_instantiable": false, "inherits": "HBoxContainer", - "api_type": "core", + "api_type": "editor", "methods": [ { "name": "setup", @@ -218765,8 +218769,64 @@ "value": 217 }, { - "name": "DATA_FORMAT_MAX", + "name": "DATA_FORMAT_ASTC_4x4_SFLOAT_BLOCK", "value": 218 + }, + { + "name": "DATA_FORMAT_ASTC_5x4_SFLOAT_BLOCK", + "value": 219 + }, + { + "name": "DATA_FORMAT_ASTC_5x5_SFLOAT_BLOCK", + "value": 220 + }, + { + "name": "DATA_FORMAT_ASTC_6x5_SFLOAT_BLOCK", + "value": 221 + }, + { + "name": "DATA_FORMAT_ASTC_6x6_SFLOAT_BLOCK", + "value": 222 + }, + { + "name": "DATA_FORMAT_ASTC_8x5_SFLOAT_BLOCK", + "value": 223 + }, + { + "name": "DATA_FORMAT_ASTC_8x6_SFLOAT_BLOCK", + "value": 224 + }, + { + "name": "DATA_FORMAT_ASTC_8x8_SFLOAT_BLOCK", + "value": 225 + }, + { + "name": "DATA_FORMAT_ASTC_10x5_SFLOAT_BLOCK", + "value": 226 + }, + { + "name": "DATA_FORMAT_ASTC_10x6_SFLOAT_BLOCK", + "value": 227 + }, + { + "name": "DATA_FORMAT_ASTC_10x8_SFLOAT_BLOCK", + "value": 228 + }, + { + "name": "DATA_FORMAT_ASTC_10x10_SFLOAT_BLOCK", + "value": 229 + }, + { + "name": "DATA_FORMAT_ASTC_12x10_SFLOAT_BLOCK", + "value": 230 + }, + { + "name": "DATA_FORMAT_ASTC_12x12_SFLOAT_BLOCK", + "value": 231 + }, + { + "name": "DATA_FORMAT_MAX", + "value": 232 } ] }, From 6fcc184587094056f74e777abc8ffd5ee30a73c4 Mon Sep 17 00:00:00 2001 From: Thaddeus Crews Date: Fri, 7 Mar 2025 17:52:09 -0600 Subject: [PATCH 02/41] Style: Integrate `#pragma once` in builders/checks (cherry picked from commit 107cb1da5ea65e4bf46225f8b5e79be9fcc141e4) --- binding_generator.py | 74 ++++--------------- misc/scripts/header_guards.py | 131 ++++++++++++---------------------- 2 files changed, 59 insertions(+), 146 deletions(-) diff --git a/binding_generator.py b/binding_generator.py index 1efc5b4ef..9697687fb 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -51,11 +51,7 @@ def generate_mod_version(argcount, const=False, returns=False): def generate_wrappers(target): max_versions = 12 - txt = """ -#ifndef GDEXTENSION_WRAPPERS_GEN_H -#define GDEXTENSION_WRAPPERS_GEN_H - -""" + txt = "#pragma once" for i in range(max_versions + 1): txt += "\n/* Module Wrapper " + str(i) + " Arguments */\n" @@ -64,8 +60,6 @@ def generate_wrappers(target): txt += generate_mod_version(i, True, False) txt += generate_mod_version(i, True, True) - txt += "\n#endif\n" - with open(target, "w", encoding="utf-8") as f: f.write(txt) @@ -187,8 +181,7 @@ def generate_virtuals(target): max_versions = 12 txt = """/* THIS FILE IS GENERATED DO NOT EDIT */ -#ifndef GDEXTENSION_GDVIRTUAL_GEN_H -#define GDEXTENSION_GDVIRTUAL_GEN_H +#pragma once """ @@ -203,8 +196,6 @@ def generate_virtuals(target): txt += generate_virtual_version(i, True, False, True) txt += generate_virtual_version(i, True, True, True) - txt += "#endif // GDEXTENSION_GDVIRTUAL_GEN_H\n" - with open(target, "w", encoding="utf-8") as f: f.write(txt) @@ -364,11 +355,8 @@ def generate_builtin_bindings(api, output_dir, build_config): variant_size_source = [] add_header("variant_size.hpp", variant_size_source) - header_guard = "GODOT_CPP_VARIANT_SIZE_HPP" - variant_size_source.append(f"#ifndef {header_guard}") - variant_size_source.append(f"#define {header_guard}") + variant_size_source.append("#pragma once") variant_size_source.append(f'#define GODOT_CPP_VARIANT_SIZE {builtin_sizes["Variant"]}') - variant_size_source.append(f"#endif // ! {header_guard}") variant_size_file.write("\n".join(variant_size_source)) @@ -448,8 +436,7 @@ def generate_builtin_bindings(api, output_dir, build_config): builtin_header = [] add_header("builtin_types.hpp", builtin_header) - builtin_header.append("#ifndef GODOT_CPP_BUILTIN_TYPES_HPP") - builtin_header.append("#define GODOT_CPP_BUILTIN_TYPES_HPP") + builtin_header.append("#pragma once") builtin_header.append("") @@ -464,8 +451,6 @@ def generate_builtin_bindings(api, output_dir, build_config): builtin_header.append("") - builtin_header.append("#endif // ! GODOT_CPP_BUILTIN_TYPES_HPP") - builtin_header_file.write("\n".join(builtin_header)) # Create a header with bindings for builtin types. @@ -474,8 +459,7 @@ def generate_builtin_bindings(api, output_dir, build_config): builtin_binds = [] add_header("builtin_binds.hpp", builtin_binds) - builtin_binds.append("#ifndef GODOT_CPP_BUILTIN_BINDS_HPP") - builtin_binds.append("#define GODOT_CPP_BUILTIN_BINDS_HPP") + builtin_binds.append("#pragma once") builtin_binds.append("") builtin_binds.append("#include ") builtin_binds.append("") @@ -487,7 +471,6 @@ def generate_builtin_bindings(api, output_dir, build_config): builtin_binds.append(f"VARIANT_ENUM_CAST({builtin_api['name']}::{enum_api['name']});") builtin_binds.append("") - builtin_binds.append("#endif // ! GODOT_CPP_BUILTIN_BINDS_HPP") builtin_binds_file.write("\n".join(builtin_binds)) @@ -503,9 +486,7 @@ def generate_builtin_class_vararg_method_implements_header(builtin_classes): add_header("builtin_vararg_methods.hpp", result) - header_guard = "GODOT_CPP_BUILTIN_VARARG_METHODS_HPP" - result.append(f"#ifndef {header_guard}") - result.append(f"#define {header_guard}") + result.append("#pragma once") result.append("") for builtin_api in builtin_classes: if "methods" not in builtin_api: @@ -520,8 +501,6 @@ def generate_builtin_class_vararg_method_implements_header(builtin_classes): ) result.append("") - result.append(f"#endif // ! {header_guard}") - return "\n".join(result) @@ -531,12 +510,9 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl class_name = builtin_api["name"] snake_class_name = camel_to_snake(class_name).upper() - header_guard = f"GODOT_CPP_{snake_class_name}_HPP" - add_header(f"{snake_class_name.lower()}.hpp", result) - result.append(f"#ifndef {header_guard}") - result.append(f"#define {header_guard}") + result.append("#pragma once") result.append("") result.append("#include ") @@ -965,8 +941,6 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl result.append("") result.append("} // namespace godot") - result.append("") - result.append(f"#endif // ! {header_guard}") result.append("") return "\n".join(result) @@ -1498,9 +1472,7 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node): result = [] add_header(f"{snake_struct_name}.hpp", result) - header_guard = f"GODOT_CPP_{snake_struct_name.upper()}_HPP" - result.append(f"#ifndef {header_guard}") - result.append(f"#define {header_guard}") + result.append("#pragma once") used_classes = [] expanded_format = native_struct["format"].replace("(", " ").replace(")", ";").replace(",", ";") @@ -1540,7 +1512,6 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node): result.append("") result.append("} // namespace godot") result.append("") - result.append(f"#endif // ! {header_guard}") with header_filename.open("w+", encoding="utf-8") as header_file: header_file.write("\n".join(result)) @@ -1556,11 +1527,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us add_header(f"{snake_class_name.lower()}.hpp", result) - header_guard = f"GODOT_CPP_{snake_class_name}_HPP" - - result.append(f"#ifndef {header_guard}") - result.append(f"#define {header_guard}") - + result.append("#pragma once") result.append("") if len(fully_used_classes) > 0: @@ -1849,7 +1816,6 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us result.append("\t") result.append("") - result.append(f"#endif // ! {header_guard}") result.append("") return "\n".join(result) @@ -2051,9 +2017,7 @@ def generate_global_constants(api, output_dir): header_filename = include_gen_folder / "global_constants.hpp" - header_guard = "GODOT_CPP_GLOBAL_CONSTANTS_HPP" - header.append(f"#ifndef {header_guard}") - header.append(f"#define {header_guard}") + header.append("#pragma once") header.append("") header.append("#include ") header.append("") @@ -2083,7 +2047,6 @@ def generate_global_constants(api, output_dir): header.append("} // namespace godot") header.append("") - header.append(f"#endif // ! {header_guard}") with header_filename.open("w+", encoding="utf-8") as header_file: header_file.write("\n".join(header)) @@ -2099,9 +2062,7 @@ def generate_version_header(api, output_dir): header_file_path = include_gen_folder / header_filename - header_guard = "GODOT_CPP_VERSION_HPP" - header.append(f"#ifndef {header_guard}") - header.append(f"#define {header_guard}") + header.append("#pragma once") header.append("") header.append(f"#define GODOT_VERSION_MAJOR {api['header']['version_major']}") @@ -2110,8 +2071,6 @@ def generate_version_header(api, output_dir): header.append(f"#define GODOT_VERSION_STATUS \"{api['header']['version_status']}\"") header.append(f"#define GODOT_VERSION_BUILD \"{api['header']['version_build']}\"") - header.append("") - header.append(f"#endif // {header_guard}") header.append("") with header_file_path.open("w+", encoding="utf-8") as header_file: @@ -2132,9 +2091,7 @@ def generate_global_constant_binds(api, output_dir): header_filename = include_gen_folder / "global_constants_binds.hpp" - header_guard = "GODOT_CPP_GLOBAL_CONSTANTS_BINDS_HPP" - header.append(f"#ifndef {header_guard}") - header.append(f"#define {header_guard}") + header.append("#pragma once") header.append("") header.append("#include ") header.append("") @@ -2153,8 +2110,6 @@ def generate_global_constant_binds(api, output_dir): header.append("") - header.append(f"#endif // ! {header_guard}") - with header_filename.open("w+", encoding="utf-8") as header_file: header_file.write("\n".join(header)) @@ -2173,9 +2128,7 @@ def generate_utility_functions(api, output_dir): header_filename = include_gen_folder / "utility_functions.hpp" - header_guard = "GODOT_CPP_UTILITY_FUNCTIONS_HPP" - header.append(f"#ifndef {header_guard}") - header.append(f"#define {header_guard}") + header.append("#pragma once") header.append("") header.append("#include ") header.append("#include ") @@ -2214,7 +2167,6 @@ def generate_utility_functions(api, output_dir): header.append("") header.append("} // namespace godot") header.append("") - header.append(f"#endif // ! {header_guard}") with header_filename.open("w+", encoding="utf-8") as header_file: header_file.write("\n".join(header)) diff --git a/misc/scripts/header_guards.py b/misc/scripts/header_guards.py index c99c42200..63a6b75ff 100644 --- a/misc/scripts/header_guards.py +++ b/misc/scripts/header_guards.py @@ -2,121 +2,82 @@ # -*- coding: utf-8 -*- import sys -from pathlib import Path if len(sys.argv) < 2: print("Invalid usage of header_guards.py, it should be called with a path to one or multiple files.") sys.exit(1) -HEADER_CHECK_OFFSET = 30 -HEADER_BEGIN_OFFSET = 31 -HEADER_END_OFFSET = -1 - changed = [] invalid = [] for file in sys.argv[1:]: - with open(file, "rt", encoding="utf-8", newline="\n") as f: - lines = f.readlines() + header_start = -1 + header_end = -1 - if len(lines) <= HEADER_BEGIN_OFFSET: - continue # Most likely a dummy file. + with open(file.strip(), "rt", encoding="utf-8", newline="\n") as f: + lines = f.readlines() - if lines[HEADER_CHECK_OFFSET].startswith("#import"): - continue # Early catch obj-c file. + for idx, line in enumerate(lines): + sline = line.strip() + + if header_start < 0: + if sline == "": # Skip empty lines at the top. + continue + + if sline.startswith("/**********"): # Godot header starts this way. + header_start = idx + else: + header_end = 0 # There is no Godot header. + break + else: + if not sline.startswith(("*", "/*")): # Not in the Godot header anymore. + header_end = idx + 1 # The guard should be two lines below the Godot header. + break + + if (HEADER_CHECK_OFFSET := header_end) < 0 or HEADER_CHECK_OFFSET >= len(lines): + invalid.append(file) + continue - name = f"GODOT_{Path(file).name}".upper().replace(".", "_").replace("-", "_").replace(" ", "_") + if lines[HEADER_CHECK_OFFSET].startswith("#pragma once"): + continue - HEADER_CHECK = f"#ifndef {name}\n" - HEADER_BEGIN = f"#define {name}\n" - HEADER_END = f"#endif // {name}\n" + # Might be using legacy header guards. + HEADER_BEGIN_OFFSET = HEADER_CHECK_OFFSET + 1 + HEADER_END_OFFSET = len(lines) - 1 - if ( - lines[HEADER_CHECK_OFFSET] == HEADER_CHECK - and lines[HEADER_BEGIN_OFFSET] == HEADER_BEGIN - and lines[HEADER_END_OFFSET] == HEADER_END - ): + if HEADER_BEGIN_OFFSET >= HEADER_END_OFFSET: + invalid.append(file) continue - # Guards might exist but with the wrong names. if ( lines[HEADER_CHECK_OFFSET].startswith("#ifndef") and lines[HEADER_BEGIN_OFFSET].startswith("#define") and lines[HEADER_END_OFFSET].startswith("#endif") ): - lines[HEADER_CHECK_OFFSET] = HEADER_CHECK - lines[HEADER_BEGIN_OFFSET] = HEADER_BEGIN - lines[HEADER_END_OFFSET] = HEADER_END + lines[HEADER_CHECK_OFFSET] = "#pragma once" + lines[HEADER_BEGIN_OFFSET] = "\n" + lines.pop() with open(file, "wt", encoding="utf-8", newline="\n") as f: f.writelines(lines) changed.append(file) continue - header_check = -1 - header_begin = -1 - header_end = -1 - pragma_once = -1 - objc = False - - for idx, line in enumerate(lines): - if not line.startswith("#"): - continue - elif line.startswith("#ifndef") and header_check == -1: - header_check = idx - elif line.startswith("#define") and header_begin == -1: - header_begin = idx - elif line.startswith("#endif") and header_end == -1: - header_end = idx - elif line.startswith("#pragma once"): - pragma_once = idx + # Verify `#pragma once` doesn't exist at invalid location. + misplaced = False + for line in lines: + if line.startswith("#pragma once"): + misplaced = True break - elif line.startswith("#import"): - objc = True - break - - if objc: - continue - if pragma_once != -1: - lines.pop(pragma_once) - lines.insert(HEADER_CHECK_OFFSET, HEADER_CHECK) - lines.insert(HEADER_BEGIN_OFFSET, HEADER_BEGIN) - lines.append("\n") - lines.append(HEADER_END) - with open(file, "wt", encoding="utf-8", newline="\n") as f: - f.writelines(lines) - changed.append(file) - continue - - if header_check == -1 and header_begin == -1 and header_end == -1: - # Guards simply didn't exist - lines.insert(HEADER_CHECK_OFFSET, HEADER_CHECK) - lines.insert(HEADER_BEGIN_OFFSET, HEADER_BEGIN) - lines.append("\n") - lines.append(HEADER_END) - with open(file, "wt", encoding="utf-8", newline="\n") as f: - f.writelines(lines) - changed.append(file) + if misplaced: + invalid.append(file) continue - if header_check != -1 and header_begin != -1 and header_end != -1: - # All prepends "found", see if we can salvage this. - if header_check == header_begin - 1 and header_begin < header_end: - lines.pop(header_check) - lines.pop(header_begin - 1) - lines.pop(header_end - 2) - if lines[header_end - 3] == "\n": - lines.pop(header_end - 3) - lines.insert(HEADER_CHECK_OFFSET, HEADER_CHECK) - lines.insert(HEADER_BEGIN_OFFSET, HEADER_BEGIN) - lines.append("\n") - lines.append(HEADER_END) - with open(file, "wt", encoding="utf-8", newline="\n") as f: - f.writelines(lines) - changed.append(file) - continue - - invalid.append(file) + # Assume that we're simply missing a guard entirely. + lines.insert(HEADER_CHECK_OFFSET, "#pragma once\n\n") + with open(file, "wt", encoding="utf-8", newline="\n") as f: + f.writelines(lines) + changed.append(file) if changed: for file in changed: From f166d4ed8c59f5198bf3992c7f8d9de77fcd40a5 Mon Sep 17 00:00:00 2001 From: Thaddeus Crews Date: Fri, 7 Mar 2025 17:58:10 -0600 Subject: [PATCH 03/41] Style: Replace header guards with `#pragma once` (cherry picked from commit 7056c996dd43ae1aa466c94d95cc2fe63853d8a9) --- include/godot_cpp/classes/editor_plugin_registration.hpp | 5 +---- include/godot_cpp/classes/ref.hpp | 5 +---- include/godot_cpp/classes/wrapped.hpp | 5 +---- include/godot_cpp/core/binder_common.hpp | 5 +---- include/godot_cpp/core/builtin_ptrcall.hpp | 5 +---- include/godot_cpp/core/class_db.hpp | 5 +---- include/godot_cpp/core/defs.hpp | 5 +---- include/godot_cpp/core/engine_ptrcall.hpp | 5 +---- include/godot_cpp/core/error_macros.hpp | 5 +---- include/godot_cpp/core/math.hpp | 5 +---- include/godot_cpp/core/memory.hpp | 5 +---- include/godot_cpp/core/method_bind.hpp | 5 +---- include/godot_cpp/core/method_ptrcall.hpp | 5 +---- include/godot_cpp/core/mutex_lock.hpp | 5 +---- include/godot_cpp/core/object.hpp | 5 +---- include/godot_cpp/core/object_id.hpp | 5 +---- include/godot_cpp/core/print_string.hpp | 5 +---- include/godot_cpp/core/property_info.hpp | 5 +---- include/godot_cpp/core/type_info.hpp | 5 +---- include/godot_cpp/godot.hpp | 5 +---- include/godot_cpp/templates/cowdata.hpp | 5 +---- include/godot_cpp/templates/hash_map.hpp | 5 +---- include/godot_cpp/templates/hash_set.hpp | 5 +---- include/godot_cpp/templates/hashfuncs.hpp | 5 +---- include/godot_cpp/templates/list.hpp | 5 +---- include/godot_cpp/templates/local_vector.hpp | 5 +---- include/godot_cpp/templates/pair.hpp | 5 +---- include/godot_cpp/templates/rb_map.hpp | 5 +---- include/godot_cpp/templates/rb_set.hpp | 5 +---- include/godot_cpp/templates/rid_owner.hpp | 5 +---- include/godot_cpp/templates/safe_refcount.hpp | 5 +---- include/godot_cpp/templates/search_array.hpp | 5 +---- include/godot_cpp/templates/self_list.hpp | 5 +---- include/godot_cpp/templates/sort_array.hpp | 5 +---- include/godot_cpp/templates/spin_lock.hpp | 5 +---- include/godot_cpp/templates/thread_work_pool.hpp | 5 +---- include/godot_cpp/templates/vector.hpp | 5 +---- include/godot_cpp/templates/vmap.hpp | 5 +---- include/godot_cpp/templates/vset.hpp | 5 +---- include/godot_cpp/variant/aabb.hpp | 5 +---- include/godot_cpp/variant/array_helpers.hpp | 5 +---- include/godot_cpp/variant/basis.hpp | 5 +---- include/godot_cpp/variant/callable_custom.hpp | 5 +---- include/godot_cpp/variant/callable_method_pointer.hpp | 5 +---- include/godot_cpp/variant/char_string.hpp | 5 +---- include/godot_cpp/variant/char_utils.hpp | 5 +---- include/godot_cpp/variant/color.hpp | 5 +---- include/godot_cpp/variant/color_names.inc.hpp | 5 +---- include/godot_cpp/variant/plane.hpp | 5 +---- include/godot_cpp/variant/projection.hpp | 5 +---- include/godot_cpp/variant/quaternion.hpp | 5 +---- include/godot_cpp/variant/rect2.hpp | 5 +---- include/godot_cpp/variant/rect2i.hpp | 5 +---- include/godot_cpp/variant/transform2d.hpp | 5 +---- include/godot_cpp/variant/transform3d.hpp | 5 +---- include/godot_cpp/variant/typed_array.hpp | 5 +---- include/godot_cpp/variant/typed_dictionary.hpp | 5 +---- include/godot_cpp/variant/variant.hpp | 5 +---- include/godot_cpp/variant/variant_internal.hpp | 5 +---- include/godot_cpp/variant/vector2.hpp | 5 +---- include/godot_cpp/variant/vector2i.hpp | 5 +---- include/godot_cpp/variant/vector3.hpp | 5 +---- include/godot_cpp/variant/vector3i.hpp | 5 +---- include/godot_cpp/variant/vector4.hpp | 5 +---- include/godot_cpp/variant/vector4i.hpp | 5 +---- test/src/example.h | 5 +---- test/src/register_types.h | 5 +---- test/src/tests.h | 5 +---- 68 files changed, 68 insertions(+), 272 deletions(-) diff --git a/include/godot_cpp/classes/editor_plugin_registration.hpp b/include/godot_cpp/classes/editor_plugin_registration.hpp index 7870bfc70..366008a43 100644 --- a/include/godot_cpp/classes/editor_plugin_registration.hpp +++ b/include/godot_cpp/classes/editor_plugin_registration.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_EDITOR_PLUGIN_REGISTRATION_HPP -#define GODOT_EDITOR_PLUGIN_REGISTRATION_HPP +#pragma once #include @@ -58,5 +57,3 @@ class EditorPlugins { }; } // namespace godot - -#endif // GODOT_EDITOR_PLUGIN_REGISTRATION_HPP diff --git a/include/godot_cpp/classes/ref.hpp b/include/godot_cpp/classes/ref.hpp index 8511fe4c2..8a5a9aa9f 100644 --- a/include/godot_cpp/classes/ref.hpp +++ b/include/godot_cpp/classes/ref.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_REF_HPP -#define GODOT_REF_HPP +#pragma once #include @@ -284,5 +283,3 @@ struct GetTypeInfo &, typename EnableIf }; } // namespace godot - -#endif // GODOT_REF_HPP diff --git a/include/godot_cpp/classes/wrapped.hpp b/include/godot_cpp/classes/wrapped.hpp index 7a07dcb1c..2b4a9035e 100644 --- a/include/godot_cpp/classes/wrapped.hpp +++ b/include/godot_cpp/classes/wrapped.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_WRAPPED_HPP -#define GODOT_WRAPPED_HPP +#pragma once #include @@ -511,5 +510,3 @@ public: #define GDVIRTUAL_BIND(m_name, ...) ::godot::ClassDB::add_virtual_method(get_class_static(), _gdvirtual_##m_name##_get_method_info(), ::godot::snarray(__VA_ARGS__)); #define GDVIRTUAL_IS_OVERRIDDEN(m_name) _gdvirtual_##m_name##_overridden() #define GDVIRTUAL_IS_OVERRIDDEN_PTR(m_obj, m_name) m_obj->_gdvirtual_##m_name##_overridden() - -#endif // GODOT_WRAPPED_HPP diff --git a/include/godot_cpp/core/binder_common.hpp b/include/godot_cpp/core/binder_common.hpp index 26ed4ca39..6a8777350 100644 --- a/include/godot_cpp/core/binder_common.hpp +++ b/include/godot_cpp/core/binder_common.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_BINDER_COMMON_HPP -#define GODOT_BINDER_COMMON_HPP +#pragma once #include @@ -692,5 +691,3 @@ void call_with_ptr_args_static_method_ret(R (*p_method)(P...), const GDExtension #include #include - -#endif // GODOT_BINDER_COMMON_HPP diff --git a/include/godot_cpp/core/builtin_ptrcall.hpp b/include/godot_cpp/core/builtin_ptrcall.hpp index 286051fa8..cf5310e2d 100644 --- a/include/godot_cpp/core/builtin_ptrcall.hpp +++ b/include/godot_cpp/core/builtin_ptrcall.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_BUILTIN_PTRCALL_HPP -#define GODOT_BUILTIN_PTRCALL_HPP +#pragma once #include #include @@ -88,5 +87,3 @@ T _call_builtin_ptr_getter(const GDExtensionPtrGetter getter, GDExtensionConstTy } // namespace internal } // namespace godot - -#endif // GODOT_BUILTIN_PTRCALL_HPP diff --git a/include/godot_cpp/core/class_db.hpp b/include/godot_cpp/core/class_db.hpp index ca20c44f0..1dcfebe3e 100644 --- a/include/godot_cpp/core/class_db.hpp +++ b/include/godot_cpp/core/class_db.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_CLASS_DB_HPP -#define GODOT_CLASS_DB_HPP +#pragma once #include @@ -370,5 +369,3 @@ MethodBind *ClassDB::bind_vararg_method(uint32_t p_flags, StringName p_name, M p } // namespace godot CLASSDB_SINGLETON_VARIANT_CAST; - -#endif // GODOT_CLASS_DB_HPP diff --git a/include/godot_cpp/core/defs.hpp b/include/godot_cpp/core/defs.hpp index 07ce14d3d..c5115aa9a 100644 --- a/include/godot_cpp/core/defs.hpp +++ b/include/godot_cpp/core/defs.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_DEFS_HPP -#define GODOT_DEFS_HPP +#pragma once #include #include @@ -130,5 +129,3 @@ struct BuildIndexSequence<0, Is...> : IndexSequence {}; // To maintain compatibility an alias is defined outside the namespace. // Consider it deprecated. using real_t = godot::real_t; - -#endif // GODOT_DEFS_HPP diff --git a/include/godot_cpp/core/engine_ptrcall.hpp b/include/godot_cpp/core/engine_ptrcall.hpp index 555806b8e..c8c80041a 100644 --- a/include/godot_cpp/core/engine_ptrcall.hpp +++ b/include/godot_cpp/core/engine_ptrcall.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_ENGINE_PTRCALL_HPP -#define GODOT_ENGINE_PTRCALL_HPP +#pragma once #include @@ -93,5 +92,3 @@ void _call_utility_no_ret(const GDExtensionPtrUtilityFunction func, const Args & } // namespace internal } // namespace godot - -#endif // GODOT_ENGINE_PTRCALL_HPP diff --git a/include/godot_cpp/core/error_macros.hpp b/include/godot_cpp/core/error_macros.hpp index a27c2cb02..1337b0b70 100644 --- a/include/godot_cpp/core/error_macros.hpp +++ b/include/godot_cpp/core/error_macros.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_ERROR_MACROS_HPP -#define GODOT_ERROR_MACROS_HPP +#pragma once #include @@ -802,5 +801,3 @@ void _err_flush_stdout(); #define CHECK_METHOD_BIND_RET(m_mb, m_ret) #define CHECK_METHOD_BIND(m_mb) #endif - -#endif // GODOT_ERROR_MACROS_HPP diff --git a/include/godot_cpp/core/math.hpp b/include/godot_cpp/core/math.hpp index 1949360a9..7da52109f 100644 --- a/include/godot_cpp/core/math.hpp +++ b/include/godot_cpp/core/math.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_MATH_HPP -#define GODOT_MATH_HPP +#pragma once #include @@ -815,5 +814,3 @@ inline float snap_scalar_separation(float p_offset, float p_step, float p_target } // namespace Math } // namespace godot - -#endif // GODOT_MATH_HPP diff --git a/include/godot_cpp/core/memory.hpp b/include/godot_cpp/core/memory.hpp index 1934ee458..4905ba897 100644 --- a/include/godot_cpp/core/memory.hpp +++ b/include/godot_cpp/core/memory.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_MEMORY_HPP -#define GODOT_MEMORY_HPP +#pragma once #include #include @@ -216,5 +215,3 @@ struct _GlobalNilClass { }; } // namespace godot - -#endif // GODOT_MEMORY_HPP diff --git a/include/godot_cpp/core/method_bind.hpp b/include/godot_cpp/core/method_bind.hpp index f2da66ce0..07d51be6e 100644 --- a/include/godot_cpp/core/method_bind.hpp +++ b/include/godot_cpp/core/method_bind.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_METHOD_BIND_HPP -#define GODOT_METHOD_BIND_HPP +#pragma once #include #include @@ -731,5 +730,3 @@ MethodBind *create_static_method_bind(R (*p_method)(P...)) { } } // namespace godot - -#endif // GODOT_METHOD_BIND_HPP diff --git a/include/godot_cpp/core/method_ptrcall.hpp b/include/godot_cpp/core/method_ptrcall.hpp index 8889e8214..8c84dbc75 100644 --- a/include/godot_cpp/core/method_ptrcall.hpp +++ b/include/godot_cpp/core/method_ptrcall.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_METHOD_PTRCALL_HPP -#define GODOT_METHOD_PTRCALL_HPP +#pragma once #include @@ -234,5 +233,3 @@ GDVIRTUAL_NATIVE_PTR(float); GDVIRTUAL_NATIVE_PTR(double); } // namespace godot - -#endif // GODOT_METHOD_PTRCALL_HPP diff --git a/include/godot_cpp/core/mutex_lock.hpp b/include/godot_cpp/core/mutex_lock.hpp index aa81d4dcd..4d0029a9b 100644 --- a/include/godot_cpp/core/mutex_lock.hpp +++ b/include/godot_cpp/core/mutex_lock.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_MUTEX_LOCK_HPP -#define GODOT_MUTEX_LOCK_HPP +#pragma once #include @@ -55,5 +54,3 @@ class MutexLock { #define _THREAD_SAFE_UNLOCK_ _thread_safe_.unlock(); } // namespace godot - -#endif // GODOT_MUTEX_LOCK_HPP diff --git a/include/godot_cpp/core/object.hpp b/include/godot_cpp/core/object.hpp index 917ec6cc4..9eab6e5c0 100644 --- a/include/godot_cpp/core/object.hpp +++ b/include/godot_cpp/core/object.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_OBJECT_HPP -#define GODOT_OBJECT_HPP +#pragma once #include @@ -148,5 +147,3 @@ const T *Object::cast_to(const Object *p_object) { } } // namespace godot - -#endif // GODOT_OBJECT_HPP diff --git a/include/godot_cpp/core/object_id.hpp b/include/godot_cpp/core/object_id.hpp index 9f3bc96ff..815622b9c 100644 --- a/include/godot_cpp/core/object_id.hpp +++ b/include/godot_cpp/core/object_id.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_OBJECT_ID_HPP -#define GODOT_OBJECT_ID_HPP +#pragma once #include @@ -58,5 +57,3 @@ class ObjectID { }; } // namespace godot - -#endif // GODOT_OBJECT_ID_HPP diff --git a/include/godot_cpp/core/print_string.hpp b/include/godot_cpp/core/print_string.hpp index 61f4330cf..69afaf07b 100644 --- a/include/godot_cpp/core/print_string.hpp +++ b/include/godot_cpp/core/print_string.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_PRINT_STRING_HPP -#define GODOT_PRINT_STRING_HPP +#pragma once #include @@ -69,5 +68,3 @@ void print_verbose(const Variant &p_variant, Args... p_args) { bool is_print_verbose_enabled(); } // namespace godot - -#endif // GODOT_PRINT_STRING_HPP diff --git a/include/godot_cpp/core/property_info.hpp b/include/godot_cpp/core/property_info.hpp index dd71d48af..23da33e31 100644 --- a/include/godot_cpp/core/property_info.hpp +++ b/include/godot_cpp/core/property_info.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_PROPERTY_INFO_HPP -#define GODOT_PROPERTY_INFO_HPP +#pragma once #include @@ -128,5 +127,3 @@ struct PropertyInfo { }; } // namespace godot - -#endif // GODOT_PROPERTY_INFO_HPP diff --git a/include/godot_cpp/core/type_info.hpp b/include/godot_cpp/core/type_info.hpp index e131c510c..59ad87e4b 100644 --- a/include/godot_cpp/core/type_info.hpp +++ b/include/godot_cpp/core/type_info.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_TYPE_INFO_HPP -#define GODOT_TYPE_INFO_HPP +#pragma once #include #include @@ -416,5 +415,3 @@ MAKE_TYPED_ARRAY_INFO(IPAddress, Variant::STRING) #define CLASS_INFO(m_type) (GetTypeInfo::get_class_info()) } // namespace godot - -#endif // GODOT_TYPE_INFO_HPP diff --git a/include/godot_cpp/godot.hpp b/include/godot_cpp/godot.hpp index 40693aa7a..7659f8a95 100644 --- a/include/godot_cpp/godot.hpp +++ b/include/godot_cpp/godot.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_GODOT_HPP -#define GODOT_GODOT_HPP +#pragma once #include @@ -265,5 +264,3 @@ class GDExtensionBinding { }; } // namespace godot - -#endif // GODOT_GODOT_HPP diff --git a/include/godot_cpp/templates/cowdata.hpp b/include/godot_cpp/templates/cowdata.hpp index dcb74eccc..68918f7ac 100644 --- a/include/godot_cpp/templates/cowdata.hpp +++ b/include/godot_cpp/templates/cowdata.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_COWDATA_HPP -#define GODOT_COWDATA_HPP +#pragma once #include #include @@ -488,5 +487,3 @@ CowData::~CowData() { #endif } // namespace godot - -#endif // GODOT_COWDATA_HPP diff --git a/include/godot_cpp/templates/hash_map.hpp b/include/godot_cpp/templates/hash_map.hpp index 59cd8e0b0..67dfb4e77 100644 --- a/include/godot_cpp/templates/hash_map.hpp +++ b/include/godot_cpp/templates/hash_map.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_HASH_MAP_HPP -#define GODOT_HASH_MAP_HPP +#pragma once #include #include @@ -587,5 +586,3 @@ class HashMap { }; } // namespace godot - -#endif // GODOT_HASH_MAP_HPP diff --git a/include/godot_cpp/templates/hash_set.hpp b/include/godot_cpp/templates/hash_set.hpp index 1845a1bb4..67ba443aa 100644 --- a/include/godot_cpp/templates/hash_set.hpp +++ b/include/godot_cpp/templates/hash_set.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_HASH_SET_HPP -#define GODOT_HASH_SET_HPP +#pragma once #include #include @@ -473,5 +472,3 @@ class HashSet { }; } // namespace godot - -#endif // GODOT_HASH_SET_HPP diff --git a/include/godot_cpp/templates/hashfuncs.hpp b/include/godot_cpp/templates/hashfuncs.hpp index 40b10a9e2..3fcedb693 100644 --- a/include/godot_cpp/templates/hashfuncs.hpp +++ b/include/godot_cpp/templates/hashfuncs.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_HASHFUNCS_HPP -#define GODOT_HASHFUNCS_HPP +#pragma once // Needed for fastmod. #if defined(_MSC_VER) @@ -522,5 +521,3 @@ static _FORCE_INLINE_ uint32_t fastmod(const uint32_t n, const uint64_t c, const } } // namespace godot - -#endif // GODOT_HASHFUNCS_HPP diff --git a/include/godot_cpp/templates/list.hpp b/include/godot_cpp/templates/list.hpp index fa5960565..bbc818c7d 100644 --- a/include/godot_cpp/templates/list.hpp +++ b/include/godot_cpp/templates/list.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_LIST_HPP -#define GODOT_LIST_HPP +#pragma once #include #include @@ -783,5 +782,3 @@ class List { }; } // namespace godot - -#endif // GODOT_LIST_HPP diff --git a/include/godot_cpp/templates/local_vector.hpp b/include/godot_cpp/templates/local_vector.hpp index c5481e48a..7b684874a 100644 --- a/include/godot_cpp/templates/local_vector.hpp +++ b/include/godot_cpp/templates/local_vector.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_LOCAL_VECTOR_HPP -#define GODOT_LOCAL_VECTOR_HPP +#pragma once #include #include @@ -339,5 +338,3 @@ template using TightLocalVector = LocalVector; } // namespace godot - -#endif // GODOT_LOCAL_VECTOR_HPP diff --git a/include/godot_cpp/templates/pair.hpp b/include/godot_cpp/templates/pair.hpp index f87541305..5c064c1cf 100644 --- a/include/godot_cpp/templates/pair.hpp +++ b/include/godot_cpp/templates/pair.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_PAIR_HPP -#define GODOT_PAIR_HPP +#pragma once namespace godot { @@ -103,5 +102,3 @@ struct KeyValueSort { }; } // namespace godot - -#endif // GODOT_PAIR_HPP diff --git a/include/godot_cpp/templates/rb_map.hpp b/include/godot_cpp/templates/rb_map.hpp index 6ab71fd7e..0ddb19839 100644 --- a/include/godot_cpp/templates/rb_map.hpp +++ b/include/godot_cpp/templates/rb_map.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_RB_MAP_HPP -#define GODOT_RB_MAP_HPP +#pragma once #include #include @@ -761,5 +760,3 @@ class RBMap { }; } // namespace godot - -#endif // GODOT_RB_MAP_HPP diff --git a/include/godot_cpp/templates/rb_set.hpp b/include/godot_cpp/templates/rb_set.hpp index 69aa8d7f9..f826896f7 100644 --- a/include/godot_cpp/templates/rb_set.hpp +++ b/include/godot_cpp/templates/rb_set.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_RB_SET_HPP -#define GODOT_RB_SET_HPP +#pragma once #include @@ -710,5 +709,3 @@ class RBSet { }; } // namespace godot - -#endif // GODOT_RB_SET_HPP diff --git a/include/godot_cpp/templates/rid_owner.hpp b/include/godot_cpp/templates/rid_owner.hpp index 1dd4a3933..6d27d4023 100644 --- a/include/godot_cpp/templates/rid_owner.hpp +++ b/include/godot_cpp/templates/rid_owner.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_RID_OWNER_HPP -#define GODOT_RID_OWNER_HPP +#pragma once #include #include @@ -461,5 +460,3 @@ class RID_Owner { }; } // namespace godot - -#endif // GODOT_RID_OWNER_HPP diff --git a/include/godot_cpp/templates/safe_refcount.hpp b/include/godot_cpp/templates/safe_refcount.hpp index 98cb04b20..e6c29689c 100644 --- a/include/godot_cpp/templates/safe_refcount.hpp +++ b/include/godot_cpp/templates/safe_refcount.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_SAFE_REFCOUNT_HPP -#define GODOT_SAFE_REFCOUNT_HPP +#pragma once #if !defined(NO_THREADS) @@ -331,5 +330,3 @@ class SafeRefCount { #endif } // namespace godot - -#endif // GODOT_SAFE_REFCOUNT_HPP diff --git a/include/godot_cpp/templates/search_array.hpp b/include/godot_cpp/templates/search_array.hpp index 11a9db525..aa3374e8f 100644 --- a/include/godot_cpp/templates/search_array.hpp +++ b/include/godot_cpp/templates/search_array.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_SEARCH_ARRAY_HPP -#define GODOT_SEARCH_ARRAY_HPP +#pragma once #include @@ -67,5 +66,3 @@ class SearchArray { }; } // namespace godot - -#endif // GODOT_SEARCH_ARRAY_HPP diff --git a/include/godot_cpp/templates/self_list.hpp b/include/godot_cpp/templates/self_list.hpp index f7a65f689..cdd1f2586 100644 --- a/include/godot_cpp/templates/self_list.hpp +++ b/include/godot_cpp/templates/self_list.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_SELF_LIST_HPP -#define GODOT_SELF_LIST_HPP +#pragma once #include #include @@ -139,5 +138,3 @@ class SelfList { }; } // namespace godot - -#endif // GODOT_SELF_LIST_HPP diff --git a/include/godot_cpp/templates/sort_array.hpp b/include/godot_cpp/templates/sort_array.hpp index 7ce5c7842..c2727dd94 100644 --- a/include/godot_cpp/templates/sort_array.hpp +++ b/include/godot_cpp/templates/sort_array.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_SORT_ARRAY_HPP -#define GODOT_SORT_ARRAY_HPP +#pragma once #include @@ -319,5 +318,3 @@ class SortArray { }; } // namespace godot - -#endif // GODOT_SORT_ARRAY_HPP diff --git a/include/godot_cpp/templates/spin_lock.hpp b/include/godot_cpp/templates/spin_lock.hpp index 530d545e3..17c21bc5c 100644 --- a/include/godot_cpp/templates/spin_lock.hpp +++ b/include/godot_cpp/templates/spin_lock.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_SPIN_LOCK_HPP -#define GODOT_SPIN_LOCK_HPP +#pragma once #include @@ -50,5 +49,3 @@ class SpinLock { }; } // namespace godot - -#endif // GODOT_SPIN_LOCK_HPP diff --git a/include/godot_cpp/templates/thread_work_pool.hpp b/include/godot_cpp/templates/thread_work_pool.hpp index cb20c6e97..190c1e00e 100644 --- a/include/godot_cpp/templates/thread_work_pool.hpp +++ b/include/godot_cpp/templates/thread_work_pool.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_THREAD_WORK_POOL_HPP -#define GODOT_THREAD_WORK_POOL_HPP +#pragma once #include #include @@ -201,5 +200,3 @@ class ThreadWorkPool { }; } // namespace godot - -#endif // GODOT_THREAD_WORK_POOL_HPP diff --git a/include/godot_cpp/templates/vector.hpp b/include/godot_cpp/templates/vector.hpp index aaa84f338..50593f30a 100644 --- a/include/godot_cpp/templates/vector.hpp +++ b/include/godot_cpp/templates/vector.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_VECTOR_HPP -#define GODOT_VECTOR_HPP +#pragma once /** * @class Vector @@ -332,5 +331,3 @@ void Vector::fill(T p_elem) { } } // namespace godot - -#endif // GODOT_VECTOR_HPP diff --git a/include/godot_cpp/templates/vmap.hpp b/include/godot_cpp/templates/vmap.hpp index 926ccd390..b6fa3c039 100644 --- a/include/godot_cpp/templates/vmap.hpp +++ b/include/godot_cpp/templates/vmap.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_VMAP_HPP -#define GODOT_VMAP_HPP +#pragma once #include @@ -200,5 +199,3 @@ class VMap { }; } // namespace godot - -#endif // GODOT_VMAP_HPP diff --git a/include/godot_cpp/templates/vset.hpp b/include/godot_cpp/templates/vset.hpp index ce21ba83f..42167403b 100644 --- a/include/godot_cpp/templates/vset.hpp +++ b/include/godot_cpp/templates/vset.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_VSET_HPP -#define GODOT_VSET_HPP +#pragma once #include @@ -141,5 +140,3 @@ class VSet { }; } // namespace godot - -#endif // GODOT_VSET_HPP diff --git a/include/godot_cpp/variant/aabb.hpp b/include/godot_cpp/variant/aabb.hpp index 46eaca961..17048d60a 100644 --- a/include/godot_cpp/variant/aabb.hpp +++ b/include/godot_cpp/variant/aabb.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_AABB_HPP -#define GODOT_AABB_HPP +#pragma once #include #include @@ -491,5 +490,3 @@ AABB AABB::quantized(real_t p_unit) const { } } // namespace godot - -#endif // GODOT_AABB_HPP diff --git a/include/godot_cpp/variant/array_helpers.hpp b/include/godot_cpp/variant/array_helpers.hpp index 3d948aab5..f408aa720 100644 --- a/include/godot_cpp/variant/array_helpers.hpp +++ b/include/godot_cpp/variant/array_helpers.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_ARRAY_HELPERS_HPP -#define GODOT_ARRAY_HELPERS_HPP +#pragma once namespace godot { namespace helpers { @@ -51,5 +50,3 @@ T append_all(T appendable) { } } // namespace helpers } // namespace godot - -#endif // GODOT_ARRAY_HELPERS_HPP diff --git a/include/godot_cpp/variant/basis.hpp b/include/godot_cpp/variant/basis.hpp index 4b7a6b44b..6ede9ead9 100644 --- a/include/godot_cpp/variant/basis.hpp +++ b/include/godot_cpp/variant/basis.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_BASIS_HPP -#define GODOT_BASIS_HPP +#pragma once #include #include @@ -315,5 +314,3 @@ real_t Basis::determinant() const { } } // namespace godot - -#endif // GODOT_BASIS_HPP diff --git a/include/godot_cpp/variant/callable_custom.hpp b/include/godot_cpp/variant/callable_custom.hpp index 48a814221..1ab18bd3d 100644 --- a/include/godot_cpp/variant/callable_custom.hpp +++ b/include/godot_cpp/variant/callable_custom.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_CALLABLE_CUSTOM_HPP -#define GODOT_CALLABLE_CUSTOM_HPP +#pragma once #include #include @@ -61,5 +60,3 @@ class CallableCustom : public CallableCustomBase { }; } // namespace godot - -#endif // GODOT_CALLABLE_CUSTOM_HPP diff --git a/include/godot_cpp/variant/callable_method_pointer.hpp b/include/godot_cpp/variant/callable_method_pointer.hpp index f3d688b45..e9aea09bc 100644 --- a/include/godot_cpp/variant/callable_method_pointer.hpp +++ b/include/godot_cpp/variant/callable_method_pointer.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_CALLABLE_METHOD_POINTER_HPP -#define GODOT_CALLABLE_METHOD_POINTER_HPP +#pragma once #include #include @@ -269,5 +268,3 @@ Callable create_custom_callable_static_function_pointer(R (*p_method)(P...)) { #define callable_mp_static(M) ::godot::create_custom_callable_static_function_pointer(M) } // namespace godot - -#endif // GODOT_CALLABLE_METHOD_POINTER_HPP diff --git a/include/godot_cpp/variant/char_string.hpp b/include/godot_cpp/variant/char_string.hpp index 991c0392a..b7b795b52 100644 --- a/include/godot_cpp/variant/char_string.hpp +++ b/include/godot_cpp/variant/char_string.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_CHAR_STRING_HPP -#define GODOT_CHAR_STRING_HPP +#pragma once #include @@ -138,5 +137,3 @@ typedef CharStringT Char32String; typedef CharStringT CharWideString; } // namespace godot - -#endif // GODOT_CHAR_STRING_HPP diff --git a/include/godot_cpp/variant/char_utils.hpp b/include/godot_cpp/variant/char_utils.hpp index 066f7945d..6b672be30 100644 --- a/include/godot_cpp/variant/char_utils.hpp +++ b/include/godot_cpp/variant/char_utils.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_CHAR_UTILS_HPP -#define GODOT_CHAR_UTILS_HPP +#pragma once static _FORCE_INLINE_ bool is_ascii_upper_case(char32_t c) { return (c >= 'A' && c <= 'Z'); @@ -86,5 +85,3 @@ static _FORCE_INLINE_ bool is_punct(char32_t p_char) { static _FORCE_INLINE_ bool is_underscore(char32_t p_char) { return (p_char == '_'); } - -#endif // GODOT_CHAR_UTILS_HPP diff --git a/include/godot_cpp/variant/color.hpp b/include/godot_cpp/variant/color.hpp index 86f1a3960..878a7d870 100644 --- a/include/godot_cpp/variant/color.hpp +++ b/include/godot_cpp/variant/color.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_COLOR_HPP -#define GODOT_COLOR_HPP +#pragma once #include @@ -285,5 +284,3 @@ _FORCE_INLINE_ Color operator*(float p_scalar, const Color &p_color) { } } // namespace godot - -#endif // GODOT_COLOR_HPP diff --git a/include/godot_cpp/variant/color_names.inc.hpp b/include/godot_cpp/variant/color_names.inc.hpp index d7708e5d6..e2c878327 100644 --- a/include/godot_cpp/variant/color_names.inc.hpp +++ b/include/godot_cpp/variant/color_names.inc.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_COLOR_NAMES_INC_HPP -#define GODOT_COLOR_NAMES_INC_HPP +#pragma once namespace godot { @@ -192,5 +191,3 @@ static NamedColor named_colors[] = { }; } // namespace godot - -#endif // GODOT_COLOR_NAMES_INC_HPP diff --git a/include/godot_cpp/variant/plane.hpp b/include/godot_cpp/variant/plane.hpp index d2184ca44..f2c440a23 100644 --- a/include/godot_cpp/variant/plane.hpp +++ b/include/godot_cpp/variant/plane.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_PLANE_HPP -#define GODOT_PLANE_HPP +#pragma once #include #include @@ -137,5 +136,3 @@ bool Plane::operator!=(const Plane &p_plane) const { } } // namespace godot - -#endif // GODOT_PLANE_HPP diff --git a/include/godot_cpp/variant/projection.hpp b/include/godot_cpp/variant/projection.hpp index cc715778e..b7eb1f89e 100644 --- a/include/godot_cpp/variant/projection.hpp +++ b/include/godot_cpp/variant/projection.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_PROJECTION_HPP -#define GODOT_PROJECTION_HPP +#pragma once #include #include @@ -167,5 +166,3 @@ Vector3 Projection::xform(const Vector3 &p_vec3) const { } } // namespace godot - -#endif // GODOT_PROJECTION_HPP diff --git a/include/godot_cpp/variant/quaternion.hpp b/include/godot_cpp/variant/quaternion.hpp index 5cf23a357..33569addf 100644 --- a/include/godot_cpp/variant/quaternion.hpp +++ b/include/godot_cpp/variant/quaternion.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_QUATERNION_HPP -#define GODOT_QUATERNION_HPP +#pragma once #include #include @@ -232,5 +231,3 @@ _FORCE_INLINE_ Quaternion operator*(real_t p_real, const Quaternion &p_quaternio } } // namespace godot - -#endif // GODOT_QUATERNION_HPP diff --git a/include/godot_cpp/variant/rect2.hpp b/include/godot_cpp/variant/rect2.hpp index 14cbeb51a..3a5e18e3b 100644 --- a/include/godot_cpp/variant/rect2.hpp +++ b/include/godot_cpp/variant/rect2.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_RECT2_HPP -#define GODOT_RECT2_HPP +#pragma once #include #include @@ -369,5 +368,3 @@ struct [[nodiscard]] Rect2 { }; } // namespace godot - -#endif // GODOT_RECT2_HPP diff --git a/include/godot_cpp/variant/rect2i.hpp b/include/godot_cpp/variant/rect2i.hpp index 2c42aa7f1..94c340a89 100644 --- a/include/godot_cpp/variant/rect2i.hpp +++ b/include/godot_cpp/variant/rect2i.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_RECT2I_HPP -#define GODOT_RECT2I_HPP +#pragma once #include #include @@ -241,5 +240,3 @@ struct [[nodiscard]] Rect2i { }; } // namespace godot - -#endif // GODOT_RECT2I_HPP diff --git a/include/godot_cpp/variant/transform2d.hpp b/include/godot_cpp/variant/transform2d.hpp index f83f0399c..5135d555e 100644 --- a/include/godot_cpp/variant/transform2d.hpp +++ b/include/godot_cpp/variant/transform2d.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_TRANSFORM2D_HPP -#define GODOT_TRANSFORM2D_HPP +#pragma once #include #include @@ -247,5 +246,3 @@ PackedVector2Array Transform2D::xform_inv(const PackedVector2Array &p_array) con } } // namespace godot - -#endif // GODOT_TRANSFORM2D_HPP diff --git a/include/godot_cpp/variant/transform3d.hpp b/include/godot_cpp/variant/transform3d.hpp index 2ad84ff3d..b0c1d2e7b 100644 --- a/include/godot_cpp/variant/transform3d.hpp +++ b/include/godot_cpp/variant/transform3d.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_TRANSFORM3D_HPP -#define GODOT_TRANSFORM3D_HPP +#pragma once #include #include @@ -272,5 +271,3 @@ _FORCE_INLINE_ Plane Transform3D::xform_inv_fast(const Plane &p_plane, const Tra } } // namespace godot - -#endif // GODOT_TRANSFORM3D_HPP diff --git a/include/godot_cpp/variant/typed_array.hpp b/include/godot_cpp/variant/typed_array.hpp index 36bbcc971..9b735c599 100644 --- a/include/godot_cpp/variant/typed_array.hpp +++ b/include/godot_cpp/variant/typed_array.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_TYPED_ARRAY_HPP -#define GODOT_TYPED_ARRAY_HPP +#pragma once #include #include @@ -138,5 +137,3 @@ MAKE_TYPED_ARRAY(PackedColorArray, Variant::PACKED_COLOR_ARRAY) #undef MAKE_TYPED_ARRAY } // namespace godot - -#endif // GODOT_TYPED_ARRAY_HPP diff --git a/include/godot_cpp/variant/typed_dictionary.hpp b/include/godot_cpp/variant/typed_dictionary.hpp index deb5871a0..ff78c5164 100644 --- a/include/godot_cpp/variant/typed_dictionary.hpp +++ b/include/godot_cpp/variant/typed_dictionary.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_TYPED_DICTIONARY_HPP -#define GODOT_TYPED_DICTIONARY_HPP +#pragma once #include #include @@ -435,5 +434,3 @@ MAKE_TYPED_DICTIONARY_INFO(IPAddress, Variant::STRING) #undef MAKE_TYPED_DICTIONARY_INFO_WITH_OBJECT } // namespace godot - -#endif // GODOT_TYPED_DICTIONARY_HPP diff --git a/include/godot_cpp/variant/variant.hpp b/include/godot_cpp/variant/variant.hpp index f6b70523a..0e4cda253 100644 --- a/include/godot_cpp/variant/variant.hpp +++ b/include/godot_cpp/variant/variant.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_VARIANT_HPP -#define GODOT_VARIANT_HPP +#pragma once #include @@ -367,5 +366,3 @@ using PackedRealArray = PackedFloat32Array; #endif // REAL_T_IS_DOUBLE } // namespace godot - -#endif // GODOT_VARIANT_HPP diff --git a/include/godot_cpp/variant/variant_internal.hpp b/include/godot_cpp/variant/variant_internal.hpp index 623810bbe..637e12dd7 100644 --- a/include/godot_cpp/variant/variant_internal.hpp +++ b/include/godot_cpp/variant/variant_internal.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_VARIANT_INTERNAL_HPP -#define GODOT_VARIANT_INTERNAL_HPP +#pragma once #include #include @@ -505,5 +504,3 @@ struct VariantDefaultInitializer { }; } // namespace godot - -#endif // GODOT_VARIANT_INTERNAL_HPP diff --git a/include/godot_cpp/variant/vector2.hpp b/include/godot_cpp/variant/vector2.hpp index 8252f348a..32004f01a 100644 --- a/include/godot_cpp/variant/vector2.hpp +++ b/include/godot_cpp/variant/vector2.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_VECTOR2_HPP -#define GODOT_VECTOR2_HPP +#pragma once #include #include @@ -330,5 +329,3 @@ typedef Vector2 Size2; typedef Vector2 Point2; } // namespace godot - -#endif // GODOT_VECTOR2_HPP diff --git a/include/godot_cpp/variant/vector2i.hpp b/include/godot_cpp/variant/vector2i.hpp index bee40d5cc..73a121a48 100644 --- a/include/godot_cpp/variant/vector2i.hpp +++ b/include/godot_cpp/variant/vector2i.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_VECTOR2I_HPP -#define GODOT_VECTOR2I_HPP +#pragma once #include #include @@ -168,5 +167,3 @@ typedef Vector2i Size2i; typedef Vector2i Point2i; } // namespace godot - -#endif // GODOT_VECTOR2I_HPP diff --git a/include/godot_cpp/variant/vector3.hpp b/include/godot_cpp/variant/vector3.hpp index 69d772656..f92d0209c 100644 --- a/include/godot_cpp/variant/vector3.hpp +++ b/include/godot_cpp/variant/vector3.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_VECTOR3_HPP -#define GODOT_VECTOR3_HPP +#pragma once #include #include @@ -537,5 +536,3 @@ Vector3 Vector3::reflect(const Vector3 &p_normal) const { } } // namespace godot - -#endif // GODOT_VECTOR3_HPP diff --git a/include/godot_cpp/variant/vector3i.hpp b/include/godot_cpp/variant/vector3i.hpp index d489b415c..15bc3bde7 100644 --- a/include/godot_cpp/variant/vector3i.hpp +++ b/include/godot_cpp/variant/vector3i.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_VECTOR3I_HPP -#define GODOT_VECTOR3I_HPP +#pragma once #include #include @@ -339,5 +338,3 @@ void Vector3i::zero() { } } // namespace godot - -#endif // GODOT_VECTOR3I_HPP diff --git a/include/godot_cpp/variant/vector4.hpp b/include/godot_cpp/variant/vector4.hpp index ff95fa7a3..1f5ff5595 100644 --- a/include/godot_cpp/variant/vector4.hpp +++ b/include/godot_cpp/variant/vector4.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_VECTOR4_HPP -#define GODOT_VECTOR4_HPP +#pragma once #include #include @@ -319,5 +318,3 @@ _FORCE_INLINE_ Vector4 operator*(const int64_t p_scalar, const Vector4 &p_vec) { } } // namespace godot - -#endif // GODOT_VECTOR4_HPP diff --git a/include/godot_cpp/variant/vector4i.hpp b/include/godot_cpp/variant/vector4i.hpp index 4325fe99f..285feeaf9 100644 --- a/include/godot_cpp/variant/vector4i.hpp +++ b/include/godot_cpp/variant/vector4i.hpp @@ -28,8 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#ifndef GODOT_VECTOR4I_HPP -#define GODOT_VECTOR4I_HPP +#pragma once #include #include @@ -367,5 +366,3 @@ void Vector4i::zero() { } } // namespace godot - -#endif // GODOT_VECTOR4I_HPP diff --git a/test/src/example.h b/test/src/example.h index 6e6ff399a..b40fcab16 100644 --- a/test/src/example.h +++ b/test/src/example.h @@ -3,8 +3,7 @@ * This is free and unencumbered software released into the public domain. */ -#ifndef EXAMPLE_CLASS_H -#define EXAMPLE_CLASS_H +#pragma once // We don't need windows.h in this example plugin but many others do, and it can // lead to annoying situations due to the ton of macros it defines. @@ -289,5 +288,3 @@ class ExamplePrzykład : public RefCounted { public: String get_the_word() const; }; - -#endif // EXAMPLE_CLASS_H diff --git a/test/src/register_types.h b/test/src/register_types.h index 5f124da77..d19fd01a9 100644 --- a/test/src/register_types.h +++ b/test/src/register_types.h @@ -3,8 +3,7 @@ * This is free and unencumbered software released into the public domain. */ -#ifndef EXAMPLE_REGISTER_TYPES_H -#define EXAMPLE_REGISTER_TYPES_H +#pragma once #include @@ -12,5 +11,3 @@ using namespace godot; void initialize_example_module(ModuleInitializationLevel p_level); void uninitialize_example_module(ModuleInitializationLevel p_level); - -#endif // EXAMPLE_REGISTER_TYPES_H diff --git a/test/src/tests.h b/test/src/tests.h index 55835fc16..a2c39be03 100644 --- a/test/src/tests.h +++ b/test/src/tests.h @@ -3,8 +3,7 @@ * This is free and unencumbered software released into the public domain. */ -#ifndef TESTS_H -#define TESTS_H +#pragma once #include #include @@ -25,5 +24,3 @@ #include #include #include - -#endif // TESTS_H From 749d68037ea3d13774f09f555638f5cba93c093a Mon Sep 17 00:00:00 2001 From: Thaddeus Crews Date: Fri, 7 Mar 2025 17:58:27 -0600 Subject: [PATCH 04/41] Ignore `#pragma once` commit (cherry picked from commit c963321cdd9e4d357d4424ab6571d35ccf2cbb4c) --- .git-blame-ignore-revs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 000000000..8c4341118 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,11 @@ +# This file contains a list of Git commit hashes that should be hidden from the +# regular Git history. Typically, this includes commits involving mass auto-formatting +# or other normalizations. Commit hashes *must* use the full 40-character notation. +# To apply the ignore list in your local Git client, you must run: +# +# git config blame.ignoreRevsFile .git-blame-ignore-revs +# +# This file is automatically used by GitHub.com's blame view. + +# Style: Replace header guards with `#pragma once` +7056c996dd43ae1aa466c94d95cc2fe63853d8a9 From 67f6f96a9b5a63de8e2634d95eb3431626750ccb Mon Sep 17 00:00:00 2001 From: David Snopek Date: Fri, 21 Feb 2025 14:59:13 -0600 Subject: [PATCH 05/41] Synchronize most shared variant code with Godot 4.4 (cherry picked from commit 075b517d96ccfb8fcca9cb47467dcd2b16e9ca76) --- include/godot_cpp/core/math.hpp | 20 + include/godot_cpp/variant/aabb.hpp | 38 +- include/godot_cpp/variant/basis.hpp | 114 +- include/godot_cpp/variant/char_range.inc.hpp | 3631 +++++++++++++++++ include/godot_cpp/variant/char_utils.hpp | 95 +- include/godot_cpp/variant/color.hpp | 90 +- include/godot_cpp/variant/color_names.inc.hpp | 1 - include/godot_cpp/variant/plane.hpp | 4 +- include/godot_cpp/variant/projection.hpp | 13 +- include/godot_cpp/variant/quaternion.hpp | 23 +- include/godot_cpp/variant/rect2.hpp | 38 +- include/godot_cpp/variant/rect2i.hpp | 2 +- include/godot_cpp/variant/transform2d.hpp | 67 +- include/godot_cpp/variant/transform3d.hpp | 22 +- include/godot_cpp/variant/vector2.hpp | 112 +- include/godot_cpp/variant/vector2i.hpp | 49 +- include/godot_cpp/variant/vector3.hpp | 122 +- include/godot_cpp/variant/vector3i.hpp | 64 +- include/godot_cpp/variant/vector4.hpp | 78 +- include/godot_cpp/variant/vector4i.hpp | 58 +- src/variant/aabb.cpp | 68 +- src/variant/basis.cpp | 152 +- src/variant/color.cpp | 57 +- src/variant/plane.cpp | 6 +- src/variant/projection.cpp | 372 +- src/variant/quaternion.cpp | 12 +- src/variant/rect2.cpp | 50 +- src/variant/transform2d.cpp | 107 +- src/variant/transform3d.cpp | 29 +- src/variant/vector2.cpp | 20 +- src/variant/vector2i.cpp | 62 +- src/variant/vector3.cpp | 38 +- src/variant/vector3i.cpp | 28 +- src/variant/vector4.cpp | 27 +- src/variant/vector4i.cpp | 32 +- 35 files changed, 4813 insertions(+), 888 deletions(-) create mode 100644 include/godot_cpp/variant/char_range.inc.hpp diff --git a/include/godot_cpp/core/math.hpp b/include/godot_cpp/core/math.hpp index 7da52109f..44cc30145 100644 --- a/include/godot_cpp/core/math.hpp +++ b/include/godot_cpp/core/math.hpp @@ -537,6 +537,26 @@ inline float bezier_interpolate(float p_start, float p_control_1, float p_contro return p_start * omt3 + p_control_1 * omt2 * p_t * 3.0f + p_control_2 * omt * t2 * 3.0f + p_end * t3; } +inline double bezier_derivative(double p_start, double p_control_1, double p_control_2, double p_end, double p_t) { + /* Formula from Wikipedia article on Bezier curves. */ + double omt = (1.0 - p_t); + double omt2 = omt * omt; + double t2 = p_t * p_t; + + double d = (p_control_1 - p_start) * 3.0 * omt2 + (p_control_2 - p_control_1) * 6.0 * omt * p_t + (p_end - p_control_2) * 3.0 * t2; + return d; +} + +inline float bezier_derivative(float p_start, float p_control_1, float p_control_2, float p_end, float p_t) { + /* Formula from Wikipedia article on Bezier curves. */ + float omt = (1.0f - p_t); + float omt2 = omt * omt; + float t2 = p_t * p_t; + + float d = (p_control_1 - p_start) * 3.0f * omt2 + (p_control_2 - p_control_1) * 6.0f * omt * p_t + (p_end - p_control_2) * 3.0f * t2; + return d; +} + template inline T clamp(T x, T minv, T maxv) { if (x < minv) { diff --git a/include/godot_cpp/variant/aabb.hpp b/include/godot_cpp/variant/aabb.hpp index 17048d60a..cac221964 100644 --- a/include/godot_cpp/variant/aabb.hpp +++ b/include/godot_cpp/variant/aabb.hpp @@ -72,16 +72,21 @@ struct [[nodiscard]] AABB { AABB merge(const AABB &p_with) const; void merge_with(const AABB &p_aabb); ///merge with another AABB AABB intersection(const AABB &p_aabb) const; ///get box where two intersect, empty if no intersection occurs - bool intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_clip = nullptr, Vector3 *r_normal = nullptr) const; - bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *r_clip = nullptr, Vector3 *r_normal = nullptr) const; - _FORCE_INLINE_ bool smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t t0, real_t t1) const; + _FORCE_INLINE_ bool smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t p_t0, real_t p_t1) const; + + bool intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_intersection_point = nullptr, Vector3 *r_normal = nullptr) const; + bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir) const { + bool inside; + return find_intersects_ray(p_from, p_dir, inside); + } + bool find_intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, bool &r_inside, Vector3 *r_intersection_point = nullptr, Vector3 *r_normal = nullptr) const; _FORCE_INLINE_ bool intersects_convex_shape(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count) const; _FORCE_INLINE_ bool inside_convex_shape(const Plane *p_planes, int p_plane_count) const; bool intersects_plane(const Plane &p_plane) const; _FORCE_INLINE_ bool has_point(const Vector3 &p_point) const; - _FORCE_INLINE_ Vector3 get_support(const Vector3 &p_normal) const; + _FORCE_INLINE_ Vector3 get_support(const Vector3 &p_direction) const; Vector3 get_longest_axis() const; int get_longest_axis_index() const; @@ -208,15 +213,18 @@ inline bool AABB::encloses(const AABB &p_aabb) const { (src_max.z >= dst_max.z)); } -Vector3 AABB::get_support(const Vector3 &p_normal) const { - Vector3 half_extents = size * 0.5f; - Vector3 ofs = position + half_extents; - - return Vector3( - (p_normal.x > 0) ? half_extents.x : -half_extents.x, - (p_normal.y > 0) ? half_extents.y : -half_extents.y, - (p_normal.z > 0) ? half_extents.z : -half_extents.z) + - ofs; +Vector3 AABB::get_support(const Vector3 &p_direction) const { + Vector3 support = position; + if (p_direction.x > 0.0f) { + support.x += size.x; + } + if (p_direction.y > 0.0f) { + support.y += size.y; + } + if (p_direction.z > 0.0f) { + support.z += size.z; + } + return support; } Vector3 AABB::get_endpoint(int p_point) const { @@ -402,7 +410,7 @@ inline real_t AABB::get_shortest_axis_size() const { return max_size; } -bool AABB::smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t t0, real_t t1) const { +bool AABB::smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t p_t0, real_t p_t1) const { #ifdef MATH_CHECKS if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) { ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size."); @@ -453,7 +461,7 @@ bool AABB::smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real if (tzmax < tmax) { tmax = tzmax; } - return ((tmin < t1) && (tmax > t0)); + return ((tmin < p_t1) && (tmax > p_t0)); } void AABB::grow_by(real_t p_amount) { diff --git a/include/godot_cpp/variant/basis.hpp b/include/godot_cpp/variant/basis.hpp index 6ede9ead9..efe21cf6d 100644 --- a/include/godot_cpp/variant/basis.hpp +++ b/include/godot_cpp/variant/basis.hpp @@ -43,11 +43,11 @@ struct [[nodiscard]] Basis { Vector3(0, 0, 1) }; - _FORCE_INLINE_ const Vector3 &operator[](int axis) const { - return rows[axis]; + _FORCE_INLINE_ const Vector3 &operator[](int p_row) const { + return rows[p_row]; } - _FORCE_INLINE_ Vector3 &operator[](int axis) { - return rows[axis]; + _FORCE_INLINE_ Vector3 &operator[](int p_row) { + return rows[p_row]; } void invert(); @@ -58,21 +58,19 @@ struct [[nodiscard]] Basis { _FORCE_INLINE_ real_t determinant() const; - void from_z(const Vector3 &p_z); - void rotate(const Vector3 &p_axis, real_t p_angle); Basis rotated(const Vector3 &p_axis, real_t p_angle) const; void rotate_local(const Vector3 &p_axis, real_t p_angle); Basis rotated_local(const Vector3 &p_axis, real_t p_angle) const; - void rotate(const Vector3 &p_euler, EulerOrder p_order = EULER_ORDER_YXZ); - Basis rotated(const Vector3 &p_euler, EulerOrder p_order = EULER_ORDER_YXZ) const; + void rotate(const Vector3 &p_euler, EulerOrder p_order = EulerOrder::EULER_ORDER_YXZ); + Basis rotated(const Vector3 &p_euler, EulerOrder p_order = EulerOrder::EULER_ORDER_YXZ) const; void rotate(const Quaternion &p_quaternion); Basis rotated(const Quaternion &p_quaternion) const; - Vector3 get_euler_normalized(EulerOrder p_order = EULER_ORDER_YXZ) const; + Vector3 get_euler_normalized(EulerOrder p_order = EulerOrder::EULER_ORDER_YXZ) const; void get_rotation_axis_angle(Vector3 &p_axis, real_t &p_angle) const; void get_rotation_axis_angle_local(Vector3 &p_axis, real_t &p_angle) const; Quaternion get_rotation_quaternion() const; @@ -81,9 +79,9 @@ struct [[nodiscard]] Basis { Vector3 rotref_posscale_decomposition(Basis &rotref) const; - Vector3 get_euler(EulerOrder p_order = EULER_ORDER_YXZ) const; - void set_euler(const Vector3 &p_euler, EulerOrder p_order = EULER_ORDER_YXZ); - static Basis from_euler(const Vector3 &p_euler, EulerOrder p_order = EULER_ORDER_YXZ) { + Vector3 get_euler(EulerOrder p_order = EulerOrder::EULER_ORDER_YXZ) const; + void set_euler(const Vector3 &p_euler, EulerOrder p_order = EulerOrder::EULER_ORDER_YXZ); + static Basis from_euler(const Vector3 &p_euler, EulerOrder p_order = EulerOrder::EULER_ORDER_YXZ) { Basis b; b.set_euler(p_euler, p_order); return b; @@ -103,27 +101,25 @@ struct [[nodiscard]] Basis { void scale_orthogonal(const Vector3 &p_scale); Basis scaled_orthogonal(const Vector3 &p_scale) const; - - void make_scale_uniform(); - float get_uniform_scale() const; + real_t get_uniform_scale() const; Vector3 get_scale() const; Vector3 get_scale_abs() const; - Vector3 get_scale_local() const; + Vector3 get_scale_global() const; void set_axis_angle_scale(const Vector3 &p_axis, real_t p_angle, const Vector3 &p_scale); - void set_euler_scale(const Vector3 &p_euler, const Vector3 &p_scale, EulerOrder p_order = EULER_ORDER_YXZ); + void set_euler_scale(const Vector3 &p_euler, const Vector3 &p_scale, EulerOrder p_order = EulerOrder::EULER_ORDER_YXZ); void set_quaternion_scale(const Quaternion &p_quaternion, const Vector3 &p_scale); // transposed dot products - _FORCE_INLINE_ real_t tdotx(const Vector3 &v) const { - return rows[0][0] * v[0] + rows[1][0] * v[1] + rows[2][0] * v[2]; + _FORCE_INLINE_ real_t tdotx(const Vector3 &p_v) const { + return rows[0][0] * p_v[0] + rows[1][0] * p_v[1] + rows[2][0] * p_v[2]; } - _FORCE_INLINE_ real_t tdoty(const Vector3 &v) const { - return rows[0][1] * v[0] + rows[1][1] * v[1] + rows[2][1] * v[2]; + _FORCE_INLINE_ real_t tdoty(const Vector3 &p_v) const { + return rows[0][1] * p_v[0] + rows[1][1] * p_v[1] + rows[2][1] * p_v[2]; } - _FORCE_INLINE_ real_t tdotz(const Vector3 &v) const { - return rows[0][2] * v[0] + rows[1][2] * v[1] + rows[2][2] * v[2]; + _FORCE_INLINE_ real_t tdotz(const Vector3 &p_v) const { + return rows[0][2] * p_v[0] + rows[1][2] * p_v[1] + rows[2][2] * p_v[2]; } bool is_equal_approx(const Basis &p_basis) const; @@ -140,31 +136,35 @@ struct [[nodiscard]] Basis { _FORCE_INLINE_ Basis operator+(const Basis &p_matrix) const; _FORCE_INLINE_ void operator-=(const Basis &p_matrix); _FORCE_INLINE_ Basis operator-(const Basis &p_matrix) const; - _FORCE_INLINE_ void operator*=(const real_t p_val); - _FORCE_INLINE_ Basis operator*(const real_t p_val) const; + _FORCE_INLINE_ void operator*=(real_t p_val); + _FORCE_INLINE_ Basis operator*(real_t p_val) const; + _FORCE_INLINE_ void operator/=(real_t p_val); + _FORCE_INLINE_ Basis operator/(real_t p_val) const; bool is_orthogonal() const; + bool is_orthonormal() const; + bool is_conformal() const; bool is_diagonal() const; bool is_rotation() const; - Basis lerp(const Basis &p_to, const real_t &p_weight) const; - Basis slerp(const Basis &p_to, const real_t &p_weight) const; + Basis lerp(const Basis &p_to, real_t p_weight) const; + Basis slerp(const Basis &p_to, real_t p_weight) const; void rotate_sh(real_t *p_values); operator String() const; /* create / set */ - _FORCE_INLINE_ void set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz) { - rows[0][0] = xx; - rows[0][1] = xy; - rows[0][2] = xz; - rows[1][0] = yx; - rows[1][1] = yy; - rows[1][2] = yz; - rows[2][0] = zx; - rows[2][1] = zy; - rows[2][2] = zz; + _FORCE_INLINE_ void set(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_zx, real_t p_zy, real_t p_zz) { + rows[0][0] = p_xx; + rows[0][1] = p_xy; + rows[0][2] = p_xz; + rows[1][0] = p_yx; + rows[1][1] = p_yy; + rows[1][2] = p_yz; + rows[2][0] = p_zx; + rows[2][1] = p_zy; + rows[2][2] = p_zz; } _FORCE_INLINE_ void set_columns(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z) { set_column(0, p_x); @@ -194,20 +194,20 @@ struct [[nodiscard]] Basis { rows[2].zero(); } - _FORCE_INLINE_ Basis transpose_xform(const Basis &m) const { + _FORCE_INLINE_ Basis transpose_xform(const Basis &p_m) const { return Basis( - rows[0].x * m[0].x + rows[1].x * m[1].x + rows[2].x * m[2].x, - rows[0].x * m[0].y + rows[1].x * m[1].y + rows[2].x * m[2].y, - rows[0].x * m[0].z + rows[1].x * m[1].z + rows[2].x * m[2].z, - rows[0].y * m[0].x + rows[1].y * m[1].x + rows[2].y * m[2].x, - rows[0].y * m[0].y + rows[1].y * m[1].y + rows[2].y * m[2].y, - rows[0].y * m[0].z + rows[1].y * m[1].z + rows[2].y * m[2].z, - rows[0].z * m[0].x + rows[1].z * m[1].x + rows[2].z * m[2].x, - rows[0].z * m[0].y + rows[1].z * m[1].y + rows[2].z * m[2].y, - rows[0].z * m[0].z + rows[1].z * m[1].z + rows[2].z * m[2].z); + rows[0].x * p_m[0].x + rows[1].x * p_m[1].x + rows[2].x * p_m[2].x, + rows[0].x * p_m[0].y + rows[1].x * p_m[1].y + rows[2].x * p_m[2].y, + rows[0].x * p_m[0].z + rows[1].x * p_m[1].z + rows[2].x * p_m[2].z, + rows[0].y * p_m[0].x + rows[1].y * p_m[1].x + rows[2].y * p_m[2].x, + rows[0].y * p_m[0].y + rows[1].y * p_m[1].y + rows[2].y * p_m[2].y, + rows[0].y * p_m[0].z + rows[1].y * p_m[1].z + rows[2].y * p_m[2].z, + rows[0].z * p_m[0].x + rows[1].z * p_m[1].x + rows[2].z * p_m[2].x, + rows[0].z * p_m[0].y + rows[1].z * p_m[1].y + rows[2].z * p_m[2].y, + rows[0].z * p_m[0].z + rows[1].z * p_m[1].z + rows[2].z * p_m[2].z); } - Basis(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz) { - set(xx, xy, xz, yx, yy, yz, zx, zy, zz); + Basis(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_zx, real_t p_zy, real_t p_zz) { + set(p_xx, p_xy, p_xz, p_yx, p_yy, p_yz, p_zx, p_zy, p_zz); } void orthonormalize(); @@ -281,18 +281,30 @@ _FORCE_INLINE_ Basis Basis::operator-(const Basis &p_matrix) const { return ret; } -_FORCE_INLINE_ void Basis::operator*=(const real_t p_val) { +_FORCE_INLINE_ void Basis::operator*=(real_t p_val) { rows[0] *= p_val; rows[1] *= p_val; rows[2] *= p_val; } -_FORCE_INLINE_ Basis Basis::operator*(const real_t p_val) const { +_FORCE_INLINE_ Basis Basis::operator*(real_t p_val) const { Basis ret(*this); ret *= p_val; return ret; } +_FORCE_INLINE_ void Basis::operator/=(real_t p_val) { + rows[0] /= p_val; + rows[1] /= p_val; + rows[2] /= p_val; +} + +_FORCE_INLINE_ Basis Basis::operator/(real_t p_val) const { + Basis ret(*this); + ret /= p_val; + return ret; +} + Vector3 Basis::xform(const Vector3 &p_vector) const { return Vector3( rows[0].dot(p_vector), diff --git a/include/godot_cpp/variant/char_range.inc.hpp b/include/godot_cpp/variant/char_range.inc.hpp new file mode 100644 index 000000000..f31e761f0 --- /dev/null +++ b/include/godot_cpp/variant/char_range.inc.hpp @@ -0,0 +1,3631 @@ +/**************************************************************************/ +/* char_range.inc.hpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#pragma once + +// Unicode Derived Core Properties +// Source: https://www.unicode.org/Public/16.0.0/ucd/DerivedCoreProperties.txt + +namespace godot { + +struct CharRange { + char32_t start; + char32_t end; +}; + +constexpr inline CharRange xid_start[] = { + { 0x41, 0x5a }, + { 0x5f, 0x5f }, // Underscore technically isn't in XID_Start, but for our purposes it's included. + { 0x61, 0x7a }, + { 0xaa, 0xaa }, + { 0xb5, 0xb5 }, + { 0xba, 0xba }, + { 0xc0, 0xd6 }, + { 0xd8, 0xf6 }, + { 0xf8, 0x2c1 }, + { 0x2c6, 0x2d1 }, + { 0x2e0, 0x2e4 }, + { 0x2ec, 0x2ec }, + { 0x2ee, 0x2ee }, + { 0x370, 0x374 }, + { 0x376, 0x377 }, + { 0x37b, 0x37d }, + { 0x37f, 0x37f }, + { 0x386, 0x386 }, + { 0x388, 0x38a }, + { 0x38c, 0x38c }, + { 0x38e, 0x3a1 }, + { 0x3a3, 0x3f5 }, + { 0x3f7, 0x481 }, + { 0x48a, 0x52f }, + { 0x531, 0x556 }, + { 0x559, 0x559 }, + { 0x560, 0x588 }, + { 0x5d0, 0x5ea }, + { 0x5ef, 0x5f2 }, + { 0x620, 0x64a }, + { 0x66e, 0x66f }, + { 0x671, 0x6d3 }, + { 0x6d5, 0x6d5 }, + { 0x6e5, 0x6e6 }, + { 0x6ee, 0x6ef }, + { 0x6fa, 0x6fc }, + { 0x6ff, 0x6ff }, + { 0x710, 0x710 }, + { 0x712, 0x72f }, + { 0x74d, 0x7a5 }, + { 0x7b1, 0x7b1 }, + { 0x7ca, 0x7ea }, + { 0x7f4, 0x7f5 }, + { 0x7fa, 0x7fa }, + { 0x800, 0x815 }, + { 0x81a, 0x81a }, + { 0x824, 0x824 }, + { 0x828, 0x828 }, + { 0x840, 0x858 }, + { 0x860, 0x86a }, + { 0x870, 0x887 }, + { 0x889, 0x88e }, + { 0x8a0, 0x8c9 }, + { 0x904, 0x939 }, + { 0x93d, 0x93d }, + { 0x950, 0x950 }, + { 0x958, 0x961 }, + { 0x971, 0x980 }, + { 0x985, 0x98c }, + { 0x98f, 0x990 }, + { 0x993, 0x9a8 }, + { 0x9aa, 0x9b0 }, + { 0x9b2, 0x9b2 }, + { 0x9b6, 0x9b9 }, + { 0x9bd, 0x9bd }, + { 0x9ce, 0x9ce }, + { 0x9dc, 0x9dd }, + { 0x9df, 0x9e1 }, + { 0x9f0, 0x9f1 }, + { 0x9fc, 0x9fc }, + { 0xa05, 0xa0a }, + { 0xa0f, 0xa10 }, + { 0xa13, 0xa28 }, + { 0xa2a, 0xa30 }, + { 0xa32, 0xa33 }, + { 0xa35, 0xa36 }, + { 0xa38, 0xa39 }, + { 0xa59, 0xa5c }, + { 0xa5e, 0xa5e }, + { 0xa72, 0xa74 }, + { 0xa85, 0xa8d }, + { 0xa8f, 0xa91 }, + { 0xa93, 0xaa8 }, + { 0xaaa, 0xab0 }, + { 0xab2, 0xab3 }, + { 0xab5, 0xab9 }, + { 0xabd, 0xabd }, + { 0xad0, 0xad0 }, + { 0xae0, 0xae1 }, + { 0xaf9, 0xaf9 }, + { 0xb05, 0xb0c }, + { 0xb0f, 0xb10 }, + { 0xb13, 0xb28 }, + { 0xb2a, 0xb30 }, + { 0xb32, 0xb33 }, + { 0xb35, 0xb39 }, + { 0xb3d, 0xb3d }, + { 0xb5c, 0xb5d }, + { 0xb5f, 0xb61 }, + { 0xb71, 0xb71 }, + { 0xb83, 0xb83 }, + { 0xb85, 0xb8a }, + { 0xb8e, 0xb90 }, + { 0xb92, 0xb95 }, + { 0xb99, 0xb9a }, + { 0xb9c, 0xb9c }, + { 0xb9e, 0xb9f }, + { 0xba3, 0xba4 }, + { 0xba8, 0xbaa }, + { 0xbae, 0xbb9 }, + { 0xbd0, 0xbd0 }, + { 0xc05, 0xc0c }, + { 0xc0e, 0xc10 }, + { 0xc12, 0xc28 }, + { 0xc2a, 0xc39 }, + { 0xc3d, 0xc3d }, + { 0xc58, 0xc5a }, + { 0xc5d, 0xc5d }, + { 0xc60, 0xc61 }, + { 0xc80, 0xc80 }, + { 0xc85, 0xc8c }, + { 0xc8e, 0xc90 }, + { 0xc92, 0xca8 }, + { 0xcaa, 0xcb3 }, + { 0xcb5, 0xcb9 }, + { 0xcbd, 0xcbd }, + { 0xcdd, 0xcde }, + { 0xce0, 0xce1 }, + { 0xcf1, 0xcf2 }, + { 0xd04, 0xd0c }, + { 0xd0e, 0xd10 }, + { 0xd12, 0xd3a }, + { 0xd3d, 0xd3d }, + { 0xd4e, 0xd4e }, + { 0xd54, 0xd56 }, + { 0xd5f, 0xd61 }, + { 0xd7a, 0xd7f }, + { 0xd85, 0xd96 }, + { 0xd9a, 0xdb1 }, + { 0xdb3, 0xdbb }, + { 0xdbd, 0xdbd }, + { 0xdc0, 0xdc6 }, + { 0xe01, 0xe30 }, + { 0xe32, 0xe32 }, + { 0xe40, 0xe46 }, + { 0xe81, 0xe82 }, + { 0xe84, 0xe84 }, + { 0xe86, 0xe8a }, + { 0xe8c, 0xea3 }, + { 0xea5, 0xea5 }, + { 0xea7, 0xeb0 }, + { 0xeb2, 0xeb2 }, + { 0xebd, 0xebd }, + { 0xec0, 0xec4 }, + { 0xec6, 0xec6 }, + { 0xedc, 0xedf }, + { 0xf00, 0xf00 }, + { 0xf40, 0xf47 }, + { 0xf49, 0xf6c }, + { 0xf88, 0xf8c }, + { 0x1000, 0x102a }, + { 0x103f, 0x103f }, + { 0x1050, 0x1055 }, + { 0x105a, 0x105d }, + { 0x1061, 0x1061 }, + { 0x1065, 0x1066 }, + { 0x106e, 0x1070 }, + { 0x1075, 0x1081 }, + { 0x108e, 0x108e }, + { 0x10a0, 0x10c5 }, + { 0x10c7, 0x10c7 }, + { 0x10cd, 0x10cd }, + { 0x10d0, 0x10fa }, + { 0x10fc, 0x1248 }, + { 0x124a, 0x124d }, + { 0x1250, 0x1256 }, + { 0x1258, 0x1258 }, + { 0x125a, 0x125d }, + { 0x1260, 0x1288 }, + { 0x128a, 0x128d }, + { 0x1290, 0x12b0 }, + { 0x12b2, 0x12b5 }, + { 0x12b8, 0x12be }, + { 0x12c0, 0x12c0 }, + { 0x12c2, 0x12c5 }, + { 0x12c8, 0x12d6 }, + { 0x12d8, 0x1310 }, + { 0x1312, 0x1315 }, + { 0x1318, 0x135a }, + { 0x1380, 0x138f }, + { 0x13a0, 0x13f5 }, + { 0x13f8, 0x13fd }, + { 0x1401, 0x166c }, + { 0x166f, 0x167f }, + { 0x1681, 0x169a }, + { 0x16a0, 0x16ea }, + { 0x16ee, 0x16f8 }, + { 0x1700, 0x1711 }, + { 0x171f, 0x1731 }, + { 0x1740, 0x1751 }, + { 0x1760, 0x176c }, + { 0x176e, 0x1770 }, + { 0x1780, 0x17b3 }, + { 0x17d7, 0x17d7 }, + { 0x17dc, 0x17dc }, + { 0x1820, 0x1878 }, + { 0x1880, 0x18a8 }, + { 0x18aa, 0x18aa }, + { 0x18b0, 0x18f5 }, + { 0x1900, 0x191e }, + { 0x1950, 0x196d }, + { 0x1970, 0x1974 }, + { 0x1980, 0x19ab }, + { 0x19b0, 0x19c9 }, + { 0x1a00, 0x1a16 }, + { 0x1a20, 0x1a54 }, + { 0x1aa7, 0x1aa7 }, + { 0x1b05, 0x1b33 }, + { 0x1b45, 0x1b4c }, + { 0x1b83, 0x1ba0 }, + { 0x1bae, 0x1baf }, + { 0x1bba, 0x1be5 }, + { 0x1c00, 0x1c23 }, + { 0x1c4d, 0x1c4f }, + { 0x1c5a, 0x1c7d }, + { 0x1c80, 0x1c8a }, + { 0x1c90, 0x1cba }, + { 0x1cbd, 0x1cbf }, + { 0x1ce9, 0x1cec }, + { 0x1cee, 0x1cf3 }, + { 0x1cf5, 0x1cf6 }, + { 0x1cfa, 0x1cfa }, + { 0x1d00, 0x1dbf }, + { 0x1e00, 0x1f15 }, + { 0x1f18, 0x1f1d }, + { 0x1f20, 0x1f45 }, + { 0x1f48, 0x1f4d }, + { 0x1f50, 0x1f57 }, + { 0x1f59, 0x1f59 }, + { 0x1f5b, 0x1f5b }, + { 0x1f5d, 0x1f5d }, + { 0x1f5f, 0x1f7d }, + { 0x1f80, 0x1fb4 }, + { 0x1fb6, 0x1fbc }, + { 0x1fbe, 0x1fbe }, + { 0x1fc2, 0x1fc4 }, + { 0x1fc6, 0x1fcc }, + { 0x1fd0, 0x1fd3 }, + { 0x1fd6, 0x1fdb }, + { 0x1fe0, 0x1fec }, + { 0x1ff2, 0x1ff4 }, + { 0x1ff6, 0x1ffc }, + { 0x2071, 0x2071 }, + { 0x207f, 0x207f }, + { 0x2090, 0x209c }, + { 0x2102, 0x2102 }, + { 0x2107, 0x2107 }, + { 0x210a, 0x2113 }, + { 0x2115, 0x2115 }, + { 0x2118, 0x211d }, + { 0x2124, 0x2124 }, + { 0x2126, 0x2126 }, + { 0x2128, 0x2128 }, + { 0x212a, 0x2139 }, + { 0x213c, 0x213f }, + { 0x2145, 0x2149 }, + { 0x214e, 0x214e }, + { 0x2160, 0x2188 }, + { 0x2c00, 0x2ce4 }, + { 0x2ceb, 0x2cee }, + { 0x2cf2, 0x2cf3 }, + { 0x2d00, 0x2d25 }, + { 0x2d27, 0x2d27 }, + { 0x2d2d, 0x2d2d }, + { 0x2d30, 0x2d67 }, + { 0x2d6f, 0x2d6f }, + { 0x2d80, 0x2d96 }, + { 0x2da0, 0x2da6 }, + { 0x2da8, 0x2dae }, + { 0x2db0, 0x2db6 }, + { 0x2db8, 0x2dbe }, + { 0x2dc0, 0x2dc6 }, + { 0x2dc8, 0x2dce }, + { 0x2dd0, 0x2dd6 }, + { 0x2dd8, 0x2dde }, + { 0x3005, 0x3007 }, + { 0x3021, 0x3029 }, + { 0x3031, 0x3035 }, + { 0x3038, 0x303c }, + { 0x3041, 0x3096 }, + { 0x309d, 0x309f }, + { 0x30a1, 0x30fa }, + { 0x30fc, 0x30ff }, + { 0x3105, 0x312f }, + { 0x3131, 0x318e }, + { 0x31a0, 0x31bf }, + { 0x31f0, 0x31ff }, + { 0x3400, 0x4dbf }, + { 0x4e00, 0xa48c }, + { 0xa4d0, 0xa4fd }, + { 0xa500, 0xa60c }, + { 0xa610, 0xa61f }, + { 0xa62a, 0xa62b }, + { 0xa640, 0xa66e }, + { 0xa67f, 0xa69d }, + { 0xa6a0, 0xa6ef }, + { 0xa717, 0xa71f }, + { 0xa722, 0xa788 }, + { 0xa78b, 0xa7cd }, + { 0xa7d0, 0xa7d1 }, + { 0xa7d3, 0xa7d3 }, + { 0xa7d5, 0xa7dc }, + { 0xa7f2, 0xa801 }, + { 0xa803, 0xa805 }, + { 0xa807, 0xa80a }, + { 0xa80c, 0xa822 }, + { 0xa840, 0xa873 }, + { 0xa882, 0xa8b3 }, + { 0xa8f2, 0xa8f7 }, + { 0xa8fb, 0xa8fb }, + { 0xa8fd, 0xa8fe }, + { 0xa90a, 0xa925 }, + { 0xa930, 0xa946 }, + { 0xa960, 0xa97c }, + { 0xa984, 0xa9b2 }, + { 0xa9cf, 0xa9cf }, + { 0xa9e0, 0xa9e4 }, + { 0xa9e6, 0xa9ef }, + { 0xa9fa, 0xa9fe }, + { 0xaa00, 0xaa28 }, + { 0xaa40, 0xaa42 }, + { 0xaa44, 0xaa4b }, + { 0xaa60, 0xaa76 }, + { 0xaa7a, 0xaa7a }, + { 0xaa7e, 0xaaaf }, + { 0xaab1, 0xaab1 }, + { 0xaab5, 0xaab6 }, + { 0xaab9, 0xaabd }, + { 0xaac0, 0xaac0 }, + { 0xaac2, 0xaac2 }, + { 0xaadb, 0xaadd }, + { 0xaae0, 0xaaea }, + { 0xaaf2, 0xaaf4 }, + { 0xab01, 0xab06 }, + { 0xab09, 0xab0e }, + { 0xab11, 0xab16 }, + { 0xab20, 0xab26 }, + { 0xab28, 0xab2e }, + { 0xab30, 0xab5a }, + { 0xab5c, 0xab69 }, + { 0xab70, 0xabe2 }, + { 0xac00, 0xd7a3 }, + { 0xd7b0, 0xd7c6 }, + { 0xd7cb, 0xd7fb }, + { 0xf900, 0xfa6d }, + { 0xfa70, 0xfad9 }, + { 0xfb00, 0xfb06 }, + { 0xfb13, 0xfb17 }, + { 0xfb1d, 0xfb1d }, + { 0xfb1f, 0xfb28 }, + { 0xfb2a, 0xfb36 }, + { 0xfb38, 0xfb3c }, + { 0xfb3e, 0xfb3e }, + { 0xfb40, 0xfb41 }, + { 0xfb43, 0xfb44 }, + { 0xfb46, 0xfbb1 }, + { 0xfbd3, 0xfc5d }, + { 0xfc64, 0xfd3d }, + { 0xfd50, 0xfd8f }, + { 0xfd92, 0xfdc7 }, + { 0xfdf0, 0xfdf9 }, + { 0xfe71, 0xfe71 }, + { 0xfe73, 0xfe73 }, + { 0xfe77, 0xfe77 }, + { 0xfe79, 0xfe79 }, + { 0xfe7b, 0xfe7b }, + { 0xfe7d, 0xfe7d }, + { 0xfe7f, 0xfefc }, + { 0xff21, 0xff3a }, + { 0xff41, 0xff5a }, + { 0xff66, 0xff9d }, + { 0xffa0, 0xffbe }, + { 0xffc2, 0xffc7 }, + { 0xffca, 0xffcf }, + { 0xffd2, 0xffd7 }, + { 0xffda, 0xffdc }, + { 0x10000, 0x1000b }, + { 0x1000d, 0x10026 }, + { 0x10028, 0x1003a }, + { 0x1003c, 0x1003d }, + { 0x1003f, 0x1004d }, + { 0x10050, 0x1005d }, + { 0x10080, 0x100fa }, + { 0x10140, 0x10174 }, + { 0x10280, 0x1029c }, + { 0x102a0, 0x102d0 }, + { 0x10300, 0x1031f }, + { 0x1032d, 0x1034a }, + { 0x10350, 0x10375 }, + { 0x10380, 0x1039d }, + { 0x103a0, 0x103c3 }, + { 0x103c8, 0x103cf }, + { 0x103d1, 0x103d5 }, + { 0x10400, 0x1049d }, + { 0x104b0, 0x104d3 }, + { 0x104d8, 0x104fb }, + { 0x10500, 0x10527 }, + { 0x10530, 0x10563 }, + { 0x10570, 0x1057a }, + { 0x1057c, 0x1058a }, + { 0x1058c, 0x10592 }, + { 0x10594, 0x10595 }, + { 0x10597, 0x105a1 }, + { 0x105a3, 0x105b1 }, + { 0x105b3, 0x105b9 }, + { 0x105bb, 0x105bc }, + { 0x105c0, 0x105f3 }, + { 0x10600, 0x10736 }, + { 0x10740, 0x10755 }, + { 0x10760, 0x10767 }, + { 0x10780, 0x10785 }, + { 0x10787, 0x107b0 }, + { 0x107b2, 0x107ba }, + { 0x10800, 0x10805 }, + { 0x10808, 0x10808 }, + { 0x1080a, 0x10835 }, + { 0x10837, 0x10838 }, + { 0x1083c, 0x1083c }, + { 0x1083f, 0x10855 }, + { 0x10860, 0x10876 }, + { 0x10880, 0x1089e }, + { 0x108e0, 0x108f2 }, + { 0x108f4, 0x108f5 }, + { 0x10900, 0x10915 }, + { 0x10920, 0x10939 }, + { 0x10980, 0x109b7 }, + { 0x109be, 0x109bf }, + { 0x10a00, 0x10a00 }, + { 0x10a10, 0x10a13 }, + { 0x10a15, 0x10a17 }, + { 0x10a19, 0x10a35 }, + { 0x10a60, 0x10a7c }, + { 0x10a80, 0x10a9c }, + { 0x10ac0, 0x10ac7 }, + { 0x10ac9, 0x10ae4 }, + { 0x10b00, 0x10b35 }, + { 0x10b40, 0x10b55 }, + { 0x10b60, 0x10b72 }, + { 0x10b80, 0x10b91 }, + { 0x10c00, 0x10c48 }, + { 0x10c80, 0x10cb2 }, + { 0x10cc0, 0x10cf2 }, + { 0x10d00, 0x10d23 }, + { 0x10d4a, 0x10d65 }, + { 0x10d6f, 0x10d85 }, + { 0x10e80, 0x10ea9 }, + { 0x10eb0, 0x10eb1 }, + { 0x10ec2, 0x10ec4 }, + { 0x10f00, 0x10f1c }, + { 0x10f27, 0x10f27 }, + { 0x10f30, 0x10f45 }, + { 0x10f70, 0x10f81 }, + { 0x10fb0, 0x10fc4 }, + { 0x10fe0, 0x10ff6 }, + { 0x11003, 0x11037 }, + { 0x11071, 0x11072 }, + { 0x11075, 0x11075 }, + { 0x11083, 0x110af }, + { 0x110d0, 0x110e8 }, + { 0x11103, 0x11126 }, + { 0x11144, 0x11144 }, + { 0x11147, 0x11147 }, + { 0x11150, 0x11172 }, + { 0x11176, 0x11176 }, + { 0x11183, 0x111b2 }, + { 0x111c1, 0x111c4 }, + { 0x111da, 0x111da }, + { 0x111dc, 0x111dc }, + { 0x11200, 0x11211 }, + { 0x11213, 0x1122b }, + { 0x1123f, 0x11240 }, + { 0x11280, 0x11286 }, + { 0x11288, 0x11288 }, + { 0x1128a, 0x1128d }, + { 0x1128f, 0x1129d }, + { 0x1129f, 0x112a8 }, + { 0x112b0, 0x112de }, + { 0x11305, 0x1130c }, + { 0x1130f, 0x11310 }, + { 0x11313, 0x11328 }, + { 0x1132a, 0x11330 }, + { 0x11332, 0x11333 }, + { 0x11335, 0x11339 }, + { 0x1133d, 0x1133d }, + { 0x11350, 0x11350 }, + { 0x1135d, 0x11361 }, + { 0x11380, 0x11389 }, + { 0x1138b, 0x1138b }, + { 0x1138e, 0x1138e }, + { 0x11390, 0x113b5 }, + { 0x113b7, 0x113b7 }, + { 0x113d1, 0x113d1 }, + { 0x113d3, 0x113d3 }, + { 0x11400, 0x11434 }, + { 0x11447, 0x1144a }, + { 0x1145f, 0x11461 }, + { 0x11480, 0x114af }, + { 0x114c4, 0x114c5 }, + { 0x114c7, 0x114c7 }, + { 0x11580, 0x115ae }, + { 0x115d8, 0x115db }, + { 0x11600, 0x1162f }, + { 0x11644, 0x11644 }, + { 0x11680, 0x116aa }, + { 0x116b8, 0x116b8 }, + { 0x11700, 0x1171a }, + { 0x11740, 0x11746 }, + { 0x11800, 0x1182b }, + { 0x118a0, 0x118df }, + { 0x118ff, 0x11906 }, + { 0x11909, 0x11909 }, + { 0x1190c, 0x11913 }, + { 0x11915, 0x11916 }, + { 0x11918, 0x1192f }, + { 0x1193f, 0x1193f }, + { 0x11941, 0x11941 }, + { 0x119a0, 0x119a7 }, + { 0x119aa, 0x119d0 }, + { 0x119e1, 0x119e1 }, + { 0x119e3, 0x119e3 }, + { 0x11a00, 0x11a00 }, + { 0x11a0b, 0x11a32 }, + { 0x11a3a, 0x11a3a }, + { 0x11a50, 0x11a50 }, + { 0x11a5c, 0x11a89 }, + { 0x11a9d, 0x11a9d }, + { 0x11ab0, 0x11af8 }, + { 0x11bc0, 0x11be0 }, + { 0x11c00, 0x11c08 }, + { 0x11c0a, 0x11c2e }, + { 0x11c40, 0x11c40 }, + { 0x11c72, 0x11c8f }, + { 0x11d00, 0x11d06 }, + { 0x11d08, 0x11d09 }, + { 0x11d0b, 0x11d30 }, + { 0x11d46, 0x11d46 }, + { 0x11d60, 0x11d65 }, + { 0x11d67, 0x11d68 }, + { 0x11d6a, 0x11d89 }, + { 0x11d98, 0x11d98 }, + { 0x11ee0, 0x11ef2 }, + { 0x11f02, 0x11f02 }, + { 0x11f04, 0x11f10 }, + { 0x11f12, 0x11f33 }, + { 0x11fb0, 0x11fb0 }, + { 0x12000, 0x12399 }, + { 0x12400, 0x1246e }, + { 0x12480, 0x12543 }, + { 0x12f90, 0x12ff0 }, + { 0x13000, 0x1342f }, + { 0x13441, 0x13446 }, + { 0x13460, 0x143fa }, + { 0x14400, 0x14646 }, + { 0x16100, 0x1611d }, + { 0x16800, 0x16a38 }, + { 0x16a40, 0x16a5e }, + { 0x16a70, 0x16abe }, + { 0x16ad0, 0x16aed }, + { 0x16b00, 0x16b2f }, + { 0x16b40, 0x16b43 }, + { 0x16b63, 0x16b77 }, + { 0x16b7d, 0x16b8f }, + { 0x16d40, 0x16d6c }, + { 0x16e40, 0x16e7f }, + { 0x16f00, 0x16f4a }, + { 0x16f50, 0x16f50 }, + { 0x16f93, 0x16f9f }, + { 0x16fe0, 0x16fe1 }, + { 0x16fe3, 0x16fe3 }, + { 0x17000, 0x187f7 }, + { 0x18800, 0x18cd5 }, + { 0x18cff, 0x18d08 }, + { 0x1aff0, 0x1aff3 }, + { 0x1aff5, 0x1affb }, + { 0x1affd, 0x1affe }, + { 0x1b000, 0x1b122 }, + { 0x1b132, 0x1b132 }, + { 0x1b150, 0x1b152 }, + { 0x1b155, 0x1b155 }, + { 0x1b164, 0x1b167 }, + { 0x1b170, 0x1b2fb }, + { 0x1bc00, 0x1bc6a }, + { 0x1bc70, 0x1bc7c }, + { 0x1bc80, 0x1bc88 }, + { 0x1bc90, 0x1bc99 }, + { 0x1d400, 0x1d454 }, + { 0x1d456, 0x1d49c }, + { 0x1d49e, 0x1d49f }, + { 0x1d4a2, 0x1d4a2 }, + { 0x1d4a5, 0x1d4a6 }, + { 0x1d4a9, 0x1d4ac }, + { 0x1d4ae, 0x1d4b9 }, + { 0x1d4bb, 0x1d4bb }, + { 0x1d4bd, 0x1d4c3 }, + { 0x1d4c5, 0x1d505 }, + { 0x1d507, 0x1d50a }, + { 0x1d50d, 0x1d514 }, + { 0x1d516, 0x1d51c }, + { 0x1d51e, 0x1d539 }, + { 0x1d53b, 0x1d53e }, + { 0x1d540, 0x1d544 }, + { 0x1d546, 0x1d546 }, + { 0x1d54a, 0x1d550 }, + { 0x1d552, 0x1d6a5 }, + { 0x1d6a8, 0x1d6c0 }, + { 0x1d6c2, 0x1d6da }, + { 0x1d6dc, 0x1d6fa }, + { 0x1d6fc, 0x1d714 }, + { 0x1d716, 0x1d734 }, + { 0x1d736, 0x1d74e }, + { 0x1d750, 0x1d76e }, + { 0x1d770, 0x1d788 }, + { 0x1d78a, 0x1d7a8 }, + { 0x1d7aa, 0x1d7c2 }, + { 0x1d7c4, 0x1d7cb }, + { 0x1df00, 0x1df1e }, + { 0x1df25, 0x1df2a }, + { 0x1e030, 0x1e06d }, + { 0x1e100, 0x1e12c }, + { 0x1e137, 0x1e13d }, + { 0x1e14e, 0x1e14e }, + { 0x1e290, 0x1e2ad }, + { 0x1e2c0, 0x1e2eb }, + { 0x1e4d0, 0x1e4eb }, + { 0x1e5d0, 0x1e5ed }, + { 0x1e5f0, 0x1e5f0 }, + { 0x1e7e0, 0x1e7e6 }, + { 0x1e7e8, 0x1e7eb }, + { 0x1e7ed, 0x1e7ee }, + { 0x1e7f0, 0x1e7fe }, + { 0x1e800, 0x1e8c4 }, + { 0x1e900, 0x1e943 }, + { 0x1e94b, 0x1e94b }, + { 0x1ee00, 0x1ee03 }, + { 0x1ee05, 0x1ee1f }, + { 0x1ee21, 0x1ee22 }, + { 0x1ee24, 0x1ee24 }, + { 0x1ee27, 0x1ee27 }, + { 0x1ee29, 0x1ee32 }, + { 0x1ee34, 0x1ee37 }, + { 0x1ee39, 0x1ee39 }, + { 0x1ee3b, 0x1ee3b }, + { 0x1ee42, 0x1ee42 }, + { 0x1ee47, 0x1ee47 }, + { 0x1ee49, 0x1ee49 }, + { 0x1ee4b, 0x1ee4b }, + { 0x1ee4d, 0x1ee4f }, + { 0x1ee51, 0x1ee52 }, + { 0x1ee54, 0x1ee54 }, + { 0x1ee57, 0x1ee57 }, + { 0x1ee59, 0x1ee59 }, + { 0x1ee5b, 0x1ee5b }, + { 0x1ee5d, 0x1ee5d }, + { 0x1ee5f, 0x1ee5f }, + { 0x1ee61, 0x1ee62 }, + { 0x1ee64, 0x1ee64 }, + { 0x1ee67, 0x1ee6a }, + { 0x1ee6c, 0x1ee72 }, + { 0x1ee74, 0x1ee77 }, + { 0x1ee79, 0x1ee7c }, + { 0x1ee7e, 0x1ee7e }, + { 0x1ee80, 0x1ee89 }, + { 0x1ee8b, 0x1ee9b }, + { 0x1eea1, 0x1eea3 }, + { 0x1eea5, 0x1eea9 }, + { 0x1eeab, 0x1eebb }, + { 0x20000, 0x2a6df }, + { 0x2a700, 0x2b739 }, + { 0x2b740, 0x2b81d }, + { 0x2b820, 0x2cea1 }, + { 0x2ceb0, 0x2ebe0 }, + { 0x2ebf0, 0x2ee5d }, + { 0x2f800, 0x2fa1d }, + { 0x30000, 0x3134a }, + { 0x31350, 0x323af }, +}; + +constexpr inline CharRange xid_continue[] = { + { 0x30, 0x39 }, + { 0x41, 0x5a }, + { 0x5f, 0x5f }, + { 0x61, 0x7a }, + { 0xaa, 0xaa }, + { 0xb5, 0xb5 }, + { 0xb7, 0xb7 }, + { 0xba, 0xba }, + { 0xc0, 0xd6 }, + { 0xd8, 0xf6 }, + { 0xf8, 0x2c1 }, + { 0x2c6, 0x2d1 }, + { 0x2e0, 0x2e4 }, + { 0x2ec, 0x2ec }, + { 0x2ee, 0x2ee }, + { 0x300, 0x374 }, + { 0x376, 0x377 }, + { 0x37b, 0x37d }, + { 0x37f, 0x37f }, + { 0x386, 0x38a }, + { 0x38c, 0x38c }, + { 0x38e, 0x3a1 }, + { 0x3a3, 0x3f5 }, + { 0x3f7, 0x481 }, + { 0x483, 0x487 }, + { 0x48a, 0x52f }, + { 0x531, 0x556 }, + { 0x559, 0x559 }, + { 0x560, 0x588 }, + { 0x591, 0x5bd }, + { 0x5bf, 0x5bf }, + { 0x5c1, 0x5c2 }, + { 0x5c4, 0x5c5 }, + { 0x5c7, 0x5c7 }, + { 0x5d0, 0x5ea }, + { 0x5ef, 0x5f2 }, + { 0x610, 0x61a }, + { 0x620, 0x669 }, + { 0x66e, 0x6d3 }, + { 0x6d5, 0x6dc }, + { 0x6df, 0x6e8 }, + { 0x6ea, 0x6fc }, + { 0x6ff, 0x6ff }, + { 0x710, 0x74a }, + { 0x74d, 0x7b1 }, + { 0x7c0, 0x7f5 }, + { 0x7fa, 0x7fa }, + { 0x7fd, 0x7fd }, + { 0x800, 0x82d }, + { 0x840, 0x85b }, + { 0x860, 0x86a }, + { 0x870, 0x887 }, + { 0x889, 0x88e }, + { 0x897, 0x8e1 }, + { 0x8e3, 0x963 }, + { 0x966, 0x96f }, + { 0x971, 0x983 }, + { 0x985, 0x98c }, + { 0x98f, 0x990 }, + { 0x993, 0x9a8 }, + { 0x9aa, 0x9b0 }, + { 0x9b2, 0x9b2 }, + { 0x9b6, 0x9b9 }, + { 0x9bc, 0x9c4 }, + { 0x9c7, 0x9c8 }, + { 0x9cb, 0x9ce }, + { 0x9d7, 0x9d7 }, + { 0x9dc, 0x9dd }, + { 0x9df, 0x9e3 }, + { 0x9e6, 0x9f1 }, + { 0x9fc, 0x9fc }, + { 0x9fe, 0x9fe }, + { 0xa01, 0xa03 }, + { 0xa05, 0xa0a }, + { 0xa0f, 0xa10 }, + { 0xa13, 0xa28 }, + { 0xa2a, 0xa30 }, + { 0xa32, 0xa33 }, + { 0xa35, 0xa36 }, + { 0xa38, 0xa39 }, + { 0xa3c, 0xa3c }, + { 0xa3e, 0xa42 }, + { 0xa47, 0xa48 }, + { 0xa4b, 0xa4d }, + { 0xa51, 0xa51 }, + { 0xa59, 0xa5c }, + { 0xa5e, 0xa5e }, + { 0xa66, 0xa75 }, + { 0xa81, 0xa83 }, + { 0xa85, 0xa8d }, + { 0xa8f, 0xa91 }, + { 0xa93, 0xaa8 }, + { 0xaaa, 0xab0 }, + { 0xab2, 0xab3 }, + { 0xab5, 0xab9 }, + { 0xabc, 0xac5 }, + { 0xac7, 0xac9 }, + { 0xacb, 0xacd }, + { 0xad0, 0xad0 }, + { 0xae0, 0xae3 }, + { 0xae6, 0xaef }, + { 0xaf9, 0xaff }, + { 0xb01, 0xb03 }, + { 0xb05, 0xb0c }, + { 0xb0f, 0xb10 }, + { 0xb13, 0xb28 }, + { 0xb2a, 0xb30 }, + { 0xb32, 0xb33 }, + { 0xb35, 0xb39 }, + { 0xb3c, 0xb44 }, + { 0xb47, 0xb48 }, + { 0xb4b, 0xb4d }, + { 0xb55, 0xb57 }, + { 0xb5c, 0xb5d }, + { 0xb5f, 0xb63 }, + { 0xb66, 0xb6f }, + { 0xb71, 0xb71 }, + { 0xb82, 0xb83 }, + { 0xb85, 0xb8a }, + { 0xb8e, 0xb90 }, + { 0xb92, 0xb95 }, + { 0xb99, 0xb9a }, + { 0xb9c, 0xb9c }, + { 0xb9e, 0xb9f }, + { 0xba3, 0xba4 }, + { 0xba8, 0xbaa }, + { 0xbae, 0xbb9 }, + { 0xbbe, 0xbc2 }, + { 0xbc6, 0xbc8 }, + { 0xbca, 0xbcd }, + { 0xbd0, 0xbd0 }, + { 0xbd7, 0xbd7 }, + { 0xbe6, 0xbef }, + { 0xc00, 0xc0c }, + { 0xc0e, 0xc10 }, + { 0xc12, 0xc28 }, + { 0xc2a, 0xc39 }, + { 0xc3c, 0xc44 }, + { 0xc46, 0xc48 }, + { 0xc4a, 0xc4d }, + { 0xc55, 0xc56 }, + { 0xc58, 0xc5a }, + { 0xc5d, 0xc5d }, + { 0xc60, 0xc63 }, + { 0xc66, 0xc6f }, + { 0xc80, 0xc83 }, + { 0xc85, 0xc8c }, + { 0xc8e, 0xc90 }, + { 0xc92, 0xca8 }, + { 0xcaa, 0xcb3 }, + { 0xcb5, 0xcb9 }, + { 0xcbc, 0xcc4 }, + { 0xcc6, 0xcc8 }, + { 0xcca, 0xccd }, + { 0xcd5, 0xcd6 }, + { 0xcdd, 0xcde }, + { 0xce0, 0xce3 }, + { 0xce6, 0xcef }, + { 0xcf1, 0xcf3 }, + { 0xd00, 0xd0c }, + { 0xd0e, 0xd10 }, + { 0xd12, 0xd44 }, + { 0xd46, 0xd48 }, + { 0xd4a, 0xd4e }, + { 0xd54, 0xd57 }, + { 0xd5f, 0xd63 }, + { 0xd66, 0xd6f }, + { 0xd7a, 0xd7f }, + { 0xd81, 0xd83 }, + { 0xd85, 0xd96 }, + { 0xd9a, 0xdb1 }, + { 0xdb3, 0xdbb }, + { 0xdbd, 0xdbd }, + { 0xdc0, 0xdc6 }, + { 0xdca, 0xdca }, + { 0xdcf, 0xdd4 }, + { 0xdd6, 0xdd6 }, + { 0xdd8, 0xddf }, + { 0xde6, 0xdef }, + { 0xdf2, 0xdf3 }, + { 0xe01, 0xe3a }, + { 0xe40, 0xe4e }, + { 0xe50, 0xe59 }, + { 0xe81, 0xe82 }, + { 0xe84, 0xe84 }, + { 0xe86, 0xe8a }, + { 0xe8c, 0xea3 }, + { 0xea5, 0xea5 }, + { 0xea7, 0xebd }, + { 0xec0, 0xec4 }, + { 0xec6, 0xec6 }, + { 0xec8, 0xece }, + { 0xed0, 0xed9 }, + { 0xedc, 0xedf }, + { 0xf00, 0xf00 }, + { 0xf18, 0xf19 }, + { 0xf20, 0xf29 }, + { 0xf35, 0xf35 }, + { 0xf37, 0xf37 }, + { 0xf39, 0xf39 }, + { 0xf3e, 0xf47 }, + { 0xf49, 0xf6c }, + { 0xf71, 0xf84 }, + { 0xf86, 0xf97 }, + { 0xf99, 0xfbc }, + { 0xfc6, 0xfc6 }, + { 0x1000, 0x1049 }, + { 0x1050, 0x109d }, + { 0x10a0, 0x10c5 }, + { 0x10c7, 0x10c7 }, + { 0x10cd, 0x10cd }, + { 0x10d0, 0x10fa }, + { 0x10fc, 0x1248 }, + { 0x124a, 0x124d }, + { 0x1250, 0x1256 }, + { 0x1258, 0x1258 }, + { 0x125a, 0x125d }, + { 0x1260, 0x1288 }, + { 0x128a, 0x128d }, + { 0x1290, 0x12b0 }, + { 0x12b2, 0x12b5 }, + { 0x12b8, 0x12be }, + { 0x12c0, 0x12c0 }, + { 0x12c2, 0x12c5 }, + { 0x12c8, 0x12d6 }, + { 0x12d8, 0x1310 }, + { 0x1312, 0x1315 }, + { 0x1318, 0x135a }, + { 0x135d, 0x135f }, + { 0x1369, 0x1371 }, + { 0x1380, 0x138f }, + { 0x13a0, 0x13f5 }, + { 0x13f8, 0x13fd }, + { 0x1401, 0x166c }, + { 0x166f, 0x167f }, + { 0x1681, 0x169a }, + { 0x16a0, 0x16ea }, + { 0x16ee, 0x16f8 }, + { 0x1700, 0x1715 }, + { 0x171f, 0x1734 }, + { 0x1740, 0x1753 }, + { 0x1760, 0x176c }, + { 0x176e, 0x1770 }, + { 0x1772, 0x1773 }, + { 0x1780, 0x17d3 }, + { 0x17d7, 0x17d7 }, + { 0x17dc, 0x17dd }, + { 0x17e0, 0x17e9 }, + { 0x180b, 0x180d }, + { 0x180f, 0x1819 }, + { 0x1820, 0x1878 }, + { 0x1880, 0x18aa }, + { 0x18b0, 0x18f5 }, + { 0x1900, 0x191e }, + { 0x1920, 0x192b }, + { 0x1930, 0x193b }, + { 0x1946, 0x196d }, + { 0x1970, 0x1974 }, + { 0x1980, 0x19ab }, + { 0x19b0, 0x19c9 }, + { 0x19d0, 0x19da }, + { 0x1a00, 0x1a1b }, + { 0x1a20, 0x1a5e }, + { 0x1a60, 0x1a7c }, + { 0x1a7f, 0x1a89 }, + { 0x1a90, 0x1a99 }, + { 0x1aa7, 0x1aa7 }, + { 0x1ab0, 0x1abd }, + { 0x1abf, 0x1ace }, + { 0x1b00, 0x1b4c }, + { 0x1b50, 0x1b59 }, + { 0x1b6b, 0x1b73 }, + { 0x1b80, 0x1bf3 }, + { 0x1c00, 0x1c37 }, + { 0x1c40, 0x1c49 }, + { 0x1c4d, 0x1c7d }, + { 0x1c80, 0x1c8a }, + { 0x1c90, 0x1cba }, + { 0x1cbd, 0x1cbf }, + { 0x1cd0, 0x1cd2 }, + { 0x1cd4, 0x1cfa }, + { 0x1d00, 0x1f15 }, + { 0x1f18, 0x1f1d }, + { 0x1f20, 0x1f45 }, + { 0x1f48, 0x1f4d }, + { 0x1f50, 0x1f57 }, + { 0x1f59, 0x1f59 }, + { 0x1f5b, 0x1f5b }, + { 0x1f5d, 0x1f5d }, + { 0x1f5f, 0x1f7d }, + { 0x1f80, 0x1fb4 }, + { 0x1fb6, 0x1fbc }, + { 0x1fbe, 0x1fbe }, + { 0x1fc2, 0x1fc4 }, + { 0x1fc6, 0x1fcc }, + { 0x1fd0, 0x1fd3 }, + { 0x1fd6, 0x1fdb }, + { 0x1fe0, 0x1fec }, + { 0x1ff2, 0x1ff4 }, + { 0x1ff6, 0x1ffc }, + { 0x200c, 0x200d }, + { 0x203f, 0x2040 }, + { 0x2054, 0x2054 }, + { 0x2071, 0x2071 }, + { 0x207f, 0x207f }, + { 0x2090, 0x209c }, + { 0x20d0, 0x20dc }, + { 0x20e1, 0x20e1 }, + { 0x20e5, 0x20f0 }, + { 0x2102, 0x2102 }, + { 0x2107, 0x2107 }, + { 0x210a, 0x2113 }, + { 0x2115, 0x2115 }, + { 0x2118, 0x211d }, + { 0x2124, 0x2124 }, + { 0x2126, 0x2126 }, + { 0x2128, 0x2128 }, + { 0x212a, 0x2139 }, + { 0x213c, 0x213f }, + { 0x2145, 0x2149 }, + { 0x214e, 0x214e }, + { 0x2160, 0x2188 }, + { 0x2c00, 0x2ce4 }, + { 0x2ceb, 0x2cf3 }, + { 0x2d00, 0x2d25 }, + { 0x2d27, 0x2d27 }, + { 0x2d2d, 0x2d2d }, + { 0x2d30, 0x2d67 }, + { 0x2d6f, 0x2d6f }, + { 0x2d7f, 0x2d96 }, + { 0x2da0, 0x2da6 }, + { 0x2da8, 0x2dae }, + { 0x2db0, 0x2db6 }, + { 0x2db8, 0x2dbe }, + { 0x2dc0, 0x2dc6 }, + { 0x2dc8, 0x2dce }, + { 0x2dd0, 0x2dd6 }, + { 0x2dd8, 0x2dde }, + { 0x2de0, 0x2dff }, + { 0x3005, 0x3007 }, + { 0x3021, 0x302f }, + { 0x3031, 0x3035 }, + { 0x3038, 0x303c }, + { 0x3041, 0x3096 }, + { 0x3099, 0x309a }, + { 0x309d, 0x309f }, + { 0x30a1, 0x30ff }, + { 0x3105, 0x312f }, + { 0x3131, 0x318e }, + { 0x31a0, 0x31bf }, + { 0x31f0, 0x31ff }, + { 0x3400, 0x4dbf }, + { 0x4e00, 0xa48c }, + { 0xa4d0, 0xa4fd }, + { 0xa500, 0xa60c }, + { 0xa610, 0xa62b }, + { 0xa640, 0xa66f }, + { 0xa674, 0xa67d }, + { 0xa67f, 0xa6f1 }, + { 0xa717, 0xa71f }, + { 0xa722, 0xa788 }, + { 0xa78b, 0xa7cd }, + { 0xa7d0, 0xa7d1 }, + { 0xa7d3, 0xa7d3 }, + { 0xa7d5, 0xa7dc }, + { 0xa7f2, 0xa827 }, + { 0xa82c, 0xa82c }, + { 0xa840, 0xa873 }, + { 0xa880, 0xa8c5 }, + { 0xa8d0, 0xa8d9 }, + { 0xa8e0, 0xa8f7 }, + { 0xa8fb, 0xa8fb }, + { 0xa8fd, 0xa92d }, + { 0xa930, 0xa953 }, + { 0xa960, 0xa97c }, + { 0xa980, 0xa9c0 }, + { 0xa9cf, 0xa9d9 }, + { 0xa9e0, 0xa9fe }, + { 0xaa00, 0xaa36 }, + { 0xaa40, 0xaa4d }, + { 0xaa50, 0xaa59 }, + { 0xaa60, 0xaa76 }, + { 0xaa7a, 0xaac2 }, + { 0xaadb, 0xaadd }, + { 0xaae0, 0xaaef }, + { 0xaaf2, 0xaaf6 }, + { 0xab01, 0xab06 }, + { 0xab09, 0xab0e }, + { 0xab11, 0xab16 }, + { 0xab20, 0xab26 }, + { 0xab28, 0xab2e }, + { 0xab30, 0xab5a }, + { 0xab5c, 0xab69 }, + { 0xab70, 0xabea }, + { 0xabec, 0xabed }, + { 0xabf0, 0xabf9 }, + { 0xac00, 0xd7a3 }, + { 0xd7b0, 0xd7c6 }, + { 0xd7cb, 0xd7fb }, + { 0xf900, 0xfa6d }, + { 0xfa70, 0xfad9 }, + { 0xfb00, 0xfb06 }, + { 0xfb13, 0xfb17 }, + { 0xfb1d, 0xfb28 }, + { 0xfb2a, 0xfb36 }, + { 0xfb38, 0xfb3c }, + { 0xfb3e, 0xfb3e }, + { 0xfb40, 0xfb41 }, + { 0xfb43, 0xfb44 }, + { 0xfb46, 0xfbb1 }, + { 0xfbd3, 0xfc5d }, + { 0xfc64, 0xfd3d }, + { 0xfd50, 0xfd8f }, + { 0xfd92, 0xfdc7 }, + { 0xfdf0, 0xfdf9 }, + { 0xfe00, 0xfe0f }, + { 0xfe20, 0xfe2f }, + { 0xfe33, 0xfe34 }, + { 0xfe4d, 0xfe4f }, + { 0xfe71, 0xfe71 }, + { 0xfe73, 0xfe73 }, + { 0xfe77, 0xfe77 }, + { 0xfe79, 0xfe79 }, + { 0xfe7b, 0xfe7b }, + { 0xfe7d, 0xfe7d }, + { 0xfe7f, 0xfefc }, + { 0xff10, 0xff19 }, + { 0xff21, 0xff3a }, + { 0xff3f, 0xff3f }, + { 0xff41, 0xff5a }, + { 0xff65, 0xffbe }, + { 0xffc2, 0xffc7 }, + { 0xffca, 0xffcf }, + { 0xffd2, 0xffd7 }, + { 0xffda, 0xffdc }, + { 0x10000, 0x1000b }, + { 0x1000d, 0x10026 }, + { 0x10028, 0x1003a }, + { 0x1003c, 0x1003d }, + { 0x1003f, 0x1004d }, + { 0x10050, 0x1005d }, + { 0x10080, 0x100fa }, + { 0x10140, 0x10174 }, + { 0x101fd, 0x101fd }, + { 0x10280, 0x1029c }, + { 0x102a0, 0x102d0 }, + { 0x102e0, 0x102e0 }, + { 0x10300, 0x1031f }, + { 0x1032d, 0x1034a }, + { 0x10350, 0x1037a }, + { 0x10380, 0x1039d }, + { 0x103a0, 0x103c3 }, + { 0x103c8, 0x103cf }, + { 0x103d1, 0x103d5 }, + { 0x10400, 0x1049d }, + { 0x104a0, 0x104a9 }, + { 0x104b0, 0x104d3 }, + { 0x104d8, 0x104fb }, + { 0x10500, 0x10527 }, + { 0x10530, 0x10563 }, + { 0x10570, 0x1057a }, + { 0x1057c, 0x1058a }, + { 0x1058c, 0x10592 }, + { 0x10594, 0x10595 }, + { 0x10597, 0x105a1 }, + { 0x105a3, 0x105b1 }, + { 0x105b3, 0x105b9 }, + { 0x105bb, 0x105bc }, + { 0x105c0, 0x105f3 }, + { 0x10600, 0x10736 }, + { 0x10740, 0x10755 }, + { 0x10760, 0x10767 }, + { 0x10780, 0x10785 }, + { 0x10787, 0x107b0 }, + { 0x107b2, 0x107ba }, + { 0x10800, 0x10805 }, + { 0x10808, 0x10808 }, + { 0x1080a, 0x10835 }, + { 0x10837, 0x10838 }, + { 0x1083c, 0x1083c }, + { 0x1083f, 0x10855 }, + { 0x10860, 0x10876 }, + { 0x10880, 0x1089e }, + { 0x108e0, 0x108f2 }, + { 0x108f4, 0x108f5 }, + { 0x10900, 0x10915 }, + { 0x10920, 0x10939 }, + { 0x10980, 0x109b7 }, + { 0x109be, 0x109bf }, + { 0x10a00, 0x10a03 }, + { 0x10a05, 0x10a06 }, + { 0x10a0c, 0x10a13 }, + { 0x10a15, 0x10a17 }, + { 0x10a19, 0x10a35 }, + { 0x10a38, 0x10a3a }, + { 0x10a3f, 0x10a3f }, + { 0x10a60, 0x10a7c }, + { 0x10a80, 0x10a9c }, + { 0x10ac0, 0x10ac7 }, + { 0x10ac9, 0x10ae6 }, + { 0x10b00, 0x10b35 }, + { 0x10b40, 0x10b55 }, + { 0x10b60, 0x10b72 }, + { 0x10b80, 0x10b91 }, + { 0x10c00, 0x10c48 }, + { 0x10c80, 0x10cb2 }, + { 0x10cc0, 0x10cf2 }, + { 0x10d00, 0x10d27 }, + { 0x10d30, 0x10d39 }, + { 0x10d40, 0x10d65 }, + { 0x10d69, 0x10d6d }, + { 0x10d6f, 0x10d85 }, + { 0x10e80, 0x10ea9 }, + { 0x10eab, 0x10eac }, + { 0x10eb0, 0x10eb1 }, + { 0x10ec2, 0x10ec4 }, + { 0x10efc, 0x10f1c }, + { 0x10f27, 0x10f27 }, + { 0x10f30, 0x10f50 }, + { 0x10f70, 0x10f85 }, + { 0x10fb0, 0x10fc4 }, + { 0x10fe0, 0x10ff6 }, + { 0x11000, 0x11046 }, + { 0x11066, 0x11075 }, + { 0x1107f, 0x110ba }, + { 0x110c2, 0x110c2 }, + { 0x110d0, 0x110e8 }, + { 0x110f0, 0x110f9 }, + { 0x11100, 0x11134 }, + { 0x11136, 0x1113f }, + { 0x11144, 0x11147 }, + { 0x11150, 0x11173 }, + { 0x11176, 0x11176 }, + { 0x11180, 0x111c4 }, + { 0x111c9, 0x111cc }, + { 0x111ce, 0x111da }, + { 0x111dc, 0x111dc }, + { 0x11200, 0x11211 }, + { 0x11213, 0x11237 }, + { 0x1123e, 0x11241 }, + { 0x11280, 0x11286 }, + { 0x11288, 0x11288 }, + { 0x1128a, 0x1128d }, + { 0x1128f, 0x1129d }, + { 0x1129f, 0x112a8 }, + { 0x112b0, 0x112ea }, + { 0x112f0, 0x112f9 }, + { 0x11300, 0x11303 }, + { 0x11305, 0x1130c }, + { 0x1130f, 0x11310 }, + { 0x11313, 0x11328 }, + { 0x1132a, 0x11330 }, + { 0x11332, 0x11333 }, + { 0x11335, 0x11339 }, + { 0x1133b, 0x11344 }, + { 0x11347, 0x11348 }, + { 0x1134b, 0x1134d }, + { 0x11350, 0x11350 }, + { 0x11357, 0x11357 }, + { 0x1135d, 0x11363 }, + { 0x11366, 0x1136c }, + { 0x11370, 0x11374 }, + { 0x11380, 0x11389 }, + { 0x1138b, 0x1138b }, + { 0x1138e, 0x1138e }, + { 0x11390, 0x113b5 }, + { 0x113b7, 0x113c0 }, + { 0x113c2, 0x113c2 }, + { 0x113c5, 0x113c5 }, + { 0x113c7, 0x113ca }, + { 0x113cc, 0x113d3 }, + { 0x113e1, 0x113e2 }, + { 0x11400, 0x1144a }, + { 0x11450, 0x11459 }, + { 0x1145e, 0x11461 }, + { 0x11480, 0x114c5 }, + { 0x114c7, 0x114c7 }, + { 0x114d0, 0x114d9 }, + { 0x11580, 0x115b5 }, + { 0x115b8, 0x115c0 }, + { 0x115d8, 0x115dd }, + { 0x11600, 0x11640 }, + { 0x11644, 0x11644 }, + { 0x11650, 0x11659 }, + { 0x11680, 0x116b8 }, + { 0x116c0, 0x116c9 }, + { 0x116d0, 0x116e3 }, + { 0x11700, 0x1171a }, + { 0x1171d, 0x1172b }, + { 0x11730, 0x11739 }, + { 0x11740, 0x11746 }, + { 0x11800, 0x1183a }, + { 0x118a0, 0x118e9 }, + { 0x118ff, 0x11906 }, + { 0x11909, 0x11909 }, + { 0x1190c, 0x11913 }, + { 0x11915, 0x11916 }, + { 0x11918, 0x11935 }, + { 0x11937, 0x11938 }, + { 0x1193b, 0x11943 }, + { 0x11950, 0x11959 }, + { 0x119a0, 0x119a7 }, + { 0x119aa, 0x119d7 }, + { 0x119da, 0x119e1 }, + { 0x119e3, 0x119e4 }, + { 0x11a00, 0x11a3e }, + { 0x11a47, 0x11a47 }, + { 0x11a50, 0x11a99 }, + { 0x11a9d, 0x11a9d }, + { 0x11ab0, 0x11af8 }, + { 0x11bc0, 0x11be0 }, + { 0x11bf0, 0x11bf9 }, + { 0x11c00, 0x11c08 }, + { 0x11c0a, 0x11c36 }, + { 0x11c38, 0x11c40 }, + { 0x11c50, 0x11c59 }, + { 0x11c72, 0x11c8f }, + { 0x11c92, 0x11ca7 }, + { 0x11ca9, 0x11cb6 }, + { 0x11d00, 0x11d06 }, + { 0x11d08, 0x11d09 }, + { 0x11d0b, 0x11d36 }, + { 0x11d3a, 0x11d3a }, + { 0x11d3c, 0x11d3d }, + { 0x11d3f, 0x11d47 }, + { 0x11d50, 0x11d59 }, + { 0x11d60, 0x11d65 }, + { 0x11d67, 0x11d68 }, + { 0x11d6a, 0x11d8e }, + { 0x11d90, 0x11d91 }, + { 0x11d93, 0x11d98 }, + { 0x11da0, 0x11da9 }, + { 0x11ee0, 0x11ef6 }, + { 0x11f00, 0x11f10 }, + { 0x11f12, 0x11f3a }, + { 0x11f3e, 0x11f42 }, + { 0x11f50, 0x11f5a }, + { 0x11fb0, 0x11fb0 }, + { 0x12000, 0x12399 }, + { 0x12400, 0x1246e }, + { 0x12480, 0x12543 }, + { 0x12f90, 0x12ff0 }, + { 0x13000, 0x1342f }, + { 0x13440, 0x13455 }, + { 0x13460, 0x143fa }, + { 0x14400, 0x14646 }, + { 0x16100, 0x16139 }, + { 0x16800, 0x16a38 }, + { 0x16a40, 0x16a5e }, + { 0x16a60, 0x16a69 }, + { 0x16a70, 0x16abe }, + { 0x16ac0, 0x16ac9 }, + { 0x16ad0, 0x16aed }, + { 0x16af0, 0x16af4 }, + { 0x16b00, 0x16b36 }, + { 0x16b40, 0x16b43 }, + { 0x16b50, 0x16b59 }, + { 0x16b63, 0x16b77 }, + { 0x16b7d, 0x16b8f }, + { 0x16d40, 0x16d6c }, + { 0x16d70, 0x16d79 }, + { 0x16e40, 0x16e7f }, + { 0x16f00, 0x16f4a }, + { 0x16f4f, 0x16f87 }, + { 0x16f8f, 0x16f9f }, + { 0x16fe0, 0x16fe1 }, + { 0x16fe3, 0x16fe4 }, + { 0x16ff0, 0x16ff1 }, + { 0x17000, 0x187f7 }, + { 0x18800, 0x18cd5 }, + { 0x18cff, 0x18d08 }, + { 0x1aff0, 0x1aff3 }, + { 0x1aff5, 0x1affb }, + { 0x1affd, 0x1affe }, + { 0x1b000, 0x1b122 }, + { 0x1b132, 0x1b132 }, + { 0x1b150, 0x1b152 }, + { 0x1b155, 0x1b155 }, + { 0x1b164, 0x1b167 }, + { 0x1b170, 0x1b2fb }, + { 0x1bc00, 0x1bc6a }, + { 0x1bc70, 0x1bc7c }, + { 0x1bc80, 0x1bc88 }, + { 0x1bc90, 0x1bc99 }, + { 0x1bc9d, 0x1bc9e }, + { 0x1ccf0, 0x1ccf9 }, + { 0x1cf00, 0x1cf2d }, + { 0x1cf30, 0x1cf46 }, + { 0x1d165, 0x1d169 }, + { 0x1d16d, 0x1d172 }, + { 0x1d17b, 0x1d182 }, + { 0x1d185, 0x1d18b }, + { 0x1d1aa, 0x1d1ad }, + { 0x1d242, 0x1d244 }, + { 0x1d400, 0x1d454 }, + { 0x1d456, 0x1d49c }, + { 0x1d49e, 0x1d49f }, + { 0x1d4a2, 0x1d4a2 }, + { 0x1d4a5, 0x1d4a6 }, + { 0x1d4a9, 0x1d4ac }, + { 0x1d4ae, 0x1d4b9 }, + { 0x1d4bb, 0x1d4bb }, + { 0x1d4bd, 0x1d4c3 }, + { 0x1d4c5, 0x1d505 }, + { 0x1d507, 0x1d50a }, + { 0x1d50d, 0x1d514 }, + { 0x1d516, 0x1d51c }, + { 0x1d51e, 0x1d539 }, + { 0x1d53b, 0x1d53e }, + { 0x1d540, 0x1d544 }, + { 0x1d546, 0x1d546 }, + { 0x1d54a, 0x1d550 }, + { 0x1d552, 0x1d6a5 }, + { 0x1d6a8, 0x1d6c0 }, + { 0x1d6c2, 0x1d6da }, + { 0x1d6dc, 0x1d6fa }, + { 0x1d6fc, 0x1d714 }, + { 0x1d716, 0x1d734 }, + { 0x1d736, 0x1d74e }, + { 0x1d750, 0x1d76e }, + { 0x1d770, 0x1d788 }, + { 0x1d78a, 0x1d7a8 }, + { 0x1d7aa, 0x1d7c2 }, + { 0x1d7c4, 0x1d7cb }, + { 0x1d7ce, 0x1d7ff }, + { 0x1da00, 0x1da36 }, + { 0x1da3b, 0x1da6c }, + { 0x1da75, 0x1da75 }, + { 0x1da84, 0x1da84 }, + { 0x1da9b, 0x1da9f }, + { 0x1daa1, 0x1daaf }, + { 0x1df00, 0x1df1e }, + { 0x1df25, 0x1df2a }, + { 0x1e000, 0x1e006 }, + { 0x1e008, 0x1e018 }, + { 0x1e01b, 0x1e021 }, + { 0x1e023, 0x1e024 }, + { 0x1e026, 0x1e02a }, + { 0x1e030, 0x1e06d }, + { 0x1e08f, 0x1e08f }, + { 0x1e100, 0x1e12c }, + { 0x1e130, 0x1e13d }, + { 0x1e140, 0x1e149 }, + { 0x1e14e, 0x1e14e }, + { 0x1e290, 0x1e2ae }, + { 0x1e2c0, 0x1e2f9 }, + { 0x1e4d0, 0x1e4f9 }, + { 0x1e5d0, 0x1e5fa }, + { 0x1e7e0, 0x1e7e6 }, + { 0x1e7e8, 0x1e7eb }, + { 0x1e7ed, 0x1e7ee }, + { 0x1e7f0, 0x1e7fe }, + { 0x1e800, 0x1e8c4 }, + { 0x1e8d0, 0x1e8d6 }, + { 0x1e900, 0x1e94b }, + { 0x1e950, 0x1e959 }, + { 0x1ee00, 0x1ee03 }, + { 0x1ee05, 0x1ee1f }, + { 0x1ee21, 0x1ee22 }, + { 0x1ee24, 0x1ee24 }, + { 0x1ee27, 0x1ee27 }, + { 0x1ee29, 0x1ee32 }, + { 0x1ee34, 0x1ee37 }, + { 0x1ee39, 0x1ee39 }, + { 0x1ee3b, 0x1ee3b }, + { 0x1ee42, 0x1ee42 }, + { 0x1ee47, 0x1ee47 }, + { 0x1ee49, 0x1ee49 }, + { 0x1ee4b, 0x1ee4b }, + { 0x1ee4d, 0x1ee4f }, + { 0x1ee51, 0x1ee52 }, + { 0x1ee54, 0x1ee54 }, + { 0x1ee57, 0x1ee57 }, + { 0x1ee59, 0x1ee59 }, + { 0x1ee5b, 0x1ee5b }, + { 0x1ee5d, 0x1ee5d }, + { 0x1ee5f, 0x1ee5f }, + { 0x1ee61, 0x1ee62 }, + { 0x1ee64, 0x1ee64 }, + { 0x1ee67, 0x1ee6a }, + { 0x1ee6c, 0x1ee72 }, + { 0x1ee74, 0x1ee77 }, + { 0x1ee79, 0x1ee7c }, + { 0x1ee7e, 0x1ee7e }, + { 0x1ee80, 0x1ee89 }, + { 0x1ee8b, 0x1ee9b }, + { 0x1eea1, 0x1eea3 }, + { 0x1eea5, 0x1eea9 }, + { 0x1eeab, 0x1eebb }, + { 0x1fbf0, 0x1fbf9 }, + { 0x20000, 0x2a6df }, + { 0x2a700, 0x2b739 }, + { 0x2b740, 0x2b81d }, + { 0x2b820, 0x2cea1 }, + { 0x2ceb0, 0x2ebe0 }, + { 0x2ebf0, 0x2ee5d }, + { 0x2f800, 0x2fa1d }, + { 0x30000, 0x3134a }, + { 0x31350, 0x323af }, + { 0xe0100, 0xe01ef }, +}; + +constexpr inline CharRange uppercase_letter[] = { + { 0x41, 0x5a }, + { 0xc0, 0xd6 }, + { 0xd8, 0xde }, + { 0x100, 0x100 }, + { 0x102, 0x102 }, + { 0x104, 0x104 }, + { 0x106, 0x106 }, + { 0x108, 0x108 }, + { 0x10a, 0x10a }, + { 0x10c, 0x10c }, + { 0x10e, 0x10e }, + { 0x110, 0x110 }, + { 0x112, 0x112 }, + { 0x114, 0x114 }, + { 0x116, 0x116 }, + { 0x118, 0x118 }, + { 0x11a, 0x11a }, + { 0x11c, 0x11c }, + { 0x11e, 0x11e }, + { 0x120, 0x120 }, + { 0x122, 0x122 }, + { 0x124, 0x124 }, + { 0x126, 0x126 }, + { 0x128, 0x128 }, + { 0x12a, 0x12a }, + { 0x12c, 0x12c }, + { 0x12e, 0x12e }, + { 0x130, 0x130 }, + { 0x132, 0x132 }, + { 0x134, 0x134 }, + { 0x136, 0x136 }, + { 0x139, 0x139 }, + { 0x13b, 0x13b }, + { 0x13d, 0x13d }, + { 0x13f, 0x13f }, + { 0x141, 0x141 }, + { 0x143, 0x143 }, + { 0x145, 0x145 }, + { 0x147, 0x147 }, + { 0x14a, 0x14a }, + { 0x14c, 0x14c }, + { 0x14e, 0x14e }, + { 0x150, 0x150 }, + { 0x152, 0x152 }, + { 0x154, 0x154 }, + { 0x156, 0x156 }, + { 0x158, 0x158 }, + { 0x15a, 0x15a }, + { 0x15c, 0x15c }, + { 0x15e, 0x15e }, + { 0x160, 0x160 }, + { 0x162, 0x162 }, + { 0x164, 0x164 }, + { 0x166, 0x166 }, + { 0x168, 0x168 }, + { 0x16a, 0x16a }, + { 0x16c, 0x16c }, + { 0x16e, 0x16e }, + { 0x170, 0x170 }, + { 0x172, 0x172 }, + { 0x174, 0x174 }, + { 0x176, 0x176 }, + { 0x178, 0x179 }, + { 0x17b, 0x17b }, + { 0x17d, 0x17d }, + { 0x181, 0x182 }, + { 0x184, 0x184 }, + { 0x186, 0x187 }, + { 0x189, 0x18b }, + { 0x18e, 0x191 }, + { 0x193, 0x194 }, + { 0x196, 0x198 }, + { 0x19c, 0x19d }, + { 0x19f, 0x1a0 }, + { 0x1a2, 0x1a2 }, + { 0x1a4, 0x1a4 }, + { 0x1a6, 0x1a7 }, + { 0x1a9, 0x1a9 }, + { 0x1ac, 0x1ac }, + { 0x1ae, 0x1af }, + { 0x1b1, 0x1b3 }, + { 0x1b5, 0x1b5 }, + { 0x1b7, 0x1b8 }, + { 0x1bc, 0x1bc }, + { 0x1c4, 0x1c4 }, + { 0x1c7, 0x1c7 }, + { 0x1ca, 0x1ca }, + { 0x1cd, 0x1cd }, + { 0x1cf, 0x1cf }, + { 0x1d1, 0x1d1 }, + { 0x1d3, 0x1d3 }, + { 0x1d5, 0x1d5 }, + { 0x1d7, 0x1d7 }, + { 0x1d9, 0x1d9 }, + { 0x1db, 0x1db }, + { 0x1de, 0x1de }, + { 0x1e0, 0x1e0 }, + { 0x1e2, 0x1e2 }, + { 0x1e4, 0x1e4 }, + { 0x1e6, 0x1e6 }, + { 0x1e8, 0x1e8 }, + { 0x1ea, 0x1ea }, + { 0x1ec, 0x1ec }, + { 0x1ee, 0x1ee }, + { 0x1f1, 0x1f1 }, + { 0x1f4, 0x1f4 }, + { 0x1f6, 0x1f8 }, + { 0x1fa, 0x1fa }, + { 0x1fc, 0x1fc }, + { 0x1fe, 0x1fe }, + { 0x200, 0x200 }, + { 0x202, 0x202 }, + { 0x204, 0x204 }, + { 0x206, 0x206 }, + { 0x208, 0x208 }, + { 0x20a, 0x20a }, + { 0x20c, 0x20c }, + { 0x20e, 0x20e }, + { 0x210, 0x210 }, + { 0x212, 0x212 }, + { 0x214, 0x214 }, + { 0x216, 0x216 }, + { 0x218, 0x218 }, + { 0x21a, 0x21a }, + { 0x21c, 0x21c }, + { 0x21e, 0x21e }, + { 0x220, 0x220 }, + { 0x222, 0x222 }, + { 0x224, 0x224 }, + { 0x226, 0x226 }, + { 0x228, 0x228 }, + { 0x22a, 0x22a }, + { 0x22c, 0x22c }, + { 0x22e, 0x22e }, + { 0x230, 0x230 }, + { 0x232, 0x232 }, + { 0x23a, 0x23b }, + { 0x23d, 0x23e }, + { 0x241, 0x241 }, + { 0x243, 0x246 }, + { 0x248, 0x248 }, + { 0x24a, 0x24a }, + { 0x24c, 0x24c }, + { 0x24e, 0x24e }, + { 0x370, 0x370 }, + { 0x372, 0x372 }, + { 0x376, 0x376 }, + { 0x37f, 0x37f }, + { 0x386, 0x386 }, + { 0x388, 0x38a }, + { 0x38c, 0x38c }, + { 0x38e, 0x38f }, + { 0x391, 0x3a1 }, + { 0x3a3, 0x3ab }, + { 0x3cf, 0x3cf }, + { 0x3d2, 0x3d4 }, + { 0x3d8, 0x3d8 }, + { 0x3da, 0x3da }, + { 0x3dc, 0x3dc }, + { 0x3de, 0x3de }, + { 0x3e0, 0x3e0 }, + { 0x3e2, 0x3e2 }, + { 0x3e4, 0x3e4 }, + { 0x3e6, 0x3e6 }, + { 0x3e8, 0x3e8 }, + { 0x3ea, 0x3ea }, + { 0x3ec, 0x3ec }, + { 0x3ee, 0x3ee }, + { 0x3f4, 0x3f4 }, + { 0x3f7, 0x3f7 }, + { 0x3f9, 0x3fa }, + { 0x3fd, 0x42f }, + { 0x460, 0x460 }, + { 0x462, 0x462 }, + { 0x464, 0x464 }, + { 0x466, 0x466 }, + { 0x468, 0x468 }, + { 0x46a, 0x46a }, + { 0x46c, 0x46c }, + { 0x46e, 0x46e }, + { 0x470, 0x470 }, + { 0x472, 0x472 }, + { 0x474, 0x474 }, + { 0x476, 0x476 }, + { 0x478, 0x478 }, + { 0x47a, 0x47a }, + { 0x47c, 0x47c }, + { 0x47e, 0x47e }, + { 0x480, 0x480 }, + { 0x48a, 0x48a }, + { 0x48c, 0x48c }, + { 0x48e, 0x48e }, + { 0x490, 0x490 }, + { 0x492, 0x492 }, + { 0x494, 0x494 }, + { 0x496, 0x496 }, + { 0x498, 0x498 }, + { 0x49a, 0x49a }, + { 0x49c, 0x49c }, + { 0x49e, 0x49e }, + { 0x4a0, 0x4a0 }, + { 0x4a2, 0x4a2 }, + { 0x4a4, 0x4a4 }, + { 0x4a6, 0x4a6 }, + { 0x4a8, 0x4a8 }, + { 0x4aa, 0x4aa }, + { 0x4ac, 0x4ac }, + { 0x4ae, 0x4ae }, + { 0x4b0, 0x4b0 }, + { 0x4b2, 0x4b2 }, + { 0x4b4, 0x4b4 }, + { 0x4b6, 0x4b6 }, + { 0x4b8, 0x4b8 }, + { 0x4ba, 0x4ba }, + { 0x4bc, 0x4bc }, + { 0x4be, 0x4be }, + { 0x4c0, 0x4c1 }, + { 0x4c3, 0x4c3 }, + { 0x4c5, 0x4c5 }, + { 0x4c7, 0x4c7 }, + { 0x4c9, 0x4c9 }, + { 0x4cb, 0x4cb }, + { 0x4cd, 0x4cd }, + { 0x4d0, 0x4d0 }, + { 0x4d2, 0x4d2 }, + { 0x4d4, 0x4d4 }, + { 0x4d6, 0x4d6 }, + { 0x4d8, 0x4d8 }, + { 0x4da, 0x4da }, + { 0x4dc, 0x4dc }, + { 0x4de, 0x4de }, + { 0x4e0, 0x4e0 }, + { 0x4e2, 0x4e2 }, + { 0x4e4, 0x4e4 }, + { 0x4e6, 0x4e6 }, + { 0x4e8, 0x4e8 }, + { 0x4ea, 0x4ea }, + { 0x4ec, 0x4ec }, + { 0x4ee, 0x4ee }, + { 0x4f0, 0x4f0 }, + { 0x4f2, 0x4f2 }, + { 0x4f4, 0x4f4 }, + { 0x4f6, 0x4f6 }, + { 0x4f8, 0x4f8 }, + { 0x4fa, 0x4fa }, + { 0x4fc, 0x4fc }, + { 0x4fe, 0x4fe }, + { 0x500, 0x500 }, + { 0x502, 0x502 }, + { 0x504, 0x504 }, + { 0x506, 0x506 }, + { 0x508, 0x508 }, + { 0x50a, 0x50a }, + { 0x50c, 0x50c }, + { 0x50e, 0x50e }, + { 0x510, 0x510 }, + { 0x512, 0x512 }, + { 0x514, 0x514 }, + { 0x516, 0x516 }, + { 0x518, 0x518 }, + { 0x51a, 0x51a }, + { 0x51c, 0x51c }, + { 0x51e, 0x51e }, + { 0x520, 0x520 }, + { 0x522, 0x522 }, + { 0x524, 0x524 }, + { 0x526, 0x526 }, + { 0x528, 0x528 }, + { 0x52a, 0x52a }, + { 0x52c, 0x52c }, + { 0x52e, 0x52e }, + { 0x531, 0x556 }, + { 0x10a0, 0x10c5 }, + { 0x10c7, 0x10c7 }, + { 0x10cd, 0x10cd }, + { 0x13a0, 0x13f5 }, + { 0x1c89, 0x1c89 }, + { 0x1c90, 0x1cba }, + { 0x1cbd, 0x1cbf }, + { 0x1e00, 0x1e00 }, + { 0x1e02, 0x1e02 }, + { 0x1e04, 0x1e04 }, + { 0x1e06, 0x1e06 }, + { 0x1e08, 0x1e08 }, + { 0x1e0a, 0x1e0a }, + { 0x1e0c, 0x1e0c }, + { 0x1e0e, 0x1e0e }, + { 0x1e10, 0x1e10 }, + { 0x1e12, 0x1e12 }, + { 0x1e14, 0x1e14 }, + { 0x1e16, 0x1e16 }, + { 0x1e18, 0x1e18 }, + { 0x1e1a, 0x1e1a }, + { 0x1e1c, 0x1e1c }, + { 0x1e1e, 0x1e1e }, + { 0x1e20, 0x1e20 }, + { 0x1e22, 0x1e22 }, + { 0x1e24, 0x1e24 }, + { 0x1e26, 0x1e26 }, + { 0x1e28, 0x1e28 }, + { 0x1e2a, 0x1e2a }, + { 0x1e2c, 0x1e2c }, + { 0x1e2e, 0x1e2e }, + { 0x1e30, 0x1e30 }, + { 0x1e32, 0x1e32 }, + { 0x1e34, 0x1e34 }, + { 0x1e36, 0x1e36 }, + { 0x1e38, 0x1e38 }, + { 0x1e3a, 0x1e3a }, + { 0x1e3c, 0x1e3c }, + { 0x1e3e, 0x1e3e }, + { 0x1e40, 0x1e40 }, + { 0x1e42, 0x1e42 }, + { 0x1e44, 0x1e44 }, + { 0x1e46, 0x1e46 }, + { 0x1e48, 0x1e48 }, + { 0x1e4a, 0x1e4a }, + { 0x1e4c, 0x1e4c }, + { 0x1e4e, 0x1e4e }, + { 0x1e50, 0x1e50 }, + { 0x1e52, 0x1e52 }, + { 0x1e54, 0x1e54 }, + { 0x1e56, 0x1e56 }, + { 0x1e58, 0x1e58 }, + { 0x1e5a, 0x1e5a }, + { 0x1e5c, 0x1e5c }, + { 0x1e5e, 0x1e5e }, + { 0x1e60, 0x1e60 }, + { 0x1e62, 0x1e62 }, + { 0x1e64, 0x1e64 }, + { 0x1e66, 0x1e66 }, + { 0x1e68, 0x1e68 }, + { 0x1e6a, 0x1e6a }, + { 0x1e6c, 0x1e6c }, + { 0x1e6e, 0x1e6e }, + { 0x1e70, 0x1e70 }, + { 0x1e72, 0x1e72 }, + { 0x1e74, 0x1e74 }, + { 0x1e76, 0x1e76 }, + { 0x1e78, 0x1e78 }, + { 0x1e7a, 0x1e7a }, + { 0x1e7c, 0x1e7c }, + { 0x1e7e, 0x1e7e }, + { 0x1e80, 0x1e80 }, + { 0x1e82, 0x1e82 }, + { 0x1e84, 0x1e84 }, + { 0x1e86, 0x1e86 }, + { 0x1e88, 0x1e88 }, + { 0x1e8a, 0x1e8a }, + { 0x1e8c, 0x1e8c }, + { 0x1e8e, 0x1e8e }, + { 0x1e90, 0x1e90 }, + { 0x1e92, 0x1e92 }, + { 0x1e94, 0x1e94 }, + { 0x1e9e, 0x1e9e }, + { 0x1ea0, 0x1ea0 }, + { 0x1ea2, 0x1ea2 }, + { 0x1ea4, 0x1ea4 }, + { 0x1ea6, 0x1ea6 }, + { 0x1ea8, 0x1ea8 }, + { 0x1eaa, 0x1eaa }, + { 0x1eac, 0x1eac }, + { 0x1eae, 0x1eae }, + { 0x1eb0, 0x1eb0 }, + { 0x1eb2, 0x1eb2 }, + { 0x1eb4, 0x1eb4 }, + { 0x1eb6, 0x1eb6 }, + { 0x1eb8, 0x1eb8 }, + { 0x1eba, 0x1eba }, + { 0x1ebc, 0x1ebc }, + { 0x1ebe, 0x1ebe }, + { 0x1ec0, 0x1ec0 }, + { 0x1ec2, 0x1ec2 }, + { 0x1ec4, 0x1ec4 }, + { 0x1ec6, 0x1ec6 }, + { 0x1ec8, 0x1ec8 }, + { 0x1eca, 0x1eca }, + { 0x1ecc, 0x1ecc }, + { 0x1ece, 0x1ece }, + { 0x1ed0, 0x1ed0 }, + { 0x1ed2, 0x1ed2 }, + { 0x1ed4, 0x1ed4 }, + { 0x1ed6, 0x1ed6 }, + { 0x1ed8, 0x1ed8 }, + { 0x1eda, 0x1eda }, + { 0x1edc, 0x1edc }, + { 0x1ede, 0x1ede }, + { 0x1ee0, 0x1ee0 }, + { 0x1ee2, 0x1ee2 }, + { 0x1ee4, 0x1ee4 }, + { 0x1ee6, 0x1ee6 }, + { 0x1ee8, 0x1ee8 }, + { 0x1eea, 0x1eea }, + { 0x1eec, 0x1eec }, + { 0x1eee, 0x1eee }, + { 0x1ef0, 0x1ef0 }, + { 0x1ef2, 0x1ef2 }, + { 0x1ef4, 0x1ef4 }, + { 0x1ef6, 0x1ef6 }, + { 0x1ef8, 0x1ef8 }, + { 0x1efa, 0x1efa }, + { 0x1efc, 0x1efc }, + { 0x1efe, 0x1efe }, + { 0x1f08, 0x1f0f }, + { 0x1f18, 0x1f1d }, + { 0x1f28, 0x1f2f }, + { 0x1f38, 0x1f3f }, + { 0x1f48, 0x1f4d }, + { 0x1f59, 0x1f59 }, + { 0x1f5b, 0x1f5b }, + { 0x1f5d, 0x1f5d }, + { 0x1f5f, 0x1f5f }, + { 0x1f68, 0x1f6f }, + { 0x1fb8, 0x1fbb }, + { 0x1fc8, 0x1fcb }, + { 0x1fd8, 0x1fdb }, + { 0x1fe8, 0x1fec }, + { 0x1ff8, 0x1ffb }, + { 0x2102, 0x2102 }, + { 0x2107, 0x2107 }, + { 0x210b, 0x210d }, + { 0x2110, 0x2112 }, + { 0x2115, 0x2115 }, + { 0x2119, 0x211d }, + { 0x2124, 0x2124 }, + { 0x2126, 0x2126 }, + { 0x2128, 0x2128 }, + { 0x212a, 0x212d }, + { 0x2130, 0x2133 }, + { 0x213e, 0x213f }, + { 0x2145, 0x2145 }, + { 0x2160, 0x216f }, + { 0x2183, 0x2183 }, + { 0x24b6, 0x24cf }, + { 0x2c00, 0x2c2f }, + { 0x2c60, 0x2c60 }, + { 0x2c62, 0x2c64 }, + { 0x2c67, 0x2c67 }, + { 0x2c69, 0x2c69 }, + { 0x2c6b, 0x2c6b }, + { 0x2c6d, 0x2c70 }, + { 0x2c72, 0x2c72 }, + { 0x2c75, 0x2c75 }, + { 0x2c7e, 0x2c80 }, + { 0x2c82, 0x2c82 }, + { 0x2c84, 0x2c84 }, + { 0x2c86, 0x2c86 }, + { 0x2c88, 0x2c88 }, + { 0x2c8a, 0x2c8a }, + { 0x2c8c, 0x2c8c }, + { 0x2c8e, 0x2c8e }, + { 0x2c90, 0x2c90 }, + { 0x2c92, 0x2c92 }, + { 0x2c94, 0x2c94 }, + { 0x2c96, 0x2c96 }, + { 0x2c98, 0x2c98 }, + { 0x2c9a, 0x2c9a }, + { 0x2c9c, 0x2c9c }, + { 0x2c9e, 0x2c9e }, + { 0x2ca0, 0x2ca0 }, + { 0x2ca2, 0x2ca2 }, + { 0x2ca4, 0x2ca4 }, + { 0x2ca6, 0x2ca6 }, + { 0x2ca8, 0x2ca8 }, + { 0x2caa, 0x2caa }, + { 0x2cac, 0x2cac }, + { 0x2cae, 0x2cae }, + { 0x2cb0, 0x2cb0 }, + { 0x2cb2, 0x2cb2 }, + { 0x2cb4, 0x2cb4 }, + { 0x2cb6, 0x2cb6 }, + { 0x2cb8, 0x2cb8 }, + { 0x2cba, 0x2cba }, + { 0x2cbc, 0x2cbc }, + { 0x2cbe, 0x2cbe }, + { 0x2cc0, 0x2cc0 }, + { 0x2cc2, 0x2cc2 }, + { 0x2cc4, 0x2cc4 }, + { 0x2cc6, 0x2cc6 }, + { 0x2cc8, 0x2cc8 }, + { 0x2cca, 0x2cca }, + { 0x2ccc, 0x2ccc }, + { 0x2cce, 0x2cce }, + { 0x2cd0, 0x2cd0 }, + { 0x2cd2, 0x2cd2 }, + { 0x2cd4, 0x2cd4 }, + { 0x2cd6, 0x2cd6 }, + { 0x2cd8, 0x2cd8 }, + { 0x2cda, 0x2cda }, + { 0x2cdc, 0x2cdc }, + { 0x2cde, 0x2cde }, + { 0x2ce0, 0x2ce0 }, + { 0x2ce2, 0x2ce2 }, + { 0x2ceb, 0x2ceb }, + { 0x2ced, 0x2ced }, + { 0x2cf2, 0x2cf2 }, + { 0xa640, 0xa640 }, + { 0xa642, 0xa642 }, + { 0xa644, 0xa644 }, + { 0xa646, 0xa646 }, + { 0xa648, 0xa648 }, + { 0xa64a, 0xa64a }, + { 0xa64c, 0xa64c }, + { 0xa64e, 0xa64e }, + { 0xa650, 0xa650 }, + { 0xa652, 0xa652 }, + { 0xa654, 0xa654 }, + { 0xa656, 0xa656 }, + { 0xa658, 0xa658 }, + { 0xa65a, 0xa65a }, + { 0xa65c, 0xa65c }, + { 0xa65e, 0xa65e }, + { 0xa660, 0xa660 }, + { 0xa662, 0xa662 }, + { 0xa664, 0xa664 }, + { 0xa666, 0xa666 }, + { 0xa668, 0xa668 }, + { 0xa66a, 0xa66a }, + { 0xa66c, 0xa66c }, + { 0xa680, 0xa680 }, + { 0xa682, 0xa682 }, + { 0xa684, 0xa684 }, + { 0xa686, 0xa686 }, + { 0xa688, 0xa688 }, + { 0xa68a, 0xa68a }, + { 0xa68c, 0xa68c }, + { 0xa68e, 0xa68e }, + { 0xa690, 0xa690 }, + { 0xa692, 0xa692 }, + { 0xa694, 0xa694 }, + { 0xa696, 0xa696 }, + { 0xa698, 0xa698 }, + { 0xa69a, 0xa69a }, + { 0xa722, 0xa722 }, + { 0xa724, 0xa724 }, + { 0xa726, 0xa726 }, + { 0xa728, 0xa728 }, + { 0xa72a, 0xa72a }, + { 0xa72c, 0xa72c }, + { 0xa72e, 0xa72e }, + { 0xa732, 0xa732 }, + { 0xa734, 0xa734 }, + { 0xa736, 0xa736 }, + { 0xa738, 0xa738 }, + { 0xa73a, 0xa73a }, + { 0xa73c, 0xa73c }, + { 0xa73e, 0xa73e }, + { 0xa740, 0xa740 }, + { 0xa742, 0xa742 }, + { 0xa744, 0xa744 }, + { 0xa746, 0xa746 }, + { 0xa748, 0xa748 }, + { 0xa74a, 0xa74a }, + { 0xa74c, 0xa74c }, + { 0xa74e, 0xa74e }, + { 0xa750, 0xa750 }, + { 0xa752, 0xa752 }, + { 0xa754, 0xa754 }, + { 0xa756, 0xa756 }, + { 0xa758, 0xa758 }, + { 0xa75a, 0xa75a }, + { 0xa75c, 0xa75c }, + { 0xa75e, 0xa75e }, + { 0xa760, 0xa760 }, + { 0xa762, 0xa762 }, + { 0xa764, 0xa764 }, + { 0xa766, 0xa766 }, + { 0xa768, 0xa768 }, + { 0xa76a, 0xa76a }, + { 0xa76c, 0xa76c }, + { 0xa76e, 0xa76e }, + { 0xa779, 0xa779 }, + { 0xa77b, 0xa77b }, + { 0xa77d, 0xa77e }, + { 0xa780, 0xa780 }, + { 0xa782, 0xa782 }, + { 0xa784, 0xa784 }, + { 0xa786, 0xa786 }, + { 0xa78b, 0xa78b }, + { 0xa78d, 0xa78d }, + { 0xa790, 0xa790 }, + { 0xa792, 0xa792 }, + { 0xa796, 0xa796 }, + { 0xa798, 0xa798 }, + { 0xa79a, 0xa79a }, + { 0xa79c, 0xa79c }, + { 0xa79e, 0xa79e }, + { 0xa7a0, 0xa7a0 }, + { 0xa7a2, 0xa7a2 }, + { 0xa7a4, 0xa7a4 }, + { 0xa7a6, 0xa7a6 }, + { 0xa7a8, 0xa7a8 }, + { 0xa7aa, 0xa7ae }, + { 0xa7b0, 0xa7b4 }, + { 0xa7b6, 0xa7b6 }, + { 0xa7b8, 0xa7b8 }, + { 0xa7ba, 0xa7ba }, + { 0xa7bc, 0xa7bc }, + { 0xa7be, 0xa7be }, + { 0xa7c0, 0xa7c0 }, + { 0xa7c2, 0xa7c2 }, + { 0xa7c4, 0xa7c7 }, + { 0xa7c9, 0xa7c9 }, + { 0xa7cb, 0xa7cc }, + { 0xa7d0, 0xa7d0 }, + { 0xa7d6, 0xa7d6 }, + { 0xa7d8, 0xa7d8 }, + { 0xa7da, 0xa7da }, + { 0xa7dc, 0xa7dc }, + { 0xa7f5, 0xa7f5 }, + { 0xff21, 0xff3a }, + { 0x10400, 0x10427 }, + { 0x104b0, 0x104d3 }, + { 0x10570, 0x1057a }, + { 0x1057c, 0x1058a }, + { 0x1058c, 0x10592 }, + { 0x10594, 0x10595 }, + { 0x10c80, 0x10cb2 }, + { 0x10d50, 0x10d65 }, + { 0x118a0, 0x118bf }, + { 0x16e40, 0x16e5f }, + { 0x1d400, 0x1d419 }, + { 0x1d434, 0x1d44d }, + { 0x1d468, 0x1d481 }, + { 0x1d49c, 0x1d49c }, + { 0x1d49e, 0x1d49f }, + { 0x1d4a2, 0x1d4a2 }, + { 0x1d4a5, 0x1d4a6 }, + { 0x1d4a9, 0x1d4ac }, + { 0x1d4ae, 0x1d4b5 }, + { 0x1d4d0, 0x1d4e9 }, + { 0x1d504, 0x1d505 }, + { 0x1d507, 0x1d50a }, + { 0x1d50d, 0x1d514 }, + { 0x1d516, 0x1d51c }, + { 0x1d538, 0x1d539 }, + { 0x1d53b, 0x1d53e }, + { 0x1d540, 0x1d544 }, + { 0x1d546, 0x1d546 }, + { 0x1d54a, 0x1d550 }, + { 0x1d56c, 0x1d585 }, + { 0x1d5a0, 0x1d5b9 }, + { 0x1d5d4, 0x1d5ed }, + { 0x1d608, 0x1d621 }, + { 0x1d63c, 0x1d655 }, + { 0x1d670, 0x1d689 }, + { 0x1d6a8, 0x1d6c0 }, + { 0x1d6e2, 0x1d6fa }, + { 0x1d71c, 0x1d734 }, + { 0x1d756, 0x1d76e }, + { 0x1d790, 0x1d7a8 }, + { 0x1d7ca, 0x1d7ca }, + { 0x1e900, 0x1e921 }, + { 0x1f130, 0x1f149 }, + { 0x1f150, 0x1f169 }, + { 0x1f170, 0x1f189 }, +}; + +constexpr inline CharRange lowercase_letter[] = { + { 0x61, 0x7a }, + { 0xaa, 0xaa }, + { 0xb5, 0xb5 }, + { 0xba, 0xba }, + { 0xdf, 0xf6 }, + { 0xf8, 0xff }, + { 0x101, 0x101 }, + { 0x103, 0x103 }, + { 0x105, 0x105 }, + { 0x107, 0x107 }, + { 0x109, 0x109 }, + { 0x10b, 0x10b }, + { 0x10d, 0x10d }, + { 0x10f, 0x10f }, + { 0x111, 0x111 }, + { 0x113, 0x113 }, + { 0x115, 0x115 }, + { 0x117, 0x117 }, + { 0x119, 0x119 }, + { 0x11b, 0x11b }, + { 0x11d, 0x11d }, + { 0x11f, 0x11f }, + { 0x121, 0x121 }, + { 0x123, 0x123 }, + { 0x125, 0x125 }, + { 0x127, 0x127 }, + { 0x129, 0x129 }, + { 0x12b, 0x12b }, + { 0x12d, 0x12d }, + { 0x12f, 0x12f }, + { 0x131, 0x131 }, + { 0x133, 0x133 }, + { 0x135, 0x135 }, + { 0x137, 0x138 }, + { 0x13a, 0x13a }, + { 0x13c, 0x13c }, + { 0x13e, 0x13e }, + { 0x140, 0x140 }, + { 0x142, 0x142 }, + { 0x144, 0x144 }, + { 0x146, 0x146 }, + { 0x148, 0x149 }, + { 0x14b, 0x14b }, + { 0x14d, 0x14d }, + { 0x14f, 0x14f }, + { 0x151, 0x151 }, + { 0x153, 0x153 }, + { 0x155, 0x155 }, + { 0x157, 0x157 }, + { 0x159, 0x159 }, + { 0x15b, 0x15b }, + { 0x15d, 0x15d }, + { 0x15f, 0x15f }, + { 0x161, 0x161 }, + { 0x163, 0x163 }, + { 0x165, 0x165 }, + { 0x167, 0x167 }, + { 0x169, 0x169 }, + { 0x16b, 0x16b }, + { 0x16d, 0x16d }, + { 0x16f, 0x16f }, + { 0x171, 0x171 }, + { 0x173, 0x173 }, + { 0x175, 0x175 }, + { 0x177, 0x177 }, + { 0x17a, 0x17a }, + { 0x17c, 0x17c }, + { 0x17e, 0x180 }, + { 0x183, 0x183 }, + { 0x185, 0x185 }, + { 0x188, 0x188 }, + { 0x18c, 0x18d }, + { 0x192, 0x192 }, + { 0x195, 0x195 }, + { 0x199, 0x19b }, + { 0x19e, 0x19e }, + { 0x1a1, 0x1a1 }, + { 0x1a3, 0x1a3 }, + { 0x1a5, 0x1a5 }, + { 0x1a8, 0x1a8 }, + { 0x1aa, 0x1ab }, + { 0x1ad, 0x1ad }, + { 0x1b0, 0x1b0 }, + { 0x1b4, 0x1b4 }, + { 0x1b6, 0x1b6 }, + { 0x1b9, 0x1ba }, + { 0x1bd, 0x1bf }, + { 0x1c6, 0x1c6 }, + { 0x1c9, 0x1c9 }, + { 0x1cc, 0x1cc }, + { 0x1ce, 0x1ce }, + { 0x1d0, 0x1d0 }, + { 0x1d2, 0x1d2 }, + { 0x1d4, 0x1d4 }, + { 0x1d6, 0x1d6 }, + { 0x1d8, 0x1d8 }, + { 0x1da, 0x1da }, + { 0x1dc, 0x1dd }, + { 0x1df, 0x1df }, + { 0x1e1, 0x1e1 }, + { 0x1e3, 0x1e3 }, + { 0x1e5, 0x1e5 }, + { 0x1e7, 0x1e7 }, + { 0x1e9, 0x1e9 }, + { 0x1eb, 0x1eb }, + { 0x1ed, 0x1ed }, + { 0x1ef, 0x1f0 }, + { 0x1f3, 0x1f3 }, + { 0x1f5, 0x1f5 }, + { 0x1f9, 0x1f9 }, + { 0x1fb, 0x1fb }, + { 0x1fd, 0x1fd }, + { 0x1ff, 0x1ff }, + { 0x201, 0x201 }, + { 0x203, 0x203 }, + { 0x205, 0x205 }, + { 0x207, 0x207 }, + { 0x209, 0x209 }, + { 0x20b, 0x20b }, + { 0x20d, 0x20d }, + { 0x20f, 0x20f }, + { 0x211, 0x211 }, + { 0x213, 0x213 }, + { 0x215, 0x215 }, + { 0x217, 0x217 }, + { 0x219, 0x219 }, + { 0x21b, 0x21b }, + { 0x21d, 0x21d }, + { 0x21f, 0x21f }, + { 0x221, 0x221 }, + { 0x223, 0x223 }, + { 0x225, 0x225 }, + { 0x227, 0x227 }, + { 0x229, 0x229 }, + { 0x22b, 0x22b }, + { 0x22d, 0x22d }, + { 0x22f, 0x22f }, + { 0x231, 0x231 }, + { 0x233, 0x239 }, + { 0x23c, 0x23c }, + { 0x23f, 0x240 }, + { 0x242, 0x242 }, + { 0x247, 0x247 }, + { 0x249, 0x249 }, + { 0x24b, 0x24b }, + { 0x24d, 0x24d }, + { 0x24f, 0x293 }, + { 0x295, 0x2b8 }, + { 0x2c0, 0x2c1 }, + { 0x2e0, 0x2e4 }, + { 0x345, 0x345 }, + { 0x371, 0x371 }, + { 0x373, 0x373 }, + { 0x377, 0x377 }, + { 0x37a, 0x37d }, + { 0x390, 0x390 }, + { 0x3ac, 0x3ce }, + { 0x3d0, 0x3d1 }, + { 0x3d5, 0x3d7 }, + { 0x3d9, 0x3d9 }, + { 0x3db, 0x3db }, + { 0x3dd, 0x3dd }, + { 0x3df, 0x3df }, + { 0x3e1, 0x3e1 }, + { 0x3e3, 0x3e3 }, + { 0x3e5, 0x3e5 }, + { 0x3e7, 0x3e7 }, + { 0x3e9, 0x3e9 }, + { 0x3eb, 0x3eb }, + { 0x3ed, 0x3ed }, + { 0x3ef, 0x3f3 }, + { 0x3f5, 0x3f5 }, + { 0x3f8, 0x3f8 }, + { 0x3fb, 0x3fc }, + { 0x430, 0x45f }, + { 0x461, 0x461 }, + { 0x463, 0x463 }, + { 0x465, 0x465 }, + { 0x467, 0x467 }, + { 0x469, 0x469 }, + { 0x46b, 0x46b }, + { 0x46d, 0x46d }, + { 0x46f, 0x46f }, + { 0x471, 0x471 }, + { 0x473, 0x473 }, + { 0x475, 0x475 }, + { 0x477, 0x477 }, + { 0x479, 0x479 }, + { 0x47b, 0x47b }, + { 0x47d, 0x47d }, + { 0x47f, 0x47f }, + { 0x481, 0x481 }, + { 0x48b, 0x48b }, + { 0x48d, 0x48d }, + { 0x48f, 0x48f }, + { 0x491, 0x491 }, + { 0x493, 0x493 }, + { 0x495, 0x495 }, + { 0x497, 0x497 }, + { 0x499, 0x499 }, + { 0x49b, 0x49b }, + { 0x49d, 0x49d }, + { 0x49f, 0x49f }, + { 0x4a1, 0x4a1 }, + { 0x4a3, 0x4a3 }, + { 0x4a5, 0x4a5 }, + { 0x4a7, 0x4a7 }, + { 0x4a9, 0x4a9 }, + { 0x4ab, 0x4ab }, + { 0x4ad, 0x4ad }, + { 0x4af, 0x4af }, + { 0x4b1, 0x4b1 }, + { 0x4b3, 0x4b3 }, + { 0x4b5, 0x4b5 }, + { 0x4b7, 0x4b7 }, + { 0x4b9, 0x4b9 }, + { 0x4bb, 0x4bb }, + { 0x4bd, 0x4bd }, + { 0x4bf, 0x4bf }, + { 0x4c2, 0x4c2 }, + { 0x4c4, 0x4c4 }, + { 0x4c6, 0x4c6 }, + { 0x4c8, 0x4c8 }, + { 0x4ca, 0x4ca }, + { 0x4cc, 0x4cc }, + { 0x4ce, 0x4cf }, + { 0x4d1, 0x4d1 }, + { 0x4d3, 0x4d3 }, + { 0x4d5, 0x4d5 }, + { 0x4d7, 0x4d7 }, + { 0x4d9, 0x4d9 }, + { 0x4db, 0x4db }, + { 0x4dd, 0x4dd }, + { 0x4df, 0x4df }, + { 0x4e1, 0x4e1 }, + { 0x4e3, 0x4e3 }, + { 0x4e5, 0x4e5 }, + { 0x4e7, 0x4e7 }, + { 0x4e9, 0x4e9 }, + { 0x4eb, 0x4eb }, + { 0x4ed, 0x4ed }, + { 0x4ef, 0x4ef }, + { 0x4f1, 0x4f1 }, + { 0x4f3, 0x4f3 }, + { 0x4f5, 0x4f5 }, + { 0x4f7, 0x4f7 }, + { 0x4f9, 0x4f9 }, + { 0x4fb, 0x4fb }, + { 0x4fd, 0x4fd }, + { 0x4ff, 0x4ff }, + { 0x501, 0x501 }, + { 0x503, 0x503 }, + { 0x505, 0x505 }, + { 0x507, 0x507 }, + { 0x509, 0x509 }, + { 0x50b, 0x50b }, + { 0x50d, 0x50d }, + { 0x50f, 0x50f }, + { 0x511, 0x511 }, + { 0x513, 0x513 }, + { 0x515, 0x515 }, + { 0x517, 0x517 }, + { 0x519, 0x519 }, + { 0x51b, 0x51b }, + { 0x51d, 0x51d }, + { 0x51f, 0x51f }, + { 0x521, 0x521 }, + { 0x523, 0x523 }, + { 0x525, 0x525 }, + { 0x527, 0x527 }, + { 0x529, 0x529 }, + { 0x52b, 0x52b }, + { 0x52d, 0x52d }, + { 0x52f, 0x52f }, + { 0x560, 0x588 }, + { 0x10d0, 0x10fa }, + { 0x10fc, 0x10ff }, + { 0x13f8, 0x13fd }, + { 0x1c80, 0x1c88 }, + { 0x1c8a, 0x1c8a }, + { 0x1d00, 0x1dbf }, + { 0x1e01, 0x1e01 }, + { 0x1e03, 0x1e03 }, + { 0x1e05, 0x1e05 }, + { 0x1e07, 0x1e07 }, + { 0x1e09, 0x1e09 }, + { 0x1e0b, 0x1e0b }, + { 0x1e0d, 0x1e0d }, + { 0x1e0f, 0x1e0f }, + { 0x1e11, 0x1e11 }, + { 0x1e13, 0x1e13 }, + { 0x1e15, 0x1e15 }, + { 0x1e17, 0x1e17 }, + { 0x1e19, 0x1e19 }, + { 0x1e1b, 0x1e1b }, + { 0x1e1d, 0x1e1d }, + { 0x1e1f, 0x1e1f }, + { 0x1e21, 0x1e21 }, + { 0x1e23, 0x1e23 }, + { 0x1e25, 0x1e25 }, + { 0x1e27, 0x1e27 }, + { 0x1e29, 0x1e29 }, + { 0x1e2b, 0x1e2b }, + { 0x1e2d, 0x1e2d }, + { 0x1e2f, 0x1e2f }, + { 0x1e31, 0x1e31 }, + { 0x1e33, 0x1e33 }, + { 0x1e35, 0x1e35 }, + { 0x1e37, 0x1e37 }, + { 0x1e39, 0x1e39 }, + { 0x1e3b, 0x1e3b }, + { 0x1e3d, 0x1e3d }, + { 0x1e3f, 0x1e3f }, + { 0x1e41, 0x1e41 }, + { 0x1e43, 0x1e43 }, + { 0x1e45, 0x1e45 }, + { 0x1e47, 0x1e47 }, + { 0x1e49, 0x1e49 }, + { 0x1e4b, 0x1e4b }, + { 0x1e4d, 0x1e4d }, + { 0x1e4f, 0x1e4f }, + { 0x1e51, 0x1e51 }, + { 0x1e53, 0x1e53 }, + { 0x1e55, 0x1e55 }, + { 0x1e57, 0x1e57 }, + { 0x1e59, 0x1e59 }, + { 0x1e5b, 0x1e5b }, + { 0x1e5d, 0x1e5d }, + { 0x1e5f, 0x1e5f }, + { 0x1e61, 0x1e61 }, + { 0x1e63, 0x1e63 }, + { 0x1e65, 0x1e65 }, + { 0x1e67, 0x1e67 }, + { 0x1e69, 0x1e69 }, + { 0x1e6b, 0x1e6b }, + { 0x1e6d, 0x1e6d }, + { 0x1e6f, 0x1e6f }, + { 0x1e71, 0x1e71 }, + { 0x1e73, 0x1e73 }, + { 0x1e75, 0x1e75 }, + { 0x1e77, 0x1e77 }, + { 0x1e79, 0x1e79 }, + { 0x1e7b, 0x1e7b }, + { 0x1e7d, 0x1e7d }, + { 0x1e7f, 0x1e7f }, + { 0x1e81, 0x1e81 }, + { 0x1e83, 0x1e83 }, + { 0x1e85, 0x1e85 }, + { 0x1e87, 0x1e87 }, + { 0x1e89, 0x1e89 }, + { 0x1e8b, 0x1e8b }, + { 0x1e8d, 0x1e8d }, + { 0x1e8f, 0x1e8f }, + { 0x1e91, 0x1e91 }, + { 0x1e93, 0x1e93 }, + { 0x1e95, 0x1e9d }, + { 0x1e9f, 0x1e9f }, + { 0x1ea1, 0x1ea1 }, + { 0x1ea3, 0x1ea3 }, + { 0x1ea5, 0x1ea5 }, + { 0x1ea7, 0x1ea7 }, + { 0x1ea9, 0x1ea9 }, + { 0x1eab, 0x1eab }, + { 0x1ead, 0x1ead }, + { 0x1eaf, 0x1eaf }, + { 0x1eb1, 0x1eb1 }, + { 0x1eb3, 0x1eb3 }, + { 0x1eb5, 0x1eb5 }, + { 0x1eb7, 0x1eb7 }, + { 0x1eb9, 0x1eb9 }, + { 0x1ebb, 0x1ebb }, + { 0x1ebd, 0x1ebd }, + { 0x1ebf, 0x1ebf }, + { 0x1ec1, 0x1ec1 }, + { 0x1ec3, 0x1ec3 }, + { 0x1ec5, 0x1ec5 }, + { 0x1ec7, 0x1ec7 }, + { 0x1ec9, 0x1ec9 }, + { 0x1ecb, 0x1ecb }, + { 0x1ecd, 0x1ecd }, + { 0x1ecf, 0x1ecf }, + { 0x1ed1, 0x1ed1 }, + { 0x1ed3, 0x1ed3 }, + { 0x1ed5, 0x1ed5 }, + { 0x1ed7, 0x1ed7 }, + { 0x1ed9, 0x1ed9 }, + { 0x1edb, 0x1edb }, + { 0x1edd, 0x1edd }, + { 0x1edf, 0x1edf }, + { 0x1ee1, 0x1ee1 }, + { 0x1ee3, 0x1ee3 }, + { 0x1ee5, 0x1ee5 }, + { 0x1ee7, 0x1ee7 }, + { 0x1ee9, 0x1ee9 }, + { 0x1eeb, 0x1eeb }, + { 0x1eed, 0x1eed }, + { 0x1eef, 0x1eef }, + { 0x1ef1, 0x1ef1 }, + { 0x1ef3, 0x1ef3 }, + { 0x1ef5, 0x1ef5 }, + { 0x1ef7, 0x1ef7 }, + { 0x1ef9, 0x1ef9 }, + { 0x1efb, 0x1efb }, + { 0x1efd, 0x1efd }, + { 0x1eff, 0x1f07 }, + { 0x1f10, 0x1f15 }, + { 0x1f20, 0x1f27 }, + { 0x1f30, 0x1f37 }, + { 0x1f40, 0x1f45 }, + { 0x1f50, 0x1f57 }, + { 0x1f60, 0x1f67 }, + { 0x1f70, 0x1f7d }, + { 0x1f80, 0x1f87 }, + { 0x1f90, 0x1f97 }, + { 0x1fa0, 0x1fa7 }, + { 0x1fb0, 0x1fb4 }, + { 0x1fb6, 0x1fb7 }, + { 0x1fbe, 0x1fbe }, + { 0x1fc2, 0x1fc4 }, + { 0x1fc6, 0x1fc7 }, + { 0x1fd0, 0x1fd3 }, + { 0x1fd6, 0x1fd7 }, + { 0x1fe0, 0x1fe7 }, + { 0x1ff2, 0x1ff4 }, + { 0x1ff6, 0x1ff7 }, + { 0x2071, 0x2071 }, + { 0x207f, 0x207f }, + { 0x2090, 0x209c }, + { 0x210a, 0x210a }, + { 0x210e, 0x210f }, + { 0x2113, 0x2113 }, + { 0x212f, 0x212f }, + { 0x2134, 0x2134 }, + { 0x2139, 0x2139 }, + { 0x213c, 0x213d }, + { 0x2146, 0x2149 }, + { 0x214e, 0x214e }, + { 0x2170, 0x217f }, + { 0x2184, 0x2184 }, + { 0x24d0, 0x24e9 }, + { 0x2c30, 0x2c5f }, + { 0x2c61, 0x2c61 }, + { 0x2c65, 0x2c66 }, + { 0x2c68, 0x2c68 }, + { 0x2c6a, 0x2c6a }, + { 0x2c6c, 0x2c6c }, + { 0x2c71, 0x2c71 }, + { 0x2c73, 0x2c74 }, + { 0x2c76, 0x2c7d }, + { 0x2c81, 0x2c81 }, + { 0x2c83, 0x2c83 }, + { 0x2c85, 0x2c85 }, + { 0x2c87, 0x2c87 }, + { 0x2c89, 0x2c89 }, + { 0x2c8b, 0x2c8b }, + { 0x2c8d, 0x2c8d }, + { 0x2c8f, 0x2c8f }, + { 0x2c91, 0x2c91 }, + { 0x2c93, 0x2c93 }, + { 0x2c95, 0x2c95 }, + { 0x2c97, 0x2c97 }, + { 0x2c99, 0x2c99 }, + { 0x2c9b, 0x2c9b }, + { 0x2c9d, 0x2c9d }, + { 0x2c9f, 0x2c9f }, + { 0x2ca1, 0x2ca1 }, + { 0x2ca3, 0x2ca3 }, + { 0x2ca5, 0x2ca5 }, + { 0x2ca7, 0x2ca7 }, + { 0x2ca9, 0x2ca9 }, + { 0x2cab, 0x2cab }, + { 0x2cad, 0x2cad }, + { 0x2caf, 0x2caf }, + { 0x2cb1, 0x2cb1 }, + { 0x2cb3, 0x2cb3 }, + { 0x2cb5, 0x2cb5 }, + { 0x2cb7, 0x2cb7 }, + { 0x2cb9, 0x2cb9 }, + { 0x2cbb, 0x2cbb }, + { 0x2cbd, 0x2cbd }, + { 0x2cbf, 0x2cbf }, + { 0x2cc1, 0x2cc1 }, + { 0x2cc3, 0x2cc3 }, + { 0x2cc5, 0x2cc5 }, + { 0x2cc7, 0x2cc7 }, + { 0x2cc9, 0x2cc9 }, + { 0x2ccb, 0x2ccb }, + { 0x2ccd, 0x2ccd }, + { 0x2ccf, 0x2ccf }, + { 0x2cd1, 0x2cd1 }, + { 0x2cd3, 0x2cd3 }, + { 0x2cd5, 0x2cd5 }, + { 0x2cd7, 0x2cd7 }, + { 0x2cd9, 0x2cd9 }, + { 0x2cdb, 0x2cdb }, + { 0x2cdd, 0x2cdd }, + { 0x2cdf, 0x2cdf }, + { 0x2ce1, 0x2ce1 }, + { 0x2ce3, 0x2ce4 }, + { 0x2cec, 0x2cec }, + { 0x2cee, 0x2cee }, + { 0x2cf3, 0x2cf3 }, + { 0x2d00, 0x2d25 }, + { 0x2d27, 0x2d27 }, + { 0x2d2d, 0x2d2d }, + { 0xa641, 0xa641 }, + { 0xa643, 0xa643 }, + { 0xa645, 0xa645 }, + { 0xa647, 0xa647 }, + { 0xa649, 0xa649 }, + { 0xa64b, 0xa64b }, + { 0xa64d, 0xa64d }, + { 0xa64f, 0xa64f }, + { 0xa651, 0xa651 }, + { 0xa653, 0xa653 }, + { 0xa655, 0xa655 }, + { 0xa657, 0xa657 }, + { 0xa659, 0xa659 }, + { 0xa65b, 0xa65b }, + { 0xa65d, 0xa65d }, + { 0xa65f, 0xa65f }, + { 0xa661, 0xa661 }, + { 0xa663, 0xa663 }, + { 0xa665, 0xa665 }, + { 0xa667, 0xa667 }, + { 0xa669, 0xa669 }, + { 0xa66b, 0xa66b }, + { 0xa66d, 0xa66d }, + { 0xa681, 0xa681 }, + { 0xa683, 0xa683 }, + { 0xa685, 0xa685 }, + { 0xa687, 0xa687 }, + { 0xa689, 0xa689 }, + { 0xa68b, 0xa68b }, + { 0xa68d, 0xa68d }, + { 0xa68f, 0xa68f }, + { 0xa691, 0xa691 }, + { 0xa693, 0xa693 }, + { 0xa695, 0xa695 }, + { 0xa697, 0xa697 }, + { 0xa699, 0xa699 }, + { 0xa69b, 0xa69d }, + { 0xa723, 0xa723 }, + { 0xa725, 0xa725 }, + { 0xa727, 0xa727 }, + { 0xa729, 0xa729 }, + { 0xa72b, 0xa72b }, + { 0xa72d, 0xa72d }, + { 0xa72f, 0xa731 }, + { 0xa733, 0xa733 }, + { 0xa735, 0xa735 }, + { 0xa737, 0xa737 }, + { 0xa739, 0xa739 }, + { 0xa73b, 0xa73b }, + { 0xa73d, 0xa73d }, + { 0xa73f, 0xa73f }, + { 0xa741, 0xa741 }, + { 0xa743, 0xa743 }, + { 0xa745, 0xa745 }, + { 0xa747, 0xa747 }, + { 0xa749, 0xa749 }, + { 0xa74b, 0xa74b }, + { 0xa74d, 0xa74d }, + { 0xa74f, 0xa74f }, + { 0xa751, 0xa751 }, + { 0xa753, 0xa753 }, + { 0xa755, 0xa755 }, + { 0xa757, 0xa757 }, + { 0xa759, 0xa759 }, + { 0xa75b, 0xa75b }, + { 0xa75d, 0xa75d }, + { 0xa75f, 0xa75f }, + { 0xa761, 0xa761 }, + { 0xa763, 0xa763 }, + { 0xa765, 0xa765 }, + { 0xa767, 0xa767 }, + { 0xa769, 0xa769 }, + { 0xa76b, 0xa76b }, + { 0xa76d, 0xa76d }, + { 0xa76f, 0xa778 }, + { 0xa77a, 0xa77a }, + { 0xa77c, 0xa77c }, + { 0xa77f, 0xa77f }, + { 0xa781, 0xa781 }, + { 0xa783, 0xa783 }, + { 0xa785, 0xa785 }, + { 0xa787, 0xa787 }, + { 0xa78c, 0xa78c }, + { 0xa78e, 0xa78e }, + { 0xa791, 0xa791 }, + { 0xa793, 0xa795 }, + { 0xa797, 0xa797 }, + { 0xa799, 0xa799 }, + { 0xa79b, 0xa79b }, + { 0xa79d, 0xa79d }, + { 0xa79f, 0xa79f }, + { 0xa7a1, 0xa7a1 }, + { 0xa7a3, 0xa7a3 }, + { 0xa7a5, 0xa7a5 }, + { 0xa7a7, 0xa7a7 }, + { 0xa7a9, 0xa7a9 }, + { 0xa7af, 0xa7af }, + { 0xa7b5, 0xa7b5 }, + { 0xa7b7, 0xa7b7 }, + { 0xa7b9, 0xa7b9 }, + { 0xa7bb, 0xa7bb }, + { 0xa7bd, 0xa7bd }, + { 0xa7bf, 0xa7bf }, + { 0xa7c1, 0xa7c1 }, + { 0xa7c3, 0xa7c3 }, + { 0xa7c8, 0xa7c8 }, + { 0xa7ca, 0xa7ca }, + { 0xa7cd, 0xa7cd }, + { 0xa7d1, 0xa7d1 }, + { 0xa7d3, 0xa7d3 }, + { 0xa7d5, 0xa7d5 }, + { 0xa7d7, 0xa7d7 }, + { 0xa7d9, 0xa7d9 }, + { 0xa7db, 0xa7db }, + { 0xa7f2, 0xa7f4 }, + { 0xa7f6, 0xa7f6 }, + { 0xa7f8, 0xa7fa }, + { 0xab30, 0xab5a }, + { 0xab5c, 0xab69 }, + { 0xab70, 0xabbf }, + { 0xfb00, 0xfb06 }, + { 0xfb13, 0xfb17 }, + { 0xff41, 0xff5a }, + { 0x10428, 0x1044f }, + { 0x104d8, 0x104fb }, + { 0x10597, 0x105a1 }, + { 0x105a3, 0x105b1 }, + { 0x105b3, 0x105b9 }, + { 0x105bb, 0x105bc }, + { 0x10780, 0x10780 }, + { 0x10783, 0x10785 }, + { 0x10787, 0x107b0 }, + { 0x107b2, 0x107ba }, + { 0x10cc0, 0x10cf2 }, + { 0x10d70, 0x10d85 }, + { 0x118c0, 0x118df }, + { 0x16e60, 0x16e7f }, + { 0x1d41a, 0x1d433 }, + { 0x1d44e, 0x1d454 }, + { 0x1d456, 0x1d467 }, + { 0x1d482, 0x1d49b }, + { 0x1d4b6, 0x1d4b9 }, + { 0x1d4bb, 0x1d4bb }, + { 0x1d4bd, 0x1d4c3 }, + { 0x1d4c5, 0x1d4cf }, + { 0x1d4ea, 0x1d503 }, + { 0x1d51e, 0x1d537 }, + { 0x1d552, 0x1d56b }, + { 0x1d586, 0x1d59f }, + { 0x1d5ba, 0x1d5d3 }, + { 0x1d5ee, 0x1d607 }, + { 0x1d622, 0x1d63b }, + { 0x1d656, 0x1d66f }, + { 0x1d68a, 0x1d6a5 }, + { 0x1d6c2, 0x1d6da }, + { 0x1d6dc, 0x1d6e1 }, + { 0x1d6fc, 0x1d714 }, + { 0x1d716, 0x1d71b }, + { 0x1d736, 0x1d74e }, + { 0x1d750, 0x1d755 }, + { 0x1d770, 0x1d788 }, + { 0x1d78a, 0x1d78f }, + { 0x1d7aa, 0x1d7c2 }, + { 0x1d7c4, 0x1d7c9 }, + { 0x1d7cb, 0x1d7cb }, + { 0x1df00, 0x1df09 }, + { 0x1df0b, 0x1df1e }, + { 0x1df25, 0x1df2a }, + { 0x1e030, 0x1e06d }, + { 0x1e922, 0x1e943 }, +}; + +constexpr inline CharRange unicode_letter[] = { + { 0x41, 0x5a }, + { 0x61, 0x7a }, + { 0xaa, 0xaa }, + { 0xb5, 0xb5 }, + { 0xba, 0xba }, + { 0xc0, 0xd6 }, + { 0xd8, 0xf6 }, + { 0xf8, 0x2c1 }, + { 0x2c6, 0x2d1 }, + { 0x2e0, 0x2e4 }, + { 0x2ec, 0x2ec }, + { 0x2ee, 0x2ee }, + { 0x345, 0x345 }, + { 0x363, 0x374 }, + { 0x376, 0x377 }, + { 0x37a, 0x37d }, + { 0x37f, 0x37f }, + { 0x386, 0x386 }, + { 0x388, 0x38a }, + { 0x38c, 0x38c }, + { 0x38e, 0x3a1 }, + { 0x3a3, 0x3f5 }, + { 0x3f7, 0x481 }, + { 0x48a, 0x52f }, + { 0x531, 0x556 }, + { 0x559, 0x559 }, + { 0x560, 0x588 }, + { 0x5b0, 0x5bd }, + { 0x5bf, 0x5bf }, + { 0x5c1, 0x5c2 }, + { 0x5c4, 0x5c5 }, + { 0x5c7, 0x5c7 }, + { 0x5d0, 0x5ea }, + { 0x5ef, 0x5f2 }, + { 0x610, 0x61a }, + { 0x620, 0x657 }, + { 0x659, 0x65f }, + { 0x66e, 0x6d3 }, + { 0x6d5, 0x6dc }, + { 0x6e1, 0x6e8 }, + { 0x6ed, 0x6ef }, + { 0x6fa, 0x6fc }, + { 0x6ff, 0x6ff }, + { 0x710, 0x73f }, + { 0x74d, 0x7b1 }, + { 0x7ca, 0x7ea }, + { 0x7f4, 0x7f5 }, + { 0x7fa, 0x7fa }, + { 0x800, 0x817 }, + { 0x81a, 0x82c }, + { 0x840, 0x858 }, + { 0x860, 0x86a }, + { 0x870, 0x887 }, + { 0x889, 0x88e }, + { 0x897, 0x897 }, + { 0x8a0, 0x8c9 }, + { 0x8d4, 0x8df }, + { 0x8e3, 0x8e9 }, + { 0x8f0, 0x93b }, + { 0x93d, 0x94c }, + { 0x94e, 0x950 }, + { 0x955, 0x963 }, + { 0x971, 0x983 }, + { 0x985, 0x98c }, + { 0x98f, 0x990 }, + { 0x993, 0x9a8 }, + { 0x9aa, 0x9b0 }, + { 0x9b2, 0x9b2 }, + { 0x9b6, 0x9b9 }, + { 0x9bd, 0x9c4 }, + { 0x9c7, 0x9c8 }, + { 0x9cb, 0x9cc }, + { 0x9ce, 0x9ce }, + { 0x9d7, 0x9d7 }, + { 0x9dc, 0x9dd }, + { 0x9df, 0x9e3 }, + { 0x9f0, 0x9f1 }, + { 0x9fc, 0x9fc }, + { 0xa01, 0xa03 }, + { 0xa05, 0xa0a }, + { 0xa0f, 0xa10 }, + { 0xa13, 0xa28 }, + { 0xa2a, 0xa30 }, + { 0xa32, 0xa33 }, + { 0xa35, 0xa36 }, + { 0xa38, 0xa39 }, + { 0xa3e, 0xa42 }, + { 0xa47, 0xa48 }, + { 0xa4b, 0xa4c }, + { 0xa51, 0xa51 }, + { 0xa59, 0xa5c }, + { 0xa5e, 0xa5e }, + { 0xa70, 0xa75 }, + { 0xa81, 0xa83 }, + { 0xa85, 0xa8d }, + { 0xa8f, 0xa91 }, + { 0xa93, 0xaa8 }, + { 0xaaa, 0xab0 }, + { 0xab2, 0xab3 }, + { 0xab5, 0xab9 }, + { 0xabd, 0xac5 }, + { 0xac7, 0xac9 }, + { 0xacb, 0xacc }, + { 0xad0, 0xad0 }, + { 0xae0, 0xae3 }, + { 0xaf9, 0xafc }, + { 0xb01, 0xb03 }, + { 0xb05, 0xb0c }, + { 0xb0f, 0xb10 }, + { 0xb13, 0xb28 }, + { 0xb2a, 0xb30 }, + { 0xb32, 0xb33 }, + { 0xb35, 0xb39 }, + { 0xb3d, 0xb44 }, + { 0xb47, 0xb48 }, + { 0xb4b, 0xb4c }, + { 0xb56, 0xb57 }, + { 0xb5c, 0xb5d }, + { 0xb5f, 0xb63 }, + { 0xb71, 0xb71 }, + { 0xb82, 0xb83 }, + { 0xb85, 0xb8a }, + { 0xb8e, 0xb90 }, + { 0xb92, 0xb95 }, + { 0xb99, 0xb9a }, + { 0xb9c, 0xb9c }, + { 0xb9e, 0xb9f }, + { 0xba3, 0xba4 }, + { 0xba8, 0xbaa }, + { 0xbae, 0xbb9 }, + { 0xbbe, 0xbc2 }, + { 0xbc6, 0xbc8 }, + { 0xbca, 0xbcc }, + { 0xbd0, 0xbd0 }, + { 0xbd7, 0xbd7 }, + { 0xc00, 0xc0c }, + { 0xc0e, 0xc10 }, + { 0xc12, 0xc28 }, + { 0xc2a, 0xc39 }, + { 0xc3d, 0xc44 }, + { 0xc46, 0xc48 }, + { 0xc4a, 0xc4c }, + { 0xc55, 0xc56 }, + { 0xc58, 0xc5a }, + { 0xc5d, 0xc5d }, + { 0xc60, 0xc63 }, + { 0xc80, 0xc83 }, + { 0xc85, 0xc8c }, + { 0xc8e, 0xc90 }, + { 0xc92, 0xca8 }, + { 0xcaa, 0xcb3 }, + { 0xcb5, 0xcb9 }, + { 0xcbd, 0xcc4 }, + { 0xcc6, 0xcc8 }, + { 0xcca, 0xccc }, + { 0xcd5, 0xcd6 }, + { 0xcdd, 0xcde }, + { 0xce0, 0xce3 }, + { 0xcf1, 0xcf3 }, + { 0xd00, 0xd0c }, + { 0xd0e, 0xd10 }, + { 0xd12, 0xd3a }, + { 0xd3d, 0xd44 }, + { 0xd46, 0xd48 }, + { 0xd4a, 0xd4c }, + { 0xd4e, 0xd4e }, + { 0xd54, 0xd57 }, + { 0xd5f, 0xd63 }, + { 0xd7a, 0xd7f }, + { 0xd81, 0xd83 }, + { 0xd85, 0xd96 }, + { 0xd9a, 0xdb1 }, + { 0xdb3, 0xdbb }, + { 0xdbd, 0xdbd }, + { 0xdc0, 0xdc6 }, + { 0xdcf, 0xdd4 }, + { 0xdd6, 0xdd6 }, + { 0xdd8, 0xddf }, + { 0xdf2, 0xdf3 }, + { 0xe01, 0xe3a }, + { 0xe40, 0xe46 }, + { 0xe4d, 0xe4d }, + { 0xe81, 0xe82 }, + { 0xe84, 0xe84 }, + { 0xe86, 0xe8a }, + { 0xe8c, 0xea3 }, + { 0xea5, 0xea5 }, + { 0xea7, 0xeb9 }, + { 0xebb, 0xebd }, + { 0xec0, 0xec4 }, + { 0xec6, 0xec6 }, + { 0xecd, 0xecd }, + { 0xedc, 0xedf }, + { 0xf00, 0xf00 }, + { 0xf40, 0xf47 }, + { 0xf49, 0xf6c }, + { 0xf71, 0xf83 }, + { 0xf88, 0xf97 }, + { 0xf99, 0xfbc }, + { 0x1000, 0x1036 }, + { 0x1038, 0x1038 }, + { 0x103b, 0x103f }, + { 0x1050, 0x108f }, + { 0x109a, 0x109d }, + { 0x10a0, 0x10c5 }, + { 0x10c7, 0x10c7 }, + { 0x10cd, 0x10cd }, + { 0x10d0, 0x10fa }, + { 0x10fc, 0x1248 }, + { 0x124a, 0x124d }, + { 0x1250, 0x1256 }, + { 0x1258, 0x1258 }, + { 0x125a, 0x125d }, + { 0x1260, 0x1288 }, + { 0x128a, 0x128d }, + { 0x1290, 0x12b0 }, + { 0x12b2, 0x12b5 }, + { 0x12b8, 0x12be }, + { 0x12c0, 0x12c0 }, + { 0x12c2, 0x12c5 }, + { 0x12c8, 0x12d6 }, + { 0x12d8, 0x1310 }, + { 0x1312, 0x1315 }, + { 0x1318, 0x135a }, + { 0x1380, 0x138f }, + { 0x13a0, 0x13f5 }, + { 0x13f8, 0x13fd }, + { 0x1401, 0x166c }, + { 0x166f, 0x167f }, + { 0x1681, 0x169a }, + { 0x16a0, 0x16ea }, + { 0x16ee, 0x16f8 }, + { 0x1700, 0x1713 }, + { 0x171f, 0x1733 }, + { 0x1740, 0x1753 }, + { 0x1760, 0x176c }, + { 0x176e, 0x1770 }, + { 0x1772, 0x1773 }, + { 0x1780, 0x17b3 }, + { 0x17b6, 0x17c8 }, + { 0x17d7, 0x17d7 }, + { 0x17dc, 0x17dc }, + { 0x1820, 0x1878 }, + { 0x1880, 0x18aa }, + { 0x18b0, 0x18f5 }, + { 0x1900, 0x191e }, + { 0x1920, 0x192b }, + { 0x1930, 0x1938 }, + { 0x1950, 0x196d }, + { 0x1970, 0x1974 }, + { 0x1980, 0x19ab }, + { 0x19b0, 0x19c9 }, + { 0x1a00, 0x1a1b }, + { 0x1a20, 0x1a5e }, + { 0x1a61, 0x1a74 }, + { 0x1aa7, 0x1aa7 }, + { 0x1abf, 0x1ac0 }, + { 0x1acc, 0x1ace }, + { 0x1b00, 0x1b33 }, + { 0x1b35, 0x1b43 }, + { 0x1b45, 0x1b4c }, + { 0x1b80, 0x1ba9 }, + { 0x1bac, 0x1baf }, + { 0x1bba, 0x1be5 }, + { 0x1be7, 0x1bf1 }, + { 0x1c00, 0x1c36 }, + { 0x1c4d, 0x1c4f }, + { 0x1c5a, 0x1c7d }, + { 0x1c80, 0x1c8a }, + { 0x1c90, 0x1cba }, + { 0x1cbd, 0x1cbf }, + { 0x1ce9, 0x1cec }, + { 0x1cee, 0x1cf3 }, + { 0x1cf5, 0x1cf6 }, + { 0x1cfa, 0x1cfa }, + { 0x1d00, 0x1dbf }, + { 0x1dd3, 0x1df4 }, + { 0x1e00, 0x1f15 }, + { 0x1f18, 0x1f1d }, + { 0x1f20, 0x1f45 }, + { 0x1f48, 0x1f4d }, + { 0x1f50, 0x1f57 }, + { 0x1f59, 0x1f59 }, + { 0x1f5b, 0x1f5b }, + { 0x1f5d, 0x1f5d }, + { 0x1f5f, 0x1f7d }, + { 0x1f80, 0x1fb4 }, + { 0x1fb6, 0x1fbc }, + { 0x1fbe, 0x1fbe }, + { 0x1fc2, 0x1fc4 }, + { 0x1fc6, 0x1fcc }, + { 0x1fd0, 0x1fd3 }, + { 0x1fd6, 0x1fdb }, + { 0x1fe0, 0x1fec }, + { 0x1ff2, 0x1ff4 }, + { 0x1ff6, 0x1ffc }, + { 0x2071, 0x2071 }, + { 0x207f, 0x207f }, + { 0x2090, 0x209c }, + { 0x2102, 0x2102 }, + { 0x2107, 0x2107 }, + { 0x210a, 0x2113 }, + { 0x2115, 0x2115 }, + { 0x2119, 0x211d }, + { 0x2124, 0x2124 }, + { 0x2126, 0x2126 }, + { 0x2128, 0x2128 }, + { 0x212a, 0x212d }, + { 0x212f, 0x2139 }, + { 0x213c, 0x213f }, + { 0x2145, 0x2149 }, + { 0x214e, 0x214e }, + { 0x2160, 0x2188 }, + { 0x24b6, 0x24e9 }, + { 0x2c00, 0x2ce4 }, + { 0x2ceb, 0x2cee }, + { 0x2cf2, 0x2cf3 }, + { 0x2d00, 0x2d25 }, + { 0x2d27, 0x2d27 }, + { 0x2d2d, 0x2d2d }, + { 0x2d30, 0x2d67 }, + { 0x2d6f, 0x2d6f }, + { 0x2d80, 0x2d96 }, + { 0x2da0, 0x2da6 }, + { 0x2da8, 0x2dae }, + { 0x2db0, 0x2db6 }, + { 0x2db8, 0x2dbe }, + { 0x2dc0, 0x2dc6 }, + { 0x2dc8, 0x2dce }, + { 0x2dd0, 0x2dd6 }, + { 0x2dd8, 0x2dde }, + { 0x2de0, 0x2dff }, + { 0x2e2f, 0x2e2f }, + { 0x3005, 0x3007 }, + { 0x3021, 0x3029 }, + { 0x3031, 0x3035 }, + { 0x3038, 0x303c }, + { 0x3041, 0x3096 }, + { 0x309d, 0x309f }, + { 0x30a1, 0x30fa }, + { 0x30fc, 0x30ff }, + { 0x3105, 0x312f }, + { 0x3131, 0x318e }, + { 0x31a0, 0x31bf }, + { 0x31f0, 0x31ff }, + { 0x3400, 0x4dbf }, + { 0x4e00, 0xa48c }, + { 0xa4d0, 0xa4fd }, + { 0xa500, 0xa60c }, + { 0xa610, 0xa61f }, + { 0xa62a, 0xa62b }, + { 0xa640, 0xa66e }, + { 0xa674, 0xa67b }, + { 0xa67f, 0xa6ef }, + { 0xa717, 0xa71f }, + { 0xa722, 0xa788 }, + { 0xa78b, 0xa7cd }, + { 0xa7d0, 0xa7d1 }, + { 0xa7d3, 0xa7d3 }, + { 0xa7d5, 0xa7dc }, + { 0xa7f2, 0xa805 }, + { 0xa807, 0xa827 }, + { 0xa840, 0xa873 }, + { 0xa880, 0xa8c3 }, + { 0xa8c5, 0xa8c5 }, + { 0xa8f2, 0xa8f7 }, + { 0xa8fb, 0xa8fb }, + { 0xa8fd, 0xa8ff }, + { 0xa90a, 0xa92a }, + { 0xa930, 0xa952 }, + { 0xa960, 0xa97c }, + { 0xa980, 0xa9b2 }, + { 0xa9b4, 0xa9bf }, + { 0xa9cf, 0xa9cf }, + { 0xa9e0, 0xa9ef }, + { 0xa9fa, 0xa9fe }, + { 0xaa00, 0xaa36 }, + { 0xaa40, 0xaa4d }, + { 0xaa60, 0xaa76 }, + { 0xaa7a, 0xaabe }, + { 0xaac0, 0xaac0 }, + { 0xaac2, 0xaac2 }, + { 0xaadb, 0xaadd }, + { 0xaae0, 0xaaef }, + { 0xaaf2, 0xaaf5 }, + { 0xab01, 0xab06 }, + { 0xab09, 0xab0e }, + { 0xab11, 0xab16 }, + { 0xab20, 0xab26 }, + { 0xab28, 0xab2e }, + { 0xab30, 0xab5a }, + { 0xab5c, 0xab69 }, + { 0xab70, 0xabea }, + { 0xac00, 0xd7a3 }, + { 0xd7b0, 0xd7c6 }, + { 0xd7cb, 0xd7fb }, + { 0xf900, 0xfa6d }, + { 0xfa70, 0xfad9 }, + { 0xfb00, 0xfb06 }, + { 0xfb13, 0xfb17 }, + { 0xfb1d, 0xfb28 }, + { 0xfb2a, 0xfb36 }, + { 0xfb38, 0xfb3c }, + { 0xfb3e, 0xfb3e }, + { 0xfb40, 0xfb41 }, + { 0xfb43, 0xfb44 }, + { 0xfb46, 0xfbb1 }, + { 0xfbd3, 0xfd3d }, + { 0xfd50, 0xfd8f }, + { 0xfd92, 0xfdc7 }, + { 0xfdf0, 0xfdfb }, + { 0xfe70, 0xfe74 }, + { 0xfe76, 0xfefc }, + { 0xff21, 0xff3a }, + { 0xff41, 0xff5a }, + { 0xff66, 0xffbe }, + { 0xffc2, 0xffc7 }, + { 0xffca, 0xffcf }, + { 0xffd2, 0xffd7 }, + { 0xffda, 0xffdc }, + { 0x10000, 0x1000b }, + { 0x1000d, 0x10026 }, + { 0x10028, 0x1003a }, + { 0x1003c, 0x1003d }, + { 0x1003f, 0x1004d }, + { 0x10050, 0x1005d }, + { 0x10080, 0x100fa }, + { 0x10140, 0x10174 }, + { 0x10280, 0x1029c }, + { 0x102a0, 0x102d0 }, + { 0x10300, 0x1031f }, + { 0x1032d, 0x1034a }, + { 0x10350, 0x1037a }, + { 0x10380, 0x1039d }, + { 0x103a0, 0x103c3 }, + { 0x103c8, 0x103cf }, + { 0x103d1, 0x103d5 }, + { 0x10400, 0x1049d }, + { 0x104b0, 0x104d3 }, + { 0x104d8, 0x104fb }, + { 0x10500, 0x10527 }, + { 0x10530, 0x10563 }, + { 0x10570, 0x1057a }, + { 0x1057c, 0x1058a }, + { 0x1058c, 0x10592 }, + { 0x10594, 0x10595 }, + { 0x10597, 0x105a1 }, + { 0x105a3, 0x105b1 }, + { 0x105b3, 0x105b9 }, + { 0x105bb, 0x105bc }, + { 0x105c0, 0x105f3 }, + { 0x10600, 0x10736 }, + { 0x10740, 0x10755 }, + { 0x10760, 0x10767 }, + { 0x10780, 0x10785 }, + { 0x10787, 0x107b0 }, + { 0x107b2, 0x107ba }, + { 0x10800, 0x10805 }, + { 0x10808, 0x10808 }, + { 0x1080a, 0x10835 }, + { 0x10837, 0x10838 }, + { 0x1083c, 0x1083c }, + { 0x1083f, 0x10855 }, + { 0x10860, 0x10876 }, + { 0x10880, 0x1089e }, + { 0x108e0, 0x108f2 }, + { 0x108f4, 0x108f5 }, + { 0x10900, 0x10915 }, + { 0x10920, 0x10939 }, + { 0x10980, 0x109b7 }, + { 0x109be, 0x109bf }, + { 0x10a00, 0x10a03 }, + { 0x10a05, 0x10a06 }, + { 0x10a0c, 0x10a13 }, + { 0x10a15, 0x10a17 }, + { 0x10a19, 0x10a35 }, + { 0x10a60, 0x10a7c }, + { 0x10a80, 0x10a9c }, + { 0x10ac0, 0x10ac7 }, + { 0x10ac9, 0x10ae4 }, + { 0x10b00, 0x10b35 }, + { 0x10b40, 0x10b55 }, + { 0x10b60, 0x10b72 }, + { 0x10b80, 0x10b91 }, + { 0x10c00, 0x10c48 }, + { 0x10c80, 0x10cb2 }, + { 0x10cc0, 0x10cf2 }, + { 0x10d00, 0x10d27 }, + { 0x10d4a, 0x10d65 }, + { 0x10d69, 0x10d69 }, + { 0x10d6f, 0x10d85 }, + { 0x10e80, 0x10ea9 }, + { 0x10eab, 0x10eac }, + { 0x10eb0, 0x10eb1 }, + { 0x10ec2, 0x10ec4 }, + { 0x10efc, 0x10efc }, + { 0x10f00, 0x10f1c }, + { 0x10f27, 0x10f27 }, + { 0x10f30, 0x10f45 }, + { 0x10f70, 0x10f81 }, + { 0x10fb0, 0x10fc4 }, + { 0x10fe0, 0x10ff6 }, + { 0x11000, 0x11045 }, + { 0x11071, 0x11075 }, + { 0x11080, 0x110b8 }, + { 0x110c2, 0x110c2 }, + { 0x110d0, 0x110e8 }, + { 0x11100, 0x11132 }, + { 0x11144, 0x11147 }, + { 0x11150, 0x11172 }, + { 0x11176, 0x11176 }, + { 0x11180, 0x111bf }, + { 0x111c1, 0x111c4 }, + { 0x111ce, 0x111cf }, + { 0x111da, 0x111da }, + { 0x111dc, 0x111dc }, + { 0x11200, 0x11211 }, + { 0x11213, 0x11234 }, + { 0x11237, 0x11237 }, + { 0x1123e, 0x11241 }, + { 0x11280, 0x11286 }, + { 0x11288, 0x11288 }, + { 0x1128a, 0x1128d }, + { 0x1128f, 0x1129d }, + { 0x1129f, 0x112a8 }, + { 0x112b0, 0x112e8 }, + { 0x11300, 0x11303 }, + { 0x11305, 0x1130c }, + { 0x1130f, 0x11310 }, + { 0x11313, 0x11328 }, + { 0x1132a, 0x11330 }, + { 0x11332, 0x11333 }, + { 0x11335, 0x11339 }, + { 0x1133d, 0x11344 }, + { 0x11347, 0x11348 }, + { 0x1134b, 0x1134c }, + { 0x11350, 0x11350 }, + { 0x11357, 0x11357 }, + { 0x1135d, 0x11363 }, + { 0x11380, 0x11389 }, + { 0x1138b, 0x1138b }, + { 0x1138e, 0x1138e }, + { 0x11390, 0x113b5 }, + { 0x113b7, 0x113c0 }, + { 0x113c2, 0x113c2 }, + { 0x113c5, 0x113c5 }, + { 0x113c7, 0x113ca }, + { 0x113cc, 0x113cd }, + { 0x113d1, 0x113d1 }, + { 0x113d3, 0x113d3 }, + { 0x11400, 0x11441 }, + { 0x11443, 0x11445 }, + { 0x11447, 0x1144a }, + { 0x1145f, 0x11461 }, + { 0x11480, 0x114c1 }, + { 0x114c4, 0x114c5 }, + { 0x114c7, 0x114c7 }, + { 0x11580, 0x115b5 }, + { 0x115b8, 0x115be }, + { 0x115d8, 0x115dd }, + { 0x11600, 0x1163e }, + { 0x11640, 0x11640 }, + { 0x11644, 0x11644 }, + { 0x11680, 0x116b5 }, + { 0x116b8, 0x116b8 }, + { 0x11700, 0x1171a }, + { 0x1171d, 0x1172a }, + { 0x11740, 0x11746 }, + { 0x11800, 0x11838 }, + { 0x118a0, 0x118df }, + { 0x118ff, 0x11906 }, + { 0x11909, 0x11909 }, + { 0x1190c, 0x11913 }, + { 0x11915, 0x11916 }, + { 0x11918, 0x11935 }, + { 0x11937, 0x11938 }, + { 0x1193b, 0x1193c }, + { 0x1193f, 0x11942 }, + { 0x119a0, 0x119a7 }, + { 0x119aa, 0x119d7 }, + { 0x119da, 0x119df }, + { 0x119e1, 0x119e1 }, + { 0x119e3, 0x119e4 }, + { 0x11a00, 0x11a32 }, + { 0x11a35, 0x11a3e }, + { 0x11a50, 0x11a97 }, + { 0x11a9d, 0x11a9d }, + { 0x11ab0, 0x11af8 }, + { 0x11bc0, 0x11be0 }, + { 0x11c00, 0x11c08 }, + { 0x11c0a, 0x11c36 }, + { 0x11c38, 0x11c3e }, + { 0x11c40, 0x11c40 }, + { 0x11c72, 0x11c8f }, + { 0x11c92, 0x11ca7 }, + { 0x11ca9, 0x11cb6 }, + { 0x11d00, 0x11d06 }, + { 0x11d08, 0x11d09 }, + { 0x11d0b, 0x11d36 }, + { 0x11d3a, 0x11d3a }, + { 0x11d3c, 0x11d3d }, + { 0x11d3f, 0x11d41 }, + { 0x11d43, 0x11d43 }, + { 0x11d46, 0x11d47 }, + { 0x11d60, 0x11d65 }, + { 0x11d67, 0x11d68 }, + { 0x11d6a, 0x11d8e }, + { 0x11d90, 0x11d91 }, + { 0x11d93, 0x11d96 }, + { 0x11d98, 0x11d98 }, + { 0x11ee0, 0x11ef6 }, + { 0x11f00, 0x11f10 }, + { 0x11f12, 0x11f3a }, + { 0x11f3e, 0x11f40 }, + { 0x11fb0, 0x11fb0 }, + { 0x12000, 0x12399 }, + { 0x12400, 0x1246e }, + { 0x12480, 0x12543 }, + { 0x12f90, 0x12ff0 }, + { 0x13000, 0x1342f }, + { 0x13441, 0x13446 }, + { 0x13460, 0x143fa }, + { 0x14400, 0x14646 }, + { 0x16100, 0x1612e }, + { 0x16800, 0x16a38 }, + { 0x16a40, 0x16a5e }, + { 0x16a70, 0x16abe }, + { 0x16ad0, 0x16aed }, + { 0x16b00, 0x16b2f }, + { 0x16b40, 0x16b43 }, + { 0x16b63, 0x16b77 }, + { 0x16b7d, 0x16b8f }, + { 0x16d40, 0x16d6c }, + { 0x16e40, 0x16e7f }, + { 0x16f00, 0x16f4a }, + { 0x16f4f, 0x16f87 }, + { 0x16f8f, 0x16f9f }, + { 0x16fe0, 0x16fe1 }, + { 0x16fe3, 0x16fe3 }, + { 0x16ff0, 0x16ff1 }, + { 0x17000, 0x187f7 }, + { 0x18800, 0x18cd5 }, + { 0x18cff, 0x18d08 }, + { 0x1aff0, 0x1aff3 }, + { 0x1aff5, 0x1affb }, + { 0x1affd, 0x1affe }, + { 0x1b000, 0x1b122 }, + { 0x1b132, 0x1b132 }, + { 0x1b150, 0x1b152 }, + { 0x1b155, 0x1b155 }, + { 0x1b164, 0x1b167 }, + { 0x1b170, 0x1b2fb }, + { 0x1bc00, 0x1bc6a }, + { 0x1bc70, 0x1bc7c }, + { 0x1bc80, 0x1bc88 }, + { 0x1bc90, 0x1bc99 }, + { 0x1bc9e, 0x1bc9e }, + { 0x1d400, 0x1d454 }, + { 0x1d456, 0x1d49c }, + { 0x1d49e, 0x1d49f }, + { 0x1d4a2, 0x1d4a2 }, + { 0x1d4a5, 0x1d4a6 }, + { 0x1d4a9, 0x1d4ac }, + { 0x1d4ae, 0x1d4b9 }, + { 0x1d4bb, 0x1d4bb }, + { 0x1d4bd, 0x1d4c3 }, + { 0x1d4c5, 0x1d505 }, + { 0x1d507, 0x1d50a }, + { 0x1d50d, 0x1d514 }, + { 0x1d516, 0x1d51c }, + { 0x1d51e, 0x1d539 }, + { 0x1d53b, 0x1d53e }, + { 0x1d540, 0x1d544 }, + { 0x1d546, 0x1d546 }, + { 0x1d54a, 0x1d550 }, + { 0x1d552, 0x1d6a5 }, + { 0x1d6a8, 0x1d6c0 }, + { 0x1d6c2, 0x1d6da }, + { 0x1d6dc, 0x1d6fa }, + { 0x1d6fc, 0x1d714 }, + { 0x1d716, 0x1d734 }, + { 0x1d736, 0x1d74e }, + { 0x1d750, 0x1d76e }, + { 0x1d770, 0x1d788 }, + { 0x1d78a, 0x1d7a8 }, + { 0x1d7aa, 0x1d7c2 }, + { 0x1d7c4, 0x1d7cb }, + { 0x1df00, 0x1df1e }, + { 0x1df25, 0x1df2a }, + { 0x1e000, 0x1e006 }, + { 0x1e008, 0x1e018 }, + { 0x1e01b, 0x1e021 }, + { 0x1e023, 0x1e024 }, + { 0x1e026, 0x1e02a }, + { 0x1e030, 0x1e06d }, + { 0x1e08f, 0x1e08f }, + { 0x1e100, 0x1e12c }, + { 0x1e137, 0x1e13d }, + { 0x1e14e, 0x1e14e }, + { 0x1e290, 0x1e2ad }, + { 0x1e2c0, 0x1e2eb }, + { 0x1e4d0, 0x1e4eb }, + { 0x1e5d0, 0x1e5ed }, + { 0x1e5f0, 0x1e5f0 }, + { 0x1e7e0, 0x1e7e6 }, + { 0x1e7e8, 0x1e7eb }, + { 0x1e7ed, 0x1e7ee }, + { 0x1e7f0, 0x1e7fe }, + { 0x1e800, 0x1e8c4 }, + { 0x1e900, 0x1e943 }, + { 0x1e947, 0x1e947 }, + { 0x1e94b, 0x1e94b }, + { 0x1ee00, 0x1ee03 }, + { 0x1ee05, 0x1ee1f }, + { 0x1ee21, 0x1ee22 }, + { 0x1ee24, 0x1ee24 }, + { 0x1ee27, 0x1ee27 }, + { 0x1ee29, 0x1ee32 }, + { 0x1ee34, 0x1ee37 }, + { 0x1ee39, 0x1ee39 }, + { 0x1ee3b, 0x1ee3b }, + { 0x1ee42, 0x1ee42 }, + { 0x1ee47, 0x1ee47 }, + { 0x1ee49, 0x1ee49 }, + { 0x1ee4b, 0x1ee4b }, + { 0x1ee4d, 0x1ee4f }, + { 0x1ee51, 0x1ee52 }, + { 0x1ee54, 0x1ee54 }, + { 0x1ee57, 0x1ee57 }, + { 0x1ee59, 0x1ee59 }, + { 0x1ee5b, 0x1ee5b }, + { 0x1ee5d, 0x1ee5d }, + { 0x1ee5f, 0x1ee5f }, + { 0x1ee61, 0x1ee62 }, + { 0x1ee64, 0x1ee64 }, + { 0x1ee67, 0x1ee6a }, + { 0x1ee6c, 0x1ee72 }, + { 0x1ee74, 0x1ee77 }, + { 0x1ee79, 0x1ee7c }, + { 0x1ee7e, 0x1ee7e }, + { 0x1ee80, 0x1ee89 }, + { 0x1ee8b, 0x1ee9b }, + { 0x1eea1, 0x1eea3 }, + { 0x1eea5, 0x1eea9 }, + { 0x1eeab, 0x1eebb }, + { 0x1f130, 0x1f149 }, + { 0x1f150, 0x1f169 }, + { 0x1f170, 0x1f189 }, + { 0x20000, 0x2a6df }, + { 0x2a700, 0x2b739 }, + { 0x2b740, 0x2b81d }, + { 0x2b820, 0x2cea1 }, + { 0x2ceb0, 0x2ebe0 }, + { 0x2ebf0, 0x2ee5d }, + { 0x2f800, 0x2fa1d }, + { 0x30000, 0x3134a }, + { 0x31350, 0x323af }, +}; + +} // namespace godot diff --git a/include/godot_cpp/variant/char_utils.hpp b/include/godot_cpp/variant/char_utils.hpp index 6b672be30..71522c6c3 100644 --- a/include/godot_cpp/variant/char_utils.hpp +++ b/include/godot_cpp/variant/char_utils.hpp @@ -30,58 +30,105 @@ #pragma once -static _FORCE_INLINE_ bool is_ascii_upper_case(char32_t c) { - return (c >= 'A' && c <= 'Z'); +#include "char_range.inc.hpp" + +namespace godot { + +#define BSEARCH_CHAR_RANGE(m_array) \ + int low = 0; \ + int high = sizeof(m_array) / sizeof(m_array[0]) - 1; \ + int middle = (low + high) / 2; \ + \ + while (low <= high) { \ + if (p_char < m_array[middle].start) { \ + high = middle - 1; \ + } else if (p_char > m_array[middle].end) { \ + low = middle + 1; \ + } else { \ + return true; \ + } \ + \ + middle = (low + high) / 2; \ + } \ + \ + return false + +constexpr bool is_unicode_identifier_start(char32_t p_char) { + BSEARCH_CHAR_RANGE(xid_start); +} + +constexpr bool is_unicode_identifier_continue(char32_t p_char) { + BSEARCH_CHAR_RANGE(xid_continue); +} + +constexpr bool is_unicode_upper_case(char32_t p_char) { + BSEARCH_CHAR_RANGE(uppercase_letter); } -static _FORCE_INLINE_ bool is_ascii_lower_case(char32_t c) { - return (c >= 'a' && c <= 'z'); +constexpr bool is_unicode_lower_case(char32_t p_char) { + BSEARCH_CHAR_RANGE(lowercase_letter); } -static _FORCE_INLINE_ bool is_digit(char32_t c) { - return (c >= '0' && c <= '9'); +constexpr bool is_unicode_letter(char32_t p_char) { + BSEARCH_CHAR_RANGE(unicode_letter); } -static _FORCE_INLINE_ bool is_hex_digit(char32_t c) { - return (is_digit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); +#undef BSEARCH_CHAR_RANGE + +constexpr bool is_ascii_upper_case(char32_t p_char) { + return (p_char >= 'A' && p_char <= 'Z'); } -static _FORCE_INLINE_ bool is_binary_digit(char32_t c) { - return (c == '0' || c == '1'); +constexpr bool is_ascii_lower_case(char32_t p_char) { + return (p_char >= 'a' && p_char <= 'z'); } -static _FORCE_INLINE_ bool is_ascii_char(char32_t c) { - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); +constexpr bool is_digit(char32_t p_char) { + return (p_char >= '0' && p_char <= '9'); } -static _FORCE_INLINE_ bool is_ascii_alphanumeric_char(char32_t c) { - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); +constexpr bool is_hex_digit(char32_t p_char) { + return (is_digit(p_char) || (p_char >= 'a' && p_char <= 'f') || (p_char >= 'A' && p_char <= 'F')); } -static _FORCE_INLINE_ bool is_ascii_identifier_char(char32_t c) { - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_'; +constexpr bool is_binary_digit(char32_t p_char) { + return (p_char == '0' || p_char == '1'); } -static _FORCE_INLINE_ bool is_symbol(char32_t c) { - return c != '_' && ((c >= '!' && c <= '/') || (c >= ':' && c <= '@') || (c >= '[' && c <= '`') || (c >= '{' && c <= '~') || c == '\t' || c == ' '); +constexpr bool is_ascii_alphabet_char(char32_t p_char) { + return (p_char >= 'a' && p_char <= 'z') || (p_char >= 'A' && p_char <= 'Z'); } -static _FORCE_INLINE_ bool is_control(char32_t p_char) { +constexpr bool is_ascii_alphanumeric_char(char32_t p_char) { + return (p_char >= 'a' && p_char <= 'z') || (p_char >= 'A' && p_char <= 'Z') || (p_char >= '0' && p_char <= '9'); +} + +constexpr bool is_ascii_identifier_char(char32_t p_char) { + return (p_char >= 'a' && p_char <= 'z') || (p_char >= 'A' && p_char <= 'Z') || (p_char >= '0' && p_char <= '9') || p_char == '_'; +} + +constexpr bool is_symbol(char32_t p_char) { + return p_char != '_' && ((p_char >= '!' && p_char <= '/') || (p_char >= ':' && p_char <= '@') || (p_char >= '[' && p_char <= '`') || (p_char >= '{' && p_char <= '~') || p_char == '\t' || p_char == ' '); +} + +constexpr bool is_control(char32_t p_char) { return (p_char <= 0x001f) || (p_char >= 0x007f && p_char <= 0x009f); } -static _FORCE_INLINE_ bool is_whitespace(char32_t p_char) { - return (p_char == ' ') || (p_char == 0x00a0) || (p_char == 0x1680) || (p_char >= 0x2000 && p_char <= 0x200a) || (p_char == 0x202f) || (p_char == 0x205f) || (p_char == 0x3000) || (p_char == 0x2028) || (p_char == 0x2029) || (p_char >= 0x0009 && p_char <= 0x000d) || (p_char == 0x0085); +constexpr bool is_whitespace(char32_t p_char) { + return (p_char == ' ') || (p_char == 0x00a0) || (p_char == 0x1680) || (p_char >= 0x2000 && p_char <= 0x200b) || (p_char == 0x202f) || (p_char == 0x205f) || (p_char == 0x3000) || (p_char == 0x2028) || (p_char == 0x2029) || (p_char >= 0x0009 && p_char <= 0x000d) || (p_char == 0x0085); } -static _FORCE_INLINE_ bool is_linebreak(char32_t p_char) { +constexpr bool is_linebreak(char32_t p_char) { return (p_char >= 0x000a && p_char <= 0x000d) || (p_char == 0x0085) || (p_char == 0x2028) || (p_char == 0x2029); } -static _FORCE_INLINE_ bool is_punct(char32_t p_char) { +constexpr bool is_punct(char32_t p_char) { return (p_char >= ' ' && p_char <= '/') || (p_char >= ':' && p_char <= '@') || (p_char >= '[' && p_char <= '^') || (p_char == '`') || (p_char >= '{' && p_char <= '~') || (p_char >= 0x2000 && p_char <= 0x206f) || (p_char >= 0x3000 && p_char <= 0x303f); } -static _FORCE_INLINE_ bool is_underscore(char32_t p_char) { +constexpr bool is_underscore(char32_t p_char) { return (p_char == '_'); } + +} // namespace godot diff --git a/include/godot_cpp/variant/color.hpp b/include/godot_cpp/variant/color.hpp index 878a7d870..d3bbc725b 100644 --- a/include/godot_cpp/variant/color.hpp +++ b/include/godot_cpp/variant/color.hpp @@ -102,12 +102,10 @@ struct [[nodiscard]] Color { _FORCE_INLINE_ Color lerp(const Color &p_to, float p_weight) const { Color res = *this; - - res.r += (p_weight * (p_to.r - r)); - res.g += (p_weight * (p_to.g - g)); - res.b += (p_weight * (p_to.b - b)); - res.a += (p_weight * (p_to.a - a)); - + res.r = Math::lerp(res.r, p_to.r, p_weight); + res.g = Math::lerp(res.g, p_to.g, p_weight); + res.b = Math::lerp(res.b, p_to.b, p_weight); + res.a = Math::lerp(res.a, p_to.a, p_weight); return res; } @@ -128,33 +126,46 @@ struct [[nodiscard]] Color { } _FORCE_INLINE_ uint32_t to_rgbe9995() const { - const float pow2to9 = 512.0f; - const float B = 15.0f; - const float N = 9.0f; - - float sharedexp = 65408.000f; // Result of: ((pow2to9 - 1.0f) / pow2to9) * powf(2.0f, 31.0f - 15.0f) - - float cRed = MAX(0.0f, MIN(sharedexp, r)); - float cGreen = MAX(0.0f, MIN(sharedexp, g)); - float cBlue = MAX(0.0f, MIN(sharedexp, b)); - - float cMax = MAX(cRed, MAX(cGreen, cBlue)); - - float expp = MAX(-B - 1.0f, floor(Math::log(cMax) / (real_t)Math_LN2)) + 1.0f + B; - - float sMax = (float)floor((cMax / Math::pow(2.0f, expp - B - N)) + 0.5f); - - float exps = expp + 1.0f; - - if (0.0f <= sMax && sMax < pow2to9) { - exps = expp; - } - - float sRed = Math::floor((cRed / pow(2.0f, exps - B - N)) + 0.5f); - float sGreen = Math::floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f); - float sBlue = Math::floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f); - - return (uint32_t(Math::fast_ftoi(sRed)) & 0x1FF) | ((uint32_t(Math::fast_ftoi(sGreen)) & 0x1FF) << 9) | ((uint32_t(Math::fast_ftoi(sBlue)) & 0x1FF) << 18) | ((uint32_t(Math::fast_ftoi(exps)) & 0x1F) << 27); + // https://github.com/microsoft/DirectX-Graphics-Samples/blob/v10.0.19041.0/MiniEngine/Core/Color.cpp + static const float kMaxVal = float(0x1FF << 7); + static const float kMinVal = float(1.f / (1 << 16)); + + // Clamp RGB to [0, 1.FF*2^16] + const float _r = CLAMP(r, 0.0f, kMaxVal); + const float _g = CLAMP(g, 0.0f, kMaxVal); + const float _b = CLAMP(b, 0.0f, kMaxVal); + + // Compute the maximum channel, no less than 1.0*2^-15 + const float MaxChannel = MAX(MAX(_r, _g), MAX(_b, kMinVal)); + + // Take the exponent of the maximum channel (rounding up the 9th bit) and + // add 15 to it. When added to the channels, it causes the implicit '1.0' + // bit and the first 8 mantissa bits to be shifted down to the low 9 bits + // of the mantissa, rounding the truncated bits. + union { + float f; + uint32_t i; + } R, G, B, E; + + E.f = MaxChannel; + E.i += 0x07804000; // Add 15 to the exponent and 0x4000 to the mantissa + E.i &= 0x7F800000; // Zero the mantissa + + // This shifts the 9-bit values we need into the lowest bits, rounding as + // needed. Note that if the channel has a smaller exponent than the max + // channel, it will shift even more. This is intentional. + R.f = _r + E.f; + G.f = _g + E.f; + B.f = _b + E.f; + + // Convert the Bias to the correct exponent in the upper 5 bits. + E.i <<= 4; + E.i += 0x10000000; + + // Combine the fields. RGB floats have unwanted data in the upper 9 + // bits. Only red needs to mask them off because green and blue shift + // it out to the left. + return E.i | (B.i << 18U) | (G.i << 9U) | (R.i & 511U); } _FORCE_INLINE_ Color blend(const Color &p_over) const { @@ -173,16 +184,16 @@ struct [[nodiscard]] Color { _FORCE_INLINE_ Color srgb_to_linear() const { return Color( - r < 0.04045f ? r * (1.0f / 12.92f) : Math::pow((r + 0.055f) * (float)(1.0 / (1.0 + 0.055)), 2.4f), - g < 0.04045f ? g * (1.0f / 12.92f) : Math::pow((g + 0.055f) * (float)(1.0 / (1.0 + 0.055)), 2.4f), - b < 0.04045f ? b * (1.0f / 12.92f) : Math::pow((b + 0.055f) * (float)(1.0 / (1.0 + 0.055)), 2.4f), + r < 0.04045f ? r * (1.0f / 12.92f) : Math::pow(float((r + 0.055) * (1.0 / (1.0 + 0.055))), 2.4f), + g < 0.04045f ? g * (1.0f / 12.92f) : Math::pow(float((g + 0.055) * (1.0 / (1.0 + 0.055))), 2.4f), + b < 0.04045f ? b * (1.0f / 12.92f) : Math::pow(float((b + 0.055) * (1.0 / (1.0 + 0.055))), 2.4f), a); } _FORCE_INLINE_ Color linear_to_srgb() const { return Color( - r < 0.0031308f ? 12.92f * r : (1.0f + 0.055f) * Math::pow(r, 1.0f / 2.4f) - 0.055f, - g < 0.0031308f ? 12.92f * g : (1.0f + 0.055f) * Math::pow(g, 1.0f / 2.4f) - 0.055f, - b < 0.0031308f ? 12.92f * b : (1.0f + 0.055f) * Math::pow(b, 1.0f / 2.4f) - 0.055f, a); + r < 0.0031308f ? 12.92f * r : (1.0 + 0.055) * Math::pow(r, 1.0f / 2.4f) - 0.055, + g < 0.0031308f ? 12.92f * g : (1.0 + 0.055) * Math::pow(g, 1.0f / 2.4f) - 0.055, + b < 0.0031308f ? 12.92f * b : (1.0 + 0.055) * Math::pow(b, 1.0f / 2.4f) - 0.055, a); } static Color hex(uint32_t p_hex); @@ -198,6 +209,7 @@ struct [[nodiscard]] Color { static Color from_string(const String &p_string, const Color &p_default); static Color from_hsv(float p_h, float p_s, float p_v, float p_alpha = 1.0f); static Color from_rgbe9995(uint32_t p_rgbe); + static Color from_rgba8(int64_t p_r8, int64_t p_g8, int64_t p_b8, int64_t p_a8 = 255); _FORCE_INLINE_ bool operator<(const Color &p_color) const; // Used in set keys. operator String() const; diff --git a/include/godot_cpp/variant/color_names.inc.hpp b/include/godot_cpp/variant/color_names.inc.hpp index e2c878327..3a2c359c0 100644 --- a/include/godot_cpp/variant/color_names.inc.hpp +++ b/include/godot_cpp/variant/color_names.inc.hpp @@ -187,7 +187,6 @@ static NamedColor named_colors[] = { { "WHITE_SMOKE", Color::hex(0xF5F5F5FF) }, { "YELLOW", Color::hex(0xFFFF00FF) }, { "YELLOW_GREEN", Color::hex(0x9ACD32FF) }, - { nullptr, Color() }, }; } // namespace godot diff --git a/include/godot_cpp/variant/plane.hpp b/include/godot_cpp/variant/plane.hpp index f2c440a23..97ae7c81d 100644 --- a/include/godot_cpp/variant/plane.hpp +++ b/include/godot_cpp/variant/plane.hpp @@ -49,7 +49,7 @@ struct [[nodiscard]] Plane { /* Plane-Point operations */ - _FORCE_INLINE_ Vector3 center() const { return normal * d; } + _FORCE_INLINE_ Vector3 get_center() const { return normal * d; } Vector3 get_any_perpendicular_normal() const; _FORCE_INLINE_ bool is_point_over(const Vector3 &p_point) const; ///< Point is over plane @@ -102,7 +102,7 @@ real_t Plane::distance_to(const Vector3 &p_point) const { bool Plane::has_point(const Vector3 &p_point, real_t p_tolerance) const { real_t dist = normal.dot(p_point) - d; - dist = Math::abs(dist); + dist = ABS(dist); return (dist <= p_tolerance); } diff --git a/include/godot_cpp/variant/projection.hpp b/include/godot_cpp/variant/projection.hpp index b7eb1f89e..e2283e6a6 100644 --- a/include/godot_cpp/variant/projection.hpp +++ b/include/godot_cpp/variant/projection.hpp @@ -31,6 +31,7 @@ #pragma once #include +#include #include #include @@ -55,21 +56,21 @@ struct [[nodiscard]] Projection { Vector4 columns[4]; - _FORCE_INLINE_ const Vector4 &operator[](const int p_axis) const { + _FORCE_INLINE_ const Vector4 &operator[](int p_axis) const { DEV_ASSERT((unsigned int)p_axis < 4); return columns[p_axis]; } - _FORCE_INLINE_ Vector4 &operator[](const int p_axis) { + _FORCE_INLINE_ Vector4 &operator[](int p_axis) { DEV_ASSERT((unsigned int)p_axis < 4); return columns[p_axis]; } - float determinant() const; + real_t determinant() const; void set_identity(); void set_zero(); void set_light_bias(); - void set_depth_correction(bool p_flip_y = true); + void set_depth_correction(bool p_flip_y = true, bool p_reverse_z = true, bool p_remap_z = true); void set_light_atlas_rect(const Rect2 &p_rect); void set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov = false); @@ -106,7 +107,7 @@ struct [[nodiscard]] Projection { real_t get_fov() const; bool is_orthogonal() const; - Array get_projection_planes(const Transform3D &p_transform) const; + Vector get_projection_planes(const Transform3D &p_transform) const; bool get_endpoints(const Transform3D &p_transform, Vector3 *p_8points) const; Vector2 get_viewport_half_extents() const; @@ -148,7 +149,7 @@ struct [[nodiscard]] Projection { return !(*this == p_cam); } - float get_lod_multiplier() const; + real_t get_lod_multiplier() const; Projection(); Projection(const Vector4 &p_x, const Vector4 &p_y, const Vector4 &p_z, const Vector4 &p_w); diff --git a/include/godot_cpp/variant/quaternion.hpp b/include/godot_cpp/variant/quaternion.hpp index 33569addf..c93fe57e8 100644 --- a/include/godot_cpp/variant/quaternion.hpp +++ b/include/godot_cpp/variant/quaternion.hpp @@ -142,15 +142,24 @@ struct [[nodiscard]] Quaternion { } Quaternion(const Vector3 &p_v0, const Vector3 &p_v1) { // Shortest arc. - Vector3 c = p_v0.cross(p_v1); - real_t d = p_v0.dot(p_v1); - - if (d < -1.0f + (real_t)CMP_EPSILON) { - x = 0; - y = 1; - z = 0; +#ifdef MATH_CHECKS + ERR_FAIL_COND_MSG(p_v0.is_zero_approx() || p_v1.is_zero_approx(), "The vectors must not be zero."); +#endif + constexpr real_t ALMOST_ONE = 1.0f - (real_t)CMP_EPSILON; + Vector3 n0 = p_v0.normalized(); + Vector3 n1 = p_v1.normalized(); + real_t d = n0.dot(n1); + if (abs(d) > ALMOST_ONE) { + if (d >= 0) { + return; // Vectors are same. + } + Vector3 axis = n0.get_any_perpendicular(); + x = axis.x; + y = axis.y; + z = axis.z; w = 0; } else { + Vector3 c = n0.cross(n1); real_t s = Math::sqrt((1.0f + d) * 2.0f); real_t rs = 1.0f / s; diff --git a/include/godot_cpp/variant/rect2.hpp b/include/godot_cpp/variant/rect2.hpp index 3a5e18e3b..a5e334041 100644 --- a/include/godot_cpp/variant/rect2.hpp +++ b/include/godot_cpp/variant/rect2.hpp @@ -52,7 +52,7 @@ struct [[nodiscard]] Rect2 { _FORCE_INLINE_ Vector2 get_center() const { return position + (size * 0.5f); } - inline bool intersects(const Rect2 &p_rect, const bool p_include_borders = false) const { + inline bool intersects(const Rect2 &p_rect, bool p_include_borders = false) const { #ifdef MATH_CHECKS if (unlikely(size.x < 0 || size.y < 0 || p_rect.size.x < 0 || p_rect.size.y < 0)) { ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size."); @@ -105,17 +105,17 @@ struct [[nodiscard]] Rect2 { } if (p_point.y < position.y) { real_t d = position.y - p_point.y; - dist = inside ? d : Math::min(dist, d); + dist = inside ? d : MIN(dist, d); inside = false; } if (p_point.x >= (position.x + size.x)) { real_t d = p_point.x - (position.x + size.x); - dist = inside ? d : Math::min(dist, d); + dist = inside ? d : MIN(dist, d); inside = false; } if (p_point.y >= (position.y + size.y)) { real_t d = p_point.y - (position.y + size.y); - dist = inside ? d : Math::min(dist, d); + dist = inside ? d : MIN(dist, d); inside = false; } @@ -145,7 +145,7 @@ struct [[nodiscard]] Rect2 { return size.x > 0.0f && size.y > 0.0f; } - // Returns the intersection between two Rect2s or an empty Rect2 if there is no intersection + // Returns the intersection between two Rect2s or an empty Rect2 if there is no intersection. inline Rect2 intersection(const Rect2 &p_rect) const { Rect2 new_rect = p_rect; @@ -282,13 +282,19 @@ struct [[nodiscard]] Rect2 { return Rect2(position + size.minf(0), size.abs()); } - Vector2 get_support(const Vector2 &p_normal) const { - Vector2 half_extents = size * 0.5f; - Vector2 ofs = position + half_extents; - return Vector2( - (p_normal.x > 0) ? -half_extents.x : half_extents.x, - (p_normal.y > 0) ? -half_extents.y : half_extents.y) + - ofs; + _FORCE_INLINE_ Rect2 round() const { + return Rect2(position.round(), size.round()); + } + + Vector2 get_support(const Vector2 &p_direction) const { + Vector2 support = position; + if (p_direction.x > 0.0f) { + support.x += size.x; + } + if (p_direction.y > 0.0f) { + support.y += size.y; + } + return support; } _FORCE_INLINE_ bool intersects_filled_polygon(const Vector2 *p_points, int p_point_count) const { @@ -304,14 +310,14 @@ struct [[nodiscard]] Rect2 { i_f = i; Vector2 r = (b - a); - float l = r.length(); + const real_t l = r.length(); if (l == 0.0f) { continue; } // Check inside. Vector2 tg = r.orthogonal(); - float s = tg.dot(center) - tg.dot(a); + const real_t s = tg.dot(center) - tg.dot(a); if (s < 0.0f) { side_plus++; } else { @@ -327,8 +333,8 @@ struct [[nodiscard]] Rect2 { Vector2 t13 = (position - a) * ir; Vector2 t24 = (end - a) * ir; - float tmin = Math::max(Math::min(t13.x, t24.x), Math::min(t13.y, t24.y)); - float tmax = Math::min(Math::max(t13.x, t24.x), Math::max(t13.y, t24.y)); + const real_t tmin = MAX(MIN(t13.x, t24.x), MIN(t13.y, t24.y)); + const real_t tmax = MIN(MAX(t13.x, t24.x), MAX(t13.y, t24.y)); // if tmax < 0, ray (line) is intersecting AABB, but the whole AABB is behind us if (tmax < 0 || tmin > tmax || tmin >= l) { diff --git a/include/godot_cpp/variant/rect2i.hpp b/include/godot_cpp/variant/rect2i.hpp index 94c340a89..0c593edeb 100644 --- a/include/godot_cpp/variant/rect2i.hpp +++ b/include/godot_cpp/variant/rect2i.hpp @@ -88,7 +88,7 @@ struct [[nodiscard]] Rect2i { return size.x > 0 && size.y > 0; } - // Returns the intersection between two Rect2is or an empty Rect2i if there is no intersection + // Returns the intersection between two Rect2is or an empty Rect2i if there is no intersection. inline Rect2i intersection(const Rect2i &p_rect) const { Rect2i new_rect = p_rect; diff --git a/include/godot_cpp/variant/transform2d.hpp b/include/godot_cpp/variant/transform2d.hpp index 5135d555e..9170e5688 100644 --- a/include/godot_cpp/variant/transform2d.hpp +++ b/include/godot_cpp/variant/transform2d.hpp @@ -39,21 +39,24 @@ namespace godot { class String; struct [[nodiscard]] Transform2D { - // Warning #1: basis of Transform2D is stored differently from Basis. In terms of columns array, the basis matrix looks like "on paper": + // WARNING: The basis of Transform2D is stored differently from Basis. + // In terms of columns array, the basis matrix looks like "on paper": // M = (columns[0][0] columns[1][0]) // (columns[0][1] columns[1][1]) - // This is such that the columns, which can be interpreted as basis vectors of the coordinate system "painted" on the object, can be accessed as columns[i]. - // Note that this is the opposite of the indices in mathematical texts, meaning: $M_{12}$ in a math book corresponds to columns[1][0] here. + // This is such that the columns, which can be interpreted as basis vectors + // of the coordinate system "painted" on the object, can be accessed as columns[i]. + // NOTE: This is the opposite of the indices in mathematical texts, + // meaning: $M_{12}$ in a math book corresponds to columns[1][0] here. // This requires additional care when working with explicit indices. // See https://en.wikipedia.org/wiki/Row-_and_column-major_order for further reading. - // Warning #2: 2D be aware that unlike 3D code, 2D code uses a left-handed coordinate system: Y-axis points down, - // and angle is measure from +X to +Y in a clockwise-fashion. + // WARNING: Be aware that unlike 3D code, 2D code uses a left-handed coordinate system: + // Y-axis points down, and angle is measure from +X to +Y in a clockwise-fashion. Vector2 columns[3]; - _FORCE_INLINE_ real_t tdotx(const Vector2 &v) const { return columns[0][0] * v.x + columns[1][0] * v.y; } - _FORCE_INLINE_ real_t tdoty(const Vector2 &v) const { return columns[0][1] * v.x + columns[1][1] * v.y; } + _FORCE_INLINE_ real_t tdotx(const Vector2 &p_v) const { return columns[0][0] * p_v.x + columns[1][0] * p_v.y; } + _FORCE_INLINE_ real_t tdoty(const Vector2 &p_v) const { return columns[0][1] * p_v.x + columns[1][1] * p_v.y; } const Vector2 &operator[](int p_idx) const { return columns[p_idx]; } Vector2 &operator[](int p_idx) { return columns[p_idx]; } @@ -64,20 +67,20 @@ struct [[nodiscard]] Transform2D { void affine_invert(); Transform2D affine_inverse() const; - void set_rotation(const real_t p_rot); + void set_rotation(real_t p_rot); real_t get_rotation() const; real_t get_skew() const; - void set_skew(const real_t p_angle); - _FORCE_INLINE_ void set_rotation_and_scale(const real_t p_rot, const Size2 &p_scale); - _FORCE_INLINE_ void set_rotation_scale_and_skew(const real_t p_rot, const Size2 &p_scale, const real_t p_skew); - void rotate(const real_t p_angle); + void set_skew(real_t p_angle); + _FORCE_INLINE_ void set_rotation_and_scale(real_t p_rot, const Size2 &p_scale); + _FORCE_INLINE_ void set_rotation_scale_and_skew(real_t p_rot, const Size2 &p_scale, real_t p_skew); + void rotate(real_t p_angle); void scale(const Size2 &p_scale); void scale_basis(const Size2 &p_scale); - void translate_local(const real_t p_tx, const real_t p_ty); + void translate_local(real_t p_tx, real_t p_ty); void translate_local(const Vector2 &p_translation); - real_t basis_determinant() const; + real_t determinant() const; Size2 get_scale() const; void set_scale(const Size2 &p_scale); @@ -85,18 +88,18 @@ struct [[nodiscard]] Transform2D { _FORCE_INLINE_ const Vector2 &get_origin() const { return columns[2]; } _FORCE_INLINE_ void set_origin(const Vector2 &p_origin) { columns[2] = p_origin; } - Transform2D basis_scaled(const Size2 &p_scale) const; Transform2D scaled(const Size2 &p_scale) const; Transform2D scaled_local(const Size2 &p_scale) const; Transform2D translated(const Vector2 &p_offset) const; Transform2D translated_local(const Vector2 &p_offset) const; - Transform2D rotated(const real_t p_angle) const; - Transform2D rotated_local(const real_t p_angle) const; + Transform2D rotated(real_t p_angle) const; + Transform2D rotated_local(real_t p_angle) const; Transform2D untranslated() const; void orthonormalize(); Transform2D orthonormalized() const; + bool is_conformal() const; bool is_equal_approx(const Transform2D &p_transform) const; bool is_finite() const; @@ -107,10 +110,12 @@ struct [[nodiscard]] Transform2D { void operator*=(const Transform2D &p_transform); Transform2D operator*(const Transform2D &p_transform) const; - void operator*=(const real_t p_val); - Transform2D operator*(const real_t p_val) const; + void operator*=(real_t p_val); + Transform2D operator*(real_t p_val) const; + void operator/=(real_t p_val); + Transform2D operator/(real_t p_val) const; - Transform2D interpolate_with(const Transform2D &p_transform, const real_t p_c) const; + Transform2D interpolate_with(const Transform2D &p_transform, real_t p_c) const; _FORCE_INLINE_ Vector2 basis_xform(const Vector2 &p_vec) const; _FORCE_INLINE_ Vector2 basis_xform_inv(const Vector2 &p_vec) const; @@ -123,13 +128,13 @@ struct [[nodiscard]] Transform2D { operator String() const; - Transform2D(const real_t xx, const real_t xy, const real_t yx, const real_t yy, const real_t ox, const real_t oy) { - columns[0][0] = xx; - columns[0][1] = xy; - columns[1][0] = yx; - columns[1][1] = yy; - columns[2][0] = ox; - columns[2][1] = oy; + Transform2D(real_t p_xx, real_t p_xy, real_t p_yx, real_t p_yy, real_t p_ox, real_t p_oy) { + columns[0][0] = p_xx; + columns[0][1] = p_xy; + columns[1][0] = p_yx; + columns[1][1] = p_yy; + columns[2][0] = p_ox; + columns[2][1] = p_oy; } Transform2D(const Vector2 &p_x, const Vector2 &p_y, const Vector2 &p_origin) { @@ -138,9 +143,9 @@ struct [[nodiscard]] Transform2D { columns[2] = p_origin; } - Transform2D(const real_t p_rot, const Vector2 &p_pos); + Transform2D(real_t p_rot, const Vector2 &p_pos); - Transform2D(const real_t p_rot, const Size2 &p_scale, const real_t p_skew, const Vector2 &p_pos); + Transform2D(real_t p_rot, const Size2 &p_scale, real_t p_skew, const Vector2 &p_pos); Transform2D() { columns[0][0] = 1.0; @@ -188,14 +193,14 @@ Rect2 Transform2D::xform(const Rect2 &p_rect) const { return new_rect; } -void Transform2D::set_rotation_and_scale(const real_t p_rot, const Size2 &p_scale) { +void Transform2D::set_rotation_and_scale(real_t p_rot, const Size2 &p_scale) { columns[0][0] = Math::cos(p_rot) * p_scale.x; columns[1][1] = Math::cos(p_rot) * p_scale.y; columns[1][0] = -Math::sin(p_rot) * p_scale.y; columns[0][1] = Math::sin(p_rot) * p_scale.x; } -void Transform2D::set_rotation_scale_and_skew(const real_t p_rot, const Size2 &p_scale, const real_t p_skew) { +void Transform2D::set_rotation_scale_and_skew(real_t p_rot, const Size2 &p_scale, real_t p_skew) { columns[0][0] = Math::cos(p_rot) * p_scale.x; columns[1][1] = Math::cos(p_rot + p_skew) * p_scale.y; columns[1][0] = -Math::sin(p_rot + p_skew) * p_scale.y; diff --git a/include/godot_cpp/variant/transform3d.hpp b/include/godot_cpp/variant/transform3d.hpp index b0c1d2e7b..80392e396 100644 --- a/include/godot_cpp/variant/transform3d.hpp +++ b/include/godot_cpp/variant/transform3d.hpp @@ -54,8 +54,8 @@ struct [[nodiscard]] Transform3D { void rotate(const Vector3 &p_axis, real_t p_angle); void rotate_basis(const Vector3 &p_axis, real_t p_angle); - void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0)); - Transform3D looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0)) const; + void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false); + Transform3D looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false) const; void scale(const Vector3 &p_scale); Transform3D scaled(const Vector3 &p_scale) const; @@ -104,8 +104,10 @@ struct [[nodiscard]] Transform3D { void operator*=(const Transform3D &p_transform); Transform3D operator*(const Transform3D &p_transform) const; - void operator*=(const real_t p_val); - Transform3D operator*(const real_t p_val) const; + void operator*=(real_t p_val); + Transform3D operator*(real_t p_val) const; + void operator/=(real_t p_val); + Transform3D operator/(real_t p_val) const; Transform3D interpolate_with(const Transform3D &p_transform, real_t p_c) const; @@ -115,11 +117,11 @@ struct [[nodiscard]] Transform3D { basis.xform(v)); } - void set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t tx, real_t ty, real_t tz) { - basis.set(xx, xy, xz, yx, yy, yz, zx, zy, zz); - origin.x = tx; - origin.y = ty; - origin.z = tz; + void set(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_zx, real_t p_zy, real_t p_zz, real_t p_tx, real_t p_ty, real_t p_tz) { + basis.set(p_xx, p_xy, p_xz, p_yx, p_yy, p_yz, p_zx, p_zy, p_zz); + origin.x = p_tx; + origin.y = p_ty; + origin.z = p_tz; } operator String() const; @@ -127,7 +129,7 @@ struct [[nodiscard]] Transform3D { Transform3D() {} Transform3D(const Basis &p_basis, const Vector3 &p_origin = Vector3()); Transform3D(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z, const Vector3 &p_origin); - Transform3D(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t ox, real_t oy, real_t oz); + Transform3D(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_zx, real_t p_zy, real_t p_zz, real_t p_ox, real_t p_oy, real_t p_oz); }; _FORCE_INLINE_ Vector3 Transform3D::xform(const Vector3 &p_vector) const { diff --git a/include/godot_cpp/variant/vector2.hpp b/include/godot_cpp/variant/vector2.hpp index 32004f01a..400bdeffe 100644 --- a/include/godot_cpp/variant/vector2.hpp +++ b/include/godot_cpp/variant/vector2.hpp @@ -61,13 +61,13 @@ struct [[nodiscard]] Vector2 { real_t coord[2] = { 0 }; }; - _FORCE_INLINE_ real_t &operator[](int p_idx) { - DEV_ASSERT((unsigned int)p_idx < 2); - return coord[p_idx]; + _FORCE_INLINE_ real_t &operator[](int p_axis) { + DEV_ASSERT((unsigned int)p_axis < 2); + return coord[p_axis]; } - _FORCE_INLINE_ const real_t &operator[](int p_idx) const { - DEV_ASSERT((unsigned int)p_idx < 2); - return coord[p_idx]; + _FORCE_INLINE_ const real_t &operator[](int p_axis) const { + DEV_ASSERT((unsigned int)p_axis < 2); + return coord[p_axis]; } _FORCE_INLINE_ Vector2::Axis min_axis_index() const { @@ -84,7 +84,7 @@ struct [[nodiscard]] Vector2 { real_t length() const; real_t length_squared() const; - Vector2 limit_length(const real_t p_len = 1.0) const; + Vector2 limit_length(real_t p_len = 1.0) const; Vector2 min(const Vector2 &p_vector2) const { return Vector2(MIN(x, p_vector2.x), MIN(y, p_vector2.y)); @@ -110,19 +110,20 @@ struct [[nodiscard]] Vector2 { real_t dot(const Vector2 &p_other) const; real_t cross(const Vector2 &p_other) const; - Vector2 posmod(const real_t p_mod) const; + Vector2 posmod(real_t p_mod) const; Vector2 posmodv(const Vector2 &p_modv) const; Vector2 project(const Vector2 &p_to) const; - Vector2 plane_project(const real_t p_d, const Vector2 &p_vec) const; + Vector2 plane_project(real_t p_d, const Vector2 &p_vec) const; - _FORCE_INLINE_ Vector2 lerp(const Vector2 &p_to, const real_t p_weight) const; - _FORCE_INLINE_ Vector2 slerp(const Vector2 &p_to, const real_t p_weight) const; - _FORCE_INLINE_ Vector2 cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, const real_t p_weight) const; - _FORCE_INLINE_ Vector2 cubic_interpolate_in_time(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, const real_t p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const; - _FORCE_INLINE_ Vector2 bezier_interpolate(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, const real_t p_t) const; + _FORCE_INLINE_ Vector2 lerp(const Vector2 &p_to, real_t p_weight) const; + _FORCE_INLINE_ Vector2 slerp(const Vector2 &p_to, real_t p_weight) const; + _FORCE_INLINE_ Vector2 cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_weight) const; + _FORCE_INLINE_ Vector2 cubic_interpolate_in_time(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_weight, real_t p_b_t, real_t p_pre_a_t, real_t p_post_b_t) const; + _FORCE_INLINE_ Vector2 bezier_interpolate(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, real_t p_t) const; + _FORCE_INLINE_ Vector2 bezier_derivative(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, real_t p_t) const; - Vector2 move_toward(const Vector2 &p_to, const real_t p_delta) const; + Vector2 move_toward(const Vector2 &p_to, real_t p_delta) const; Vector2 slide(const Vector2 &p_normal) const; Vector2 bounce(const Vector2 &p_normal) const; @@ -138,16 +139,16 @@ struct [[nodiscard]] Vector2 { void operator-=(const Vector2 &p_v); Vector2 operator*(const Vector2 &p_v1) const; - Vector2 operator*(const real_t &rvalue) const; - void operator*=(const real_t &rvalue); - void operator*=(const Vector2 &rvalue) { *this = *this * rvalue; } + Vector2 operator*(real_t p_rvalue) const; + void operator*=(real_t p_rvalue); + void operator*=(const Vector2 &p_rvalue) { *this = *this * p_rvalue; } Vector2 operator/(const Vector2 &p_v1) const; - Vector2 operator/(const real_t &rvalue) const; + Vector2 operator/(real_t p_rvalue) const; - void operator/=(const real_t &rvalue); - void operator/=(const Vector2 &rvalue) { *this = *this / rvalue; } + void operator/=(real_t p_rvalue); + void operator/=(const Vector2 &p_rvalue) { *this = *this / p_rvalue; } Vector2 operator-() const; @@ -160,13 +161,13 @@ struct [[nodiscard]] Vector2 { bool operator>=(const Vector2 &p_vec2) const { return x == p_vec2.x ? (y >= p_vec2.y) : (x > p_vec2.x); } real_t angle() const; - static Vector2 from_angle(const real_t p_angle); + static Vector2 from_angle(real_t p_angle); _FORCE_INLINE_ Vector2 abs() const { return Vector2(Math::abs(x), Math::abs(y)); } - Vector2 rotated(const real_t p_by) const; + Vector2 rotated(real_t p_by) const; Vector2 orthogonal() const { return Vector2(y, -x); } @@ -185,13 +186,13 @@ struct [[nodiscard]] Vector2 { operator Vector2i() const; _FORCE_INLINE_ Vector2() {} - _FORCE_INLINE_ Vector2(const real_t p_x, const real_t p_y) { + _FORCE_INLINE_ Vector2(real_t p_x, real_t p_y) { x = p_x; y = p_y; } }; -_FORCE_INLINE_ Vector2 Vector2::plane_project(const real_t p_d, const Vector2 &p_vec) const { +_FORCE_INLINE_ Vector2 Vector2::plane_project(real_t p_d, const Vector2 &p_vec) const { return p_vec - *this * (dot(p_vec) - p_d); } @@ -217,26 +218,26 @@ _FORCE_INLINE_ Vector2 Vector2::operator*(const Vector2 &p_v1) const { return Vector2(x * p_v1.x, y * p_v1.y); } -_FORCE_INLINE_ Vector2 Vector2::operator*(const real_t &rvalue) const { - return Vector2(x * rvalue, y * rvalue); +_FORCE_INLINE_ Vector2 Vector2::operator*(real_t p_rvalue) const { + return Vector2(x * p_rvalue, y * p_rvalue); } -_FORCE_INLINE_ void Vector2::operator*=(const real_t &rvalue) { - x *= rvalue; - y *= rvalue; +_FORCE_INLINE_ void Vector2::operator*=(real_t p_rvalue) { + x *= p_rvalue; + y *= p_rvalue; } _FORCE_INLINE_ Vector2 Vector2::operator/(const Vector2 &p_v1) const { return Vector2(x / p_v1.x, y / p_v1.y); } -_FORCE_INLINE_ Vector2 Vector2::operator/(const real_t &rvalue) const { - return Vector2(x / rvalue, y / rvalue); +_FORCE_INLINE_ Vector2 Vector2::operator/(real_t p_rvalue) const { + return Vector2(x / p_rvalue, y / p_rvalue); } -_FORCE_INLINE_ void Vector2::operator/=(const real_t &rvalue) { - x /= rvalue; - y /= rvalue; +_FORCE_INLINE_ void Vector2::operator/=(real_t p_rvalue) { + x /= p_rvalue; + y /= p_rvalue; } _FORCE_INLINE_ Vector2 Vector2::operator-() const { @@ -251,16 +252,14 @@ _FORCE_INLINE_ bool Vector2::operator!=(const Vector2 &p_vec2) const { return x != p_vec2.x || y != p_vec2.y; } -Vector2 Vector2::lerp(const Vector2 &p_to, const real_t p_weight) const { +Vector2 Vector2::lerp(const Vector2 &p_to, real_t p_weight) const { Vector2 res = *this; - - res.x += (p_weight * (p_to.x - x)); - res.y += (p_weight * (p_to.y - y)); - + res.x = Math::lerp(res.x, p_to.x, p_weight); + res.y = Math::lerp(res.y, p_to.y, p_weight); return res; } -Vector2 Vector2::slerp(const Vector2 &p_to, const real_t p_weight) const { +Vector2 Vector2::slerp(const Vector2 &p_to, real_t p_weight) const { real_t start_length_sq = length_squared(); real_t end_length_sq = p_to.length_squared(); if (unlikely(start_length_sq == 0.0f || end_length_sq == 0.0f)) { @@ -273,31 +272,32 @@ Vector2 Vector2::slerp(const Vector2 &p_to, const real_t p_weight) const { return rotated(angle * p_weight) * (result_length / start_length); } -Vector2 Vector2::cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, const real_t p_weight) const { +Vector2 Vector2::cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_weight) const { Vector2 res = *this; res.x = Math::cubic_interpolate(res.x, p_b.x, p_pre_a.x, p_post_b.x, p_weight); res.y = Math::cubic_interpolate(res.y, p_b.y, p_pre_a.y, p_post_b.y, p_weight); return res; } -Vector2 Vector2::cubic_interpolate_in_time(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, const real_t p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const { +Vector2 Vector2::cubic_interpolate_in_time(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_weight, real_t p_b_t, real_t p_pre_a_t, real_t p_post_b_t) const { Vector2 res = *this; res.x = Math::cubic_interpolate_in_time(res.x, p_b.x, p_pre_a.x, p_post_b.x, p_weight, p_b_t, p_pre_a_t, p_post_b_t); res.y = Math::cubic_interpolate_in_time(res.y, p_b.y, p_pre_a.y, p_post_b.y, p_weight, p_b_t, p_pre_a_t, p_post_b_t); return res; } -Vector2 Vector2::bezier_interpolate(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, const real_t p_t) const { +Vector2 Vector2::bezier_interpolate(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, real_t p_t) const { Vector2 res = *this; + res.x = Math::bezier_interpolate(res.x, p_control_1.x, p_control_2.x, p_end.x, p_t); + res.y = Math::bezier_interpolate(res.y, p_control_1.y, p_control_2.y, p_end.y, p_t); + return res; +} - /* Formula from Wikipedia article on Bezier curves. */ - real_t omt = (1.0 - p_t); - real_t omt2 = omt * omt; - real_t omt3 = omt2 * omt; - real_t t2 = p_t * p_t; - real_t t3 = t2 * p_t; - - return res * omt3 + p_control_1 * omt2 * p_t * 3.0 + p_control_2 * omt * t2 * 3.0 + p_end * t3; +Vector2 Vector2::bezier_derivative(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, real_t p_t) const { + Vector2 res = *this; + res.x = Math::bezier_derivative(res.x, p_control_1.x, p_control_2.x, p_end.x, p_t); + res.y = Math::bezier_derivative(res.y, p_control_1.y, p_control_2.y, p_end.y, p_t); + return res; } Vector2 Vector2::direction_to(const Vector2 &p_to) const { @@ -309,19 +309,19 @@ Vector2 Vector2::direction_to(const Vector2 &p_to) const { // Multiplication operators required to workaround issues with LLVM using implicit conversion // to Vector2i instead for integers where it should not. -_FORCE_INLINE_ Vector2 operator*(const float p_scalar, const Vector2 &p_vec) { +_FORCE_INLINE_ Vector2 operator*(float p_scalar, const Vector2 &p_vec) { return p_vec * p_scalar; } -_FORCE_INLINE_ Vector2 operator*(const double p_scalar, const Vector2 &p_vec) { +_FORCE_INLINE_ Vector2 operator*(double p_scalar, const Vector2 &p_vec) { return p_vec * p_scalar; } -_FORCE_INLINE_ Vector2 operator*(const int32_t p_scalar, const Vector2 &p_vec) { +_FORCE_INLINE_ Vector2 operator*(int32_t p_scalar, const Vector2 &p_vec) { return p_vec * p_scalar; } -_FORCE_INLINE_ Vector2 operator*(const int64_t p_scalar, const Vector2 &p_vec) { +_FORCE_INLINE_ Vector2 operator*(int64_t p_scalar, const Vector2 &p_vec) { return p_vec * p_scalar; } diff --git a/include/godot_cpp/variant/vector2i.hpp b/include/godot_cpp/variant/vector2i.hpp index 73a121a48..3278af9f1 100644 --- a/include/godot_cpp/variant/vector2i.hpp +++ b/include/godot_cpp/variant/vector2i.hpp @@ -61,13 +61,13 @@ struct [[nodiscard]] Vector2i { int32_t coord[2] = { 0 }; }; - _FORCE_INLINE_ int32_t &operator[](int p_idx) { - DEV_ASSERT((unsigned int)p_idx < 2); - return coord[p_idx]; + _FORCE_INLINE_ int32_t &operator[](int p_axis) { + DEV_ASSERT((unsigned int)p_axis < 2); + return coord[p_axis]; } - _FORCE_INLINE_ const int32_t &operator[](int p_idx) const { - DEV_ASSERT((unsigned int)p_idx < 2); - return coord[p_idx]; + _FORCE_INLINE_ const int32_t &operator[](int p_axis) const { + DEV_ASSERT((unsigned int)p_axis < 2); + return coord[p_axis]; } _FORCE_INLINE_ Vector2i::Axis min_axis_index() const { @@ -94,22 +94,30 @@ struct [[nodiscard]] Vector2i { return Vector2i(MAX(x, p_scalar), MAX(y, p_scalar)); } + double distance_to(const Vector2i &p_to) const { + return (p_to - *this).length(); + } + + int64_t distance_squared_to(const Vector2i &p_to) const { + return (p_to - *this).length_squared(); + } + Vector2i operator+(const Vector2i &p_v) const; void operator+=(const Vector2i &p_v); Vector2i operator-(const Vector2i &p_v) const; void operator-=(const Vector2i &p_v); Vector2i operator*(const Vector2i &p_v1) const; - Vector2i operator*(const int32_t &rvalue) const; - void operator*=(const int32_t &rvalue); + Vector2i operator*(int32_t p_rvalue) const; + void operator*=(int32_t p_rvalue); Vector2i operator/(const Vector2i &p_v1) const; - Vector2i operator/(const int32_t &rvalue) const; - void operator/=(const int32_t &rvalue); + Vector2i operator/(int32_t p_rvalue) const; + void operator/=(int32_t p_rvalue); Vector2i operator%(const Vector2i &p_v1) const; - Vector2i operator%(const int32_t &rvalue) const; - void operator%=(const int32_t &rvalue); + Vector2i operator%(int32_t p_rvalue) const; + void operator%=(int32_t p_rvalue); Vector2i operator-() const; bool operator<(const Vector2i &p_vec2) const { return (x == p_vec2.x) ? (y < p_vec2.y) : (x < p_vec2.x); } @@ -124,22 +132,19 @@ struct [[nodiscard]] Vector2i { int64_t length_squared() const; double length() const; - int64_t distance_squared_to(const Vector2i &p_to) const; - double distance_to(const Vector2i &p_to) const; - real_t aspect() const { return width / (real_t)height; } Vector2i sign() const { return Vector2i(SIGN(x), SIGN(y)); } Vector2i abs() const { return Vector2i(Math::abs(x), Math::abs(y)); } - Vector2i snapped(const Vector2i &p_step) const; - Vector2i snappedi(int32_t p_step) const; Vector2i clamp(const Vector2i &p_min, const Vector2i &p_max) const; Vector2i clampi(int32_t p_min, int32_t p_max) const; + Vector2i snapped(const Vector2i &p_step) const; + Vector2i snappedi(int32_t p_step) const; operator String() const; operator Vector2() const; inline Vector2i() {} - inline Vector2i(const int32_t p_x, const int32_t p_y) { + inline Vector2i(int32_t p_x, int32_t p_y) { x = p_x; y = p_y; } @@ -147,19 +152,19 @@ struct [[nodiscard]] Vector2i { // Multiplication operators required to workaround issues with LLVM using implicit conversion. -_FORCE_INLINE_ Vector2i operator*(const int32_t p_scalar, const Vector2i &p_vector) { +_FORCE_INLINE_ Vector2i operator*(int32_t p_scalar, const Vector2i &p_vector) { return p_vector * p_scalar; } -_FORCE_INLINE_ Vector2i operator*(const int64_t p_scalar, const Vector2i &p_vector) { +_FORCE_INLINE_ Vector2i operator*(int64_t p_scalar, const Vector2i &p_vector) { return p_vector * p_scalar; } -_FORCE_INLINE_ Vector2i operator*(const float p_scalar, const Vector2i &p_vector) { +_FORCE_INLINE_ Vector2i operator*(float p_scalar, const Vector2i &p_vector) { return p_vector * p_scalar; } -_FORCE_INLINE_ Vector2i operator*(const double p_scalar, const Vector2i &p_vector) { +_FORCE_INLINE_ Vector2i operator*(double p_scalar, const Vector2i &p_vector) { return p_vector * p_scalar; } diff --git a/include/godot_cpp/variant/vector3.hpp b/include/godot_cpp/variant/vector3.hpp index f92d0209c..796daeca7 100644 --- a/include/godot_cpp/variant/vector3.hpp +++ b/include/godot_cpp/variant/vector3.hpp @@ -59,12 +59,12 @@ struct [[nodiscard]] Vector3 { real_t coord[3] = { 0 }; }; - _FORCE_INLINE_ const real_t &operator[](const int p_axis) const { + _FORCE_INLINE_ const real_t &operator[](int p_axis) const { DEV_ASSERT((unsigned int)p_axis < 3); return coord[p_axis]; } - _FORCE_INLINE_ real_t &operator[](const int p_axis) { + _FORCE_INLINE_ real_t &operator[](int p_axis) { DEV_ASSERT((unsigned int)p_axis < 3); return coord[p_axis]; } @@ -100,36 +100,38 @@ struct [[nodiscard]] Vector3 { _FORCE_INLINE_ Vector3 normalized() const; _FORCE_INLINE_ bool is_normalized() const; _FORCE_INLINE_ Vector3 inverse() const; - Vector3 limit_length(const real_t p_len = 1.0) const; + Vector3 limit_length(real_t p_len = 1.0) const; _FORCE_INLINE_ void zero(); - void snap(const Vector3 p_val); - void snapf(real_t p_val); - Vector3 snapped(const Vector3 p_val) const; - Vector3 snappedf(real_t p_val) const; + void snap(const Vector3 &p_step); + void snapf(real_t p_step); + Vector3 snapped(const Vector3 &p_step) const; + Vector3 snappedf(real_t p_step) const; - void rotate(const Vector3 &p_axis, const real_t p_angle); - Vector3 rotated(const Vector3 &p_axis, const real_t p_angle) const; + void rotate(const Vector3 &p_axis, real_t p_angle); + Vector3 rotated(const Vector3 &p_axis, real_t p_angle) const; /* Static Methods between 2 vector3s */ - _FORCE_INLINE_ Vector3 lerp(const Vector3 &p_to, const real_t p_weight) const; - _FORCE_INLINE_ Vector3 slerp(const Vector3 &p_to, const real_t p_weight) const; - _FORCE_INLINE_ Vector3 cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight) const; - _FORCE_INLINE_ Vector3 cubic_interpolate_in_time(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const; - _FORCE_INLINE_ Vector3 bezier_interpolate(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const; + _FORCE_INLINE_ Vector3 lerp(const Vector3 &p_to, real_t p_weight) const; + _FORCE_INLINE_ Vector3 slerp(const Vector3 &p_to, real_t p_weight) const; + _FORCE_INLINE_ Vector3 cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_weight) const; + _FORCE_INLINE_ Vector3 cubic_interpolate_in_time(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_weight, real_t p_b_t, real_t p_pre_a_t, real_t p_post_b_t) const; + _FORCE_INLINE_ Vector3 bezier_interpolate(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, real_t p_t) const; + _FORCE_INLINE_ Vector3 bezier_derivative(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, real_t p_t) const; - Vector3 move_toward(const Vector3 &p_to, const real_t p_delta) const; + Vector3 move_toward(const Vector3 &p_to, real_t p_delta) const; Vector2 octahedron_encode() const; static Vector3 octahedron_decode(const Vector2 &p_oct); - Vector2 octahedron_tangent_encode(const float sign) const; - static Vector3 octahedron_tangent_decode(const Vector2 &p_oct, float *sign); + Vector2 octahedron_tangent_encode(float p_sign) const; + static Vector3 octahedron_tangent_decode(const Vector2 &p_oct, float *r_sign); _FORCE_INLINE_ Vector3 cross(const Vector3 &p_with) const; _FORCE_INLINE_ real_t dot(const Vector3 &p_with) const; Basis outer(const Vector3 &p_with) const; + _FORCE_INLINE_ Vector3 get_any_perpendicular() const; _FORCE_INLINE_ Vector3 abs() const; _FORCE_INLINE_ Vector3 floor() const; @@ -142,7 +144,7 @@ struct [[nodiscard]] Vector3 { _FORCE_INLINE_ real_t distance_to(const Vector3 &p_to) const; _FORCE_INLINE_ real_t distance_squared_to(const Vector3 &p_to) const; - _FORCE_INLINE_ Vector3 posmod(const real_t p_mod) const; + _FORCE_INLINE_ Vector3 posmod(real_t p_mod) const; _FORCE_INLINE_ Vector3 posmodv(const Vector3 &p_modv) const; _FORCE_INLINE_ Vector3 project(const Vector3 &p_to) const; @@ -169,10 +171,10 @@ struct [[nodiscard]] Vector3 { _FORCE_INLINE_ Vector3 &operator/=(const Vector3 &p_v); _FORCE_INLINE_ Vector3 operator/(const Vector3 &p_v) const; - _FORCE_INLINE_ Vector3 &operator*=(const real_t p_scalar); - _FORCE_INLINE_ Vector3 operator*(const real_t p_scalar) const; - _FORCE_INLINE_ Vector3 &operator/=(const real_t p_scalar); - _FORCE_INLINE_ Vector3 operator/(const real_t p_scalar) const; + _FORCE_INLINE_ Vector3 &operator*=(real_t p_scalar); + _FORCE_INLINE_ Vector3 operator*(real_t p_scalar) const; + _FORCE_INLINE_ Vector3 &operator/=(real_t p_scalar); + _FORCE_INLINE_ Vector3 operator/(real_t p_scalar) const; _FORCE_INLINE_ Vector3 operator-() const; @@ -187,7 +189,7 @@ struct [[nodiscard]] Vector3 { operator Vector3i() const; _FORCE_INLINE_ Vector3() {} - _FORCE_INLINE_ Vector3(const real_t p_x, const real_t p_y, const real_t p_z) { + _FORCE_INLINE_ Vector3(real_t p_x, real_t p_y, real_t p_z) { x = p_x; y = p_y; z = p_z; @@ -227,14 +229,15 @@ Vector3 Vector3::round() const { return Vector3(Math::round(x), Math::round(y), Math::round(z)); } -Vector3 Vector3::lerp(const Vector3 &p_to, const real_t p_weight) const { - return Vector3( - x + (p_weight * (p_to.x - x)), - y + (p_weight * (p_to.y - y)), - z + (p_weight * (p_to.z - z))); +Vector3 Vector3::lerp(const Vector3 &p_to, real_t p_weight) const { + Vector3 res = *this; + res.x = Math::lerp(res.x, p_to.x, p_weight); + res.y = Math::lerp(res.y, p_to.y, p_weight); + res.z = Math::lerp(res.z, p_to.z, p_weight); + return res; } -Vector3 Vector3::slerp(const Vector3 &p_to, const real_t p_weight) const { +Vector3 Vector3::slerp(const Vector3 &p_to, real_t p_weight) const { // This method seems more complicated than it really is, since we write out // the internals of some methods for efficiency (mainly, checking length). real_t start_length_sq = length_squared(); @@ -256,7 +259,7 @@ Vector3 Vector3::slerp(const Vector3 &p_to, const real_t p_weight) const { return rotated(axis, angle * p_weight) * (result_length / start_length); } -Vector3 Vector3::cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight) const { +Vector3 Vector3::cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_weight) const { Vector3 res = *this; res.x = Math::cubic_interpolate(res.x, p_b.x, p_pre_a.x, p_post_b.x, p_weight); res.y = Math::cubic_interpolate(res.y, p_b.y, p_pre_a.y, p_post_b.y, p_weight); @@ -264,7 +267,7 @@ Vector3 Vector3::cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, c return res; } -Vector3 Vector3::cubic_interpolate_in_time(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const { +Vector3 Vector3::cubic_interpolate_in_time(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_weight, real_t p_b_t, real_t p_pre_a_t, real_t p_post_b_t) const { Vector3 res = *this; res.x = Math::cubic_interpolate_in_time(res.x, p_b.x, p_pre_a.x, p_post_b.x, p_weight, p_b_t, p_pre_a_t, p_post_b_t); res.y = Math::cubic_interpolate_in_time(res.y, p_b.y, p_pre_a.y, p_post_b.y, p_weight, p_b_t, p_pre_a_t, p_post_b_t); @@ -272,17 +275,20 @@ Vector3 Vector3::cubic_interpolate_in_time(const Vector3 &p_b, const Vector3 &p_ return res; } -Vector3 Vector3::bezier_interpolate(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const { +Vector3 Vector3::bezier_interpolate(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, real_t p_t) const { Vector3 res = *this; + res.x = Math::bezier_interpolate(res.x, p_control_1.x, p_control_2.x, p_end.x, p_t); + res.y = Math::bezier_interpolate(res.y, p_control_1.y, p_control_2.y, p_end.y, p_t); + res.z = Math::bezier_interpolate(res.z, p_control_1.z, p_control_2.z, p_end.z, p_t); + return res; +} - /* Formula from Wikipedia article on Bezier curves. */ - real_t omt = (1.0 - p_t); - real_t omt2 = omt * omt; - real_t omt3 = omt2 * omt; - real_t t2 = p_t * p_t; - real_t t3 = t2 * p_t; - - return res * omt3 + p_control_1 * omt2 * p_t * 3.0 + p_control_2 * omt * t2 * 3.0 + p_end * t3; +Vector3 Vector3::bezier_derivative(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, real_t p_t) const { + Vector3 res = *this; + res.x = Math::bezier_derivative(res.x, p_control_1.x, p_control_2.x, p_end.x, p_t); + res.y = Math::bezier_derivative(res.y, p_control_1.y, p_control_2.y, p_end.y, p_t); + res.z = Math::bezier_derivative(res.z, p_control_1.z, p_control_2.z, p_end.z, p_t); + return res; } real_t Vector3::distance_to(const Vector3 &p_to) const { @@ -293,7 +299,7 @@ real_t Vector3::distance_squared_to(const Vector3 &p_to) const { return (p_to - *this).length_squared(); } -Vector3 Vector3::posmod(const real_t p_mod) const { +Vector3 Vector3::posmod(real_t p_mod) const { return Vector3(Math::fposmod(x, p_mod), Math::fposmod(y, p_mod), Math::fposmod(z, p_mod)); } @@ -322,6 +328,16 @@ Vector3 Vector3::direction_to(const Vector3 &p_to) const { return ret; } +Vector3 Vector3::get_any_perpendicular() const { + // Return the any perpendicular vector by cross product with the Vector3.RIGHT or Vector3.UP, + // whichever has the greater angle to the current vector with the sign of each element positive. + // The only essence is "to avoid being parallel to the current vector", and there is no mathematical basis for using Vector3.RIGHT and Vector3.UP, + // since it could be a different vector depending on the prior branching code Math::abs(x) <= Math::abs(y) && Math::abs(x) <= Math::abs(z). + // However, it would be reasonable to use any of the axes of the basis, as it is simpler to calculate. + ERR_FAIL_COND_V_MSG(is_zero_approx(), Vector3(0, 0, 0), "The Vector3 must not be zero."); + return cross((Math::abs(x) <= Math::abs(y) && Math::abs(x) <= Math::abs(z)) ? Vector3(1, 0, 0) : Vector3(0, 1, 0)).normalized(); +} + /* Operators */ Vector3 &Vector3::operator+=(const Vector3 &p_v) { @@ -368,7 +384,7 @@ Vector3 Vector3::operator/(const Vector3 &p_v) const { return Vector3(x / p_v.x, y / p_v.y, z / p_v.z); } -Vector3 &Vector3::operator*=(const real_t p_scalar) { +Vector3 &Vector3::operator*=(real_t p_scalar) { x *= p_scalar; y *= p_scalar; z *= p_scalar; @@ -378,34 +394,34 @@ Vector3 &Vector3::operator*=(const real_t p_scalar) { // Multiplication operators required to workaround issues with LLVM using implicit conversion // to Vector3i instead for integers where it should not. -_FORCE_INLINE_ Vector3 operator*(const float p_scalar, const Vector3 &p_vec) { +_FORCE_INLINE_ Vector3 operator*(float p_scalar, const Vector3 &p_vec) { return p_vec * p_scalar; } -_FORCE_INLINE_ Vector3 operator*(const double p_scalar, const Vector3 &p_vec) { +_FORCE_INLINE_ Vector3 operator*(double p_scalar, const Vector3 &p_vec) { return p_vec * p_scalar; } -_FORCE_INLINE_ Vector3 operator*(const int32_t p_scalar, const Vector3 &p_vec) { +_FORCE_INLINE_ Vector3 operator*(int32_t p_scalar, const Vector3 &p_vec) { return p_vec * p_scalar; } -_FORCE_INLINE_ Vector3 operator*(const int64_t p_scalar, const Vector3 &p_vec) { +_FORCE_INLINE_ Vector3 operator*(int64_t p_scalar, const Vector3 &p_vec) { return p_vec * p_scalar; } -Vector3 Vector3::operator*(const real_t p_scalar) const { +Vector3 Vector3::operator*(real_t p_scalar) const { return Vector3(x * p_scalar, y * p_scalar, z * p_scalar); } -Vector3 &Vector3::operator/=(const real_t p_scalar) { +Vector3 &Vector3::operator/=(real_t p_scalar) { x /= p_scalar; y /= p_scalar; z /= p_scalar; return *this; } -Vector3 Vector3::operator/(const real_t p_scalar) const { +Vector3 Vector3::operator/(real_t p_scalar) const { return Vector3(x / p_scalar, y / p_scalar, z / p_scalar); } @@ -519,9 +535,9 @@ void Vector3::zero() { // slide returns the component of the vector along the given plane, specified by its normal vector. Vector3 Vector3::slide(const Vector3 &p_normal) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 must be normalized."); + ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 " + p_normal.operator String() + " must be normalized."); #endif - return *this - p_normal * this->dot(p_normal); + return *this - p_normal * dot(p_normal); } Vector3 Vector3::bounce(const Vector3 &p_normal) const { @@ -530,9 +546,9 @@ Vector3 Vector3::bounce(const Vector3 &p_normal) const { Vector3 Vector3::reflect(const Vector3 &p_normal) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 must be normalized."); + ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 " + p_normal.operator String() + " must be normalized."); #endif - return 2.0f * p_normal * this->dot(p_normal) - *this; + return 2.0f * p_normal * dot(p_normal) - *this; } } // namespace godot diff --git a/include/godot_cpp/variant/vector3i.hpp b/include/godot_cpp/variant/vector3i.hpp index 15bc3bde7..2901b3665 100644 --- a/include/godot_cpp/variant/vector3i.hpp +++ b/include/godot_cpp/variant/vector3i.hpp @@ -57,12 +57,12 @@ struct [[nodiscard]] Vector3i { int32_t coord[3] = { 0 }; }; - _FORCE_INLINE_ const int32_t &operator[](const int p_axis) const { + _FORCE_INLINE_ const int32_t &operator[](int p_axis) const { DEV_ASSERT((unsigned int)p_axis < 3); return coord[p_axis]; } - _FORCE_INLINE_ int32_t &operator[](const int p_axis) { + _FORCE_INLINE_ int32_t &operator[](int p_axis) { DEV_ASSERT((unsigned int)p_axis < 3); return coord[p_axis]; } @@ -89,17 +89,17 @@ struct [[nodiscard]] Vector3i { _FORCE_INLINE_ int64_t length_squared() const; _FORCE_INLINE_ double length() const; - _FORCE_INLINE_ int64_t distance_squared_to(const Vector3i &p_to) const; - _FORCE_INLINE_ double distance_to(const Vector3i &p_to) const; - _FORCE_INLINE_ void zero(); _FORCE_INLINE_ Vector3i abs() const; _FORCE_INLINE_ Vector3i sign() const; - Vector3i snapped(const Vector3i &p_step) const; - Vector3i snappedi(int32_t p_step) const; Vector3i clamp(const Vector3i &p_min, const Vector3i &p_max) const; Vector3i clampi(int32_t p_min, int32_t p_max) const; + Vector3i snapped(const Vector3i &p_step) const; + Vector3i snappedi(int32_t p_step) const; + + _FORCE_INLINE_ double distance_to(const Vector3i &p_to) const; + _FORCE_INLINE_ int64_t distance_squared_to(const Vector3i &p_to) const; /* Operators */ @@ -114,12 +114,12 @@ struct [[nodiscard]] Vector3i { _FORCE_INLINE_ Vector3i &operator%=(const Vector3i &p_v); _FORCE_INLINE_ Vector3i operator%(const Vector3i &p_v) const; - _FORCE_INLINE_ Vector3i &operator*=(const int32_t p_scalar); - _FORCE_INLINE_ Vector3i operator*(const int32_t p_scalar) const; - _FORCE_INLINE_ Vector3i &operator/=(const int32_t p_scalar); - _FORCE_INLINE_ Vector3i operator/(const int32_t p_scalar) const; - _FORCE_INLINE_ Vector3i &operator%=(const int32_t p_scalar); - _FORCE_INLINE_ Vector3i operator%(const int32_t p_scalar) const; + _FORCE_INLINE_ Vector3i &operator*=(int32_t p_scalar); + _FORCE_INLINE_ Vector3i operator*(int32_t p_scalar) const; + _FORCE_INLINE_ Vector3i &operator/=(int32_t p_scalar); + _FORCE_INLINE_ Vector3i operator/(int32_t p_scalar) const; + _FORCE_INLINE_ Vector3i &operator%=(int32_t p_scalar); + _FORCE_INLINE_ Vector3i operator%(int32_t p_scalar) const; _FORCE_INLINE_ Vector3i operator-() const; @@ -134,7 +134,7 @@ struct [[nodiscard]] Vector3i { operator Vector3() const; _FORCE_INLINE_ Vector3i() {} - _FORCE_INLINE_ Vector3i(const int32_t p_x, const int32_t p_y, const int32_t p_z) { + _FORCE_INLINE_ Vector3i(int32_t p_x, int32_t p_y, int32_t p_z) { x = p_x; y = p_y; z = p_z; @@ -149,14 +149,6 @@ double Vector3i::length() const { return Math::sqrt((double)length_squared()); } -int64_t Vector3i::distance_squared_to(const Vector3i &p_to) const { - return (p_to - *this).length_squared(); -} - -double Vector3i::distance_to(const Vector3i &p_to) const { - return (p_to - *this).length(); -} - Vector3i Vector3i::abs() const { return Vector3i(Math::abs(x), Math::abs(y), Math::abs(z)); } @@ -165,6 +157,14 @@ Vector3i Vector3i::sign() const { return Vector3i(SIGN(x), SIGN(y), SIGN(z)); } +double Vector3i::distance_to(const Vector3i &p_to) const { + return (p_to - *this).length(); +} + +int64_t Vector3i::distance_squared_to(const Vector3i &p_to) const { + return (p_to - *this).length_squared(); +} + /* Operators */ Vector3i &Vector3i::operator+=(const Vector3i &p_v) { @@ -222,54 +222,54 @@ Vector3i Vector3i::operator%(const Vector3i &p_v) const { return Vector3i(x % p_v.x, y % p_v.y, z % p_v.z); } -Vector3i &Vector3i::operator*=(const int32_t p_scalar) { +Vector3i &Vector3i::operator*=(int32_t p_scalar) { x *= p_scalar; y *= p_scalar; z *= p_scalar; return *this; } -Vector3i Vector3i::operator*(const int32_t p_scalar) const { +Vector3i Vector3i::operator*(int32_t p_scalar) const { return Vector3i(x * p_scalar, y * p_scalar, z * p_scalar); } // Multiplication operators required to workaround issues with LLVM using implicit conversion. -_FORCE_INLINE_ Vector3i operator*(const int32_t p_scalar, const Vector3i &p_vector) { +_FORCE_INLINE_ Vector3i operator*(int32_t p_scalar, const Vector3i &p_vector) { return p_vector * p_scalar; } -_FORCE_INLINE_ Vector3i operator*(const int64_t p_scalar, const Vector3i &p_vector) { +_FORCE_INLINE_ Vector3i operator*(int64_t p_scalar, const Vector3i &p_vector) { return p_vector * p_scalar; } -_FORCE_INLINE_ Vector3i operator*(const float p_scalar, const Vector3i &p_vector) { +_FORCE_INLINE_ Vector3i operator*(float p_scalar, const Vector3i &p_vector) { return p_vector * p_scalar; } -_FORCE_INLINE_ Vector3i operator*(const double p_scalar, const Vector3i &p_vector) { +_FORCE_INLINE_ Vector3i operator*(double p_scalar, const Vector3i &p_vector) { return p_vector * p_scalar; } -Vector3i &Vector3i::operator/=(const int32_t p_scalar) { +Vector3i &Vector3i::operator/=(int32_t p_scalar) { x /= p_scalar; y /= p_scalar; z /= p_scalar; return *this; } -Vector3i Vector3i::operator/(const int32_t p_scalar) const { +Vector3i Vector3i::operator/(int32_t p_scalar) const { return Vector3i(x / p_scalar, y / p_scalar, z / p_scalar); } -Vector3i &Vector3i::operator%=(const int32_t p_scalar) { +Vector3i &Vector3i::operator%=(int32_t p_scalar) { x %= p_scalar; y %= p_scalar; z %= p_scalar; return *this; } -Vector3i Vector3i::operator%(const int32_t p_scalar) const { +Vector3i Vector3i::operator%(int32_t p_scalar) const { return Vector3i(x % p_scalar, y % p_scalar, z % p_scalar); } diff --git a/include/godot_cpp/variant/vector4.hpp b/include/godot_cpp/variant/vector4.hpp index 1f5ff5595..3348f6111 100644 --- a/include/godot_cpp/variant/vector4.hpp +++ b/include/godot_cpp/variant/vector4.hpp @@ -36,6 +36,7 @@ namespace godot { class String; +struct Vector4i; struct [[nodiscard]] Vector4 { static const int AXIS_COUNT = 4; @@ -54,15 +55,14 @@ struct [[nodiscard]] Vector4 { real_t z; real_t w; }; - [[deprecated("Use coord instead")]] real_t components[4]; real_t coord[4] = { 0, 0, 0, 0 }; }; - _FORCE_INLINE_ real_t &operator[](const int p_axis) { + _FORCE_INLINE_ real_t &operator[](int p_axis) { DEV_ASSERT((unsigned int)p_axis < 4); return coord[p_axis]; } - _FORCE_INLINE_ const real_t &operator[](const int p_axis) const { + _FORCE_INLINE_ const real_t &operator[](int p_axis) const { DEV_ASSERT((unsigned int)p_axis < 4); return coord[p_axis]; } @@ -104,11 +104,11 @@ struct [[nodiscard]] Vector4 { Vector4 floor() const; Vector4 ceil() const; Vector4 round() const; - Vector4 lerp(const Vector4 &p_to, const real_t p_weight) const; - Vector4 cubic_interpolate(const Vector4 &p_b, const Vector4 &p_pre_a, const Vector4 &p_post_b, const real_t p_weight) const; - Vector4 cubic_interpolate_in_time(const Vector4 &p_b, const Vector4 &p_pre_a, const Vector4 &p_post_b, const real_t p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const; + Vector4 lerp(const Vector4 &p_to, real_t p_weight) const; + Vector4 cubic_interpolate(const Vector4 &p_b, const Vector4 &p_pre_a, const Vector4 &p_post_b, real_t p_weight) const; + Vector4 cubic_interpolate_in_time(const Vector4 &p_b, const Vector4 &p_pre_a, const Vector4 &p_post_b, real_t p_weight, real_t p_b_t, real_t p_pre_a_t, real_t p_post_b_t) const; - Vector4 posmod(const real_t p_mod) const; + Vector4 posmod(real_t p_mod) const; Vector4 posmodv(const Vector4 &p_modv) const; void snap(const Vector4 &p_step); void snapf(real_t p_step); @@ -124,15 +124,15 @@ struct [[nodiscard]] Vector4 { _FORCE_INLINE_ void operator-=(const Vector4 &p_vec4); _FORCE_INLINE_ void operator*=(const Vector4 &p_vec4); _FORCE_INLINE_ void operator/=(const Vector4 &p_vec4); - _FORCE_INLINE_ void operator*=(const real_t &s); - _FORCE_INLINE_ void operator/=(const real_t &s); + _FORCE_INLINE_ void operator*=(real_t p_s); + _FORCE_INLINE_ void operator/=(real_t p_s); _FORCE_INLINE_ Vector4 operator+(const Vector4 &p_vec4) const; _FORCE_INLINE_ Vector4 operator-(const Vector4 &p_vec4) const; _FORCE_INLINE_ Vector4 operator*(const Vector4 &p_vec4) const; _FORCE_INLINE_ Vector4 operator/(const Vector4 &p_vec4) const; _FORCE_INLINE_ Vector4 operator-() const; - _FORCE_INLINE_ Vector4 operator*(const real_t &s) const; - _FORCE_INLINE_ Vector4 operator/(const real_t &s) const; + _FORCE_INLINE_ Vector4 operator*(real_t p_s) const; + _FORCE_INLINE_ Vector4 operator/(real_t p_s) const; _FORCE_INLINE_ bool operator==(const Vector4 &p_vec4) const; _FORCE_INLINE_ bool operator!=(const Vector4 &p_vec4) const; @@ -142,28 +142,14 @@ struct [[nodiscard]] Vector4 { _FORCE_INLINE_ bool operator<=(const Vector4 &p_vec4) const; operator String() const; + operator Vector4i() const; _FORCE_INLINE_ Vector4() {} - - _FORCE_INLINE_ Vector4(real_t p_x, real_t p_y, real_t p_z, real_t p_w) : - x(p_x), - y(p_y), - z(p_z), - w(p_w) { - } - - Vector4(const Vector4 &p_vec4) : - x(p_vec4.x), - y(p_vec4.y), - z(p_vec4.z), - w(p_vec4.w) { - } - - void operator=(const Vector4 &p_vec4) { - x = p_vec4.x; - y = p_vec4.y; - z = p_vec4.z; - w = p_vec4.w; + _FORCE_INLINE_ Vector4(real_t p_x, real_t p_y, real_t p_z, real_t p_w) { + x = p_x; + y = p_y; + z = p_z; + w = p_w; } }; @@ -202,15 +188,15 @@ void Vector4::operator/=(const Vector4 &p_vec4) { z /= p_vec4.z; w /= p_vec4.w; } -void Vector4::operator*=(const real_t &s) { - x *= s; - y *= s; - z *= s; - w *= s; +void Vector4::operator*=(real_t p_s) { + x *= p_s; + y *= p_s; + z *= p_s; + w *= p_s; } -void Vector4::operator/=(const real_t &s) { - *this *= 1.0f / s; +void Vector4::operator/=(real_t p_s) { + *this *= 1.0f / p_s; } Vector4 Vector4::operator+(const Vector4 &p_vec4) const { @@ -233,12 +219,12 @@ Vector4 Vector4::operator-() const { return Vector4(-x, -y, -z, -w); } -Vector4 Vector4::operator*(const real_t &s) const { - return Vector4(x * s, y * s, z * s, w * s); +Vector4 Vector4::operator*(real_t p_s) const { + return Vector4(x * p_s, y * p_s, z * p_s, w * p_s); } -Vector4 Vector4::operator/(const real_t &s) const { - return *this * (1.0f / s); +Vector4 Vector4::operator/(real_t p_s) const { + return *this * (1.0f / p_s); } bool Vector4::operator==(const Vector4 &p_vec4) const { @@ -301,19 +287,19 @@ bool Vector4::operator>=(const Vector4 &p_v) const { return x > p_v.x; } -_FORCE_INLINE_ Vector4 operator*(const float p_scalar, const Vector4 &p_vec) { +_FORCE_INLINE_ Vector4 operator*(float p_scalar, const Vector4 &p_vec) { return p_vec * p_scalar; } -_FORCE_INLINE_ Vector4 operator*(const double p_scalar, const Vector4 &p_vec) { +_FORCE_INLINE_ Vector4 operator*(double p_scalar, const Vector4 &p_vec) { return p_vec * p_scalar; } -_FORCE_INLINE_ Vector4 operator*(const int32_t p_scalar, const Vector4 &p_vec) { +_FORCE_INLINE_ Vector4 operator*(int32_t p_scalar, const Vector4 &p_vec) { return p_vec * p_scalar; } -_FORCE_INLINE_ Vector4 operator*(const int64_t p_scalar, const Vector4 &p_vec) { +_FORCE_INLINE_ Vector4 operator*(int64_t p_scalar, const Vector4 &p_vec) { return p_vec * p_scalar; } diff --git a/include/godot_cpp/variant/vector4i.hpp b/include/godot_cpp/variant/vector4i.hpp index 285feeaf9..1a7471af6 100644 --- a/include/godot_cpp/variant/vector4i.hpp +++ b/include/godot_cpp/variant/vector4i.hpp @@ -59,12 +59,12 @@ struct [[nodiscard]] Vector4i { int32_t coord[4] = { 0 }; }; - _FORCE_INLINE_ const int32_t &operator[](const int p_axis) const { + _FORCE_INLINE_ const int32_t &operator[](int p_axis) const { DEV_ASSERT((unsigned int)p_axis < 4); return coord[p_axis]; } - _FORCE_INLINE_ int32_t &operator[](const int p_axis) { + _FORCE_INLINE_ int32_t &operator[](int p_axis) { DEV_ASSERT((unsigned int)p_axis < 4); return coord[p_axis]; } @@ -91,17 +91,17 @@ struct [[nodiscard]] Vector4i { _FORCE_INLINE_ int64_t length_squared() const; _FORCE_INLINE_ double length() const; - _FORCE_INLINE_ int64_t distance_squared_to(const Vector4i &p_to) const; - _FORCE_INLINE_ double distance_to(const Vector4i &p_to) const; - _FORCE_INLINE_ void zero(); + _FORCE_INLINE_ double distance_to(const Vector4i &p_to) const; + _FORCE_INLINE_ int64_t distance_squared_to(const Vector4i &p_to) const; + _FORCE_INLINE_ Vector4i abs() const; _FORCE_INLINE_ Vector4i sign() const; - Vector4i snapped(const Vector4i &p_step) const; - Vector4i snappedi(int32_t p_step) const; Vector4i clamp(const Vector4i &p_min, const Vector4i &p_max) const; Vector4i clampi(int32_t p_min, int32_t p_max) const; + Vector4i snapped(const Vector4i &p_step) const; + Vector4i snappedi(int32_t p_step) const; /* Operators */ @@ -116,12 +116,12 @@ struct [[nodiscard]] Vector4i { _FORCE_INLINE_ Vector4i &operator%=(const Vector4i &p_v); _FORCE_INLINE_ Vector4i operator%(const Vector4i &p_v) const; - _FORCE_INLINE_ Vector4i &operator*=(const int32_t p_scalar); - _FORCE_INLINE_ Vector4i operator*(const int32_t p_scalar) const; - _FORCE_INLINE_ Vector4i &operator/=(const int32_t p_scalar); - _FORCE_INLINE_ Vector4i operator/(const int32_t p_scalar) const; - _FORCE_INLINE_ Vector4i &operator%=(const int32_t p_scalar); - _FORCE_INLINE_ Vector4i operator%(const int32_t p_scalar) const; + _FORCE_INLINE_ Vector4i &operator*=(int32_t p_scalar); + _FORCE_INLINE_ Vector4i operator*(int32_t p_scalar) const; + _FORCE_INLINE_ Vector4i &operator/=(int32_t p_scalar); + _FORCE_INLINE_ Vector4i operator/(int32_t p_scalar) const; + _FORCE_INLINE_ Vector4i &operator%=(int32_t p_scalar); + _FORCE_INLINE_ Vector4i operator%(int32_t p_scalar) const; _FORCE_INLINE_ Vector4i operator-() const; @@ -137,7 +137,7 @@ struct [[nodiscard]] Vector4i { _FORCE_INLINE_ Vector4i() {} Vector4i(const Vector4 &p_vec4); - _FORCE_INLINE_ Vector4i(const int32_t p_x, const int32_t p_y, const int32_t p_z, const int32_t p_w) { + _FORCE_INLINE_ Vector4i(int32_t p_x, int32_t p_y, int32_t p_z, int32_t p_w) { x = p_x; y = p_y; z = p_z; @@ -153,20 +153,20 @@ double Vector4i::length() const { return Math::sqrt((double)length_squared()); } -int64_t Vector4i::distance_squared_to(const Vector4i &p_to) const { - return (p_to - *this).length_squared(); -} - double Vector4i::distance_to(const Vector4i &p_to) const { return (p_to - *this).length(); } +int64_t Vector4i::distance_squared_to(const Vector4i &p_to) const { + return (p_to - *this).length_squared(); +} + Vector4i Vector4i::abs() const { return Vector4i(Math::abs(x), Math::abs(y), Math::abs(z), Math::abs(w)); } Vector4i Vector4i::sign() const { - return Vector4i(Math::sign(x), Math::sign(y), Math::sign(z), Math::sign(w)); + return Vector4i(SIGN(x), SIGN(y), SIGN(z), SIGN(w)); } /* Operators */ @@ -231,7 +231,7 @@ Vector4i Vector4i::operator%(const Vector4i &p_v) const { return Vector4i(x % p_v.x, y % p_v.y, z % p_v.z, w % p_v.w); } -Vector4i &Vector4i::operator*=(const int32_t p_scalar) { +Vector4i &Vector4i::operator*=(int32_t p_scalar) { x *= p_scalar; y *= p_scalar; z *= p_scalar; @@ -239,29 +239,29 @@ Vector4i &Vector4i::operator*=(const int32_t p_scalar) { return *this; } -Vector4i Vector4i::operator*(const int32_t p_scalar) const { +Vector4i Vector4i::operator*(int32_t p_scalar) const { return Vector4i(x * p_scalar, y * p_scalar, z * p_scalar, w * p_scalar); } // Multiplication operators required to workaround issues with LLVM using implicit conversion. -_FORCE_INLINE_ Vector4i operator*(const int32_t p_scalar, const Vector4i &p_vector) { +_FORCE_INLINE_ Vector4i operator*(int32_t p_scalar, const Vector4i &p_vector) { return p_vector * p_scalar; } -_FORCE_INLINE_ Vector4i operator*(const int64_t p_scalar, const Vector4i &p_vector) { +_FORCE_INLINE_ Vector4i operator*(int64_t p_scalar, const Vector4i &p_vector) { return p_vector * p_scalar; } -_FORCE_INLINE_ Vector4i operator*(const float p_scalar, const Vector4i &p_vector) { +_FORCE_INLINE_ Vector4i operator*(float p_scalar, const Vector4i &p_vector) { return p_vector * p_scalar; } -_FORCE_INLINE_ Vector4i operator*(const double p_scalar, const Vector4i &p_vector) { +_FORCE_INLINE_ Vector4i operator*(double p_scalar, const Vector4i &p_vector) { return p_vector * p_scalar; } -Vector4i &Vector4i::operator/=(const int32_t p_scalar) { +Vector4i &Vector4i::operator/=(int32_t p_scalar) { x /= p_scalar; y /= p_scalar; z /= p_scalar; @@ -269,11 +269,11 @@ Vector4i &Vector4i::operator/=(const int32_t p_scalar) { return *this; } -Vector4i Vector4i::operator/(const int32_t p_scalar) const { +Vector4i Vector4i::operator/(int32_t p_scalar) const { return Vector4i(x / p_scalar, y / p_scalar, z / p_scalar, w / p_scalar); } -Vector4i &Vector4i::operator%=(const int32_t p_scalar) { +Vector4i &Vector4i::operator%=(int32_t p_scalar) { x %= p_scalar; y %= p_scalar; z %= p_scalar; @@ -281,7 +281,7 @@ Vector4i &Vector4i::operator%=(const int32_t p_scalar) { return *this; } -Vector4i Vector4i::operator%(const int32_t p_scalar) const { +Vector4i Vector4i::operator%(int32_t p_scalar) const { return Vector4i(x % p_scalar, y % p_scalar, z % p_scalar, w % p_scalar); } diff --git a/src/variant/aabb.cpp b/src/variant/aabb.cpp index ded17d2ba..c0ac63899 100644 --- a/src/variant/aabb.cpp +++ b/src/variant/aabb.cpp @@ -119,55 +119,75 @@ AABB AABB::intersection(const AABB &p_aabb) const { return AABB(min, max - min); } -bool AABB::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *r_clip, Vector3 *r_normal) const { +// Note that this routine returns the BACKTRACKED (i.e. behind the ray origin) +// intersection point + normal if INSIDE the AABB. +// The caller can therefore decide when INSIDE whether to use the +// backtracked intersection, or use p_from as the intersection, and +// carry on progressing without e.g. reflecting against the normal. +bool AABB::find_intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, bool &r_inside, Vector3 *r_intersection_point, Vector3 *r_normal) const { #ifdef MATH_CHECKS if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) { ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size."); } #endif - Vector3 c1, c2; Vector3 end = position + size; - real_t near = -1e20; - real_t far = 1e20; + real_t tmin = -1e20; + real_t tmax = 1e20; int axis = 0; + // Make sure r_inside is always initialized, + // to prevent reading uninitialized data in the client code. + r_inside = false; + for (int i = 0; i < 3; i++) { if (p_dir[i] == 0) { if ((p_from[i] < position[i]) || (p_from[i] > end[i])) { return false; } } else { // ray not parallel to planes in this direction - c1[i] = (position[i] - p_from[i]) / p_dir[i]; - c2[i] = (end[i] - p_from[i]) / p_dir[i]; + real_t t1 = (position[i] - p_from[i]) / p_dir[i]; + real_t t2 = (end[i] - p_from[i]) / p_dir[i]; - if (c1[i] > c2[i]) { - SWAP(c1, c2); + if (t1 > t2) { + SWAP(t1, t2); } - if (c1[i] > near) { - near = c1[i]; + if (t1 >= tmin) { + tmin = t1; axis = i; } - if (c2[i] < far) { - far = c2[i]; + if (t2 < tmax) { + if (t2 < 0) { + return false; + } + tmax = t2; } - if ((near > far) || (far < 0)) { + if (tmin > tmax) { return false; } } } - if (r_clip) { - *r_clip = c1; + // Did the ray start from inside the box? + // In which case the intersection returned is the point of entry + // (behind the ray start) or the calling routine can use the ray origin as intersection point. + r_inside = tmin < 0; + + if (r_intersection_point) { + *r_intersection_point = p_from + p_dir * tmin; + + // Prevent float error by making sure the point is exactly + // on the AABB border on the relevant axis. + r_intersection_point->coord[axis] = (p_dir[axis] >= 0) ? position.coord[axis] : end.coord[axis]; } if (r_normal) { *r_normal = Vector3(); - (*r_normal)[axis] = p_dir[axis] ? -1 : 1; + (*r_normal)[axis] = (p_dir[axis] >= 0) ? -1 : 1; } return true; } -bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_clip, Vector3 *r_normal) const { +bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_intersection_point, Vector3 *r_normal) const { #ifdef MATH_CHECKS if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) { ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size."); @@ -225,8 +245,8 @@ bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector *r_normal = normal; } - if (r_clip) { - *r_clip = p_from + rel * min; + if (r_intersection_point) { + *r_intersection_point = p_from + rel * min; } return true; @@ -412,7 +432,15 @@ Variant AABB::intersects_segment_bind(const Vector3 &p_from, const Vector3 &p_to Variant AABB::intersects_ray_bind(const Vector3 &p_from, const Vector3 &p_dir) const { Vector3 inters; - if (intersects_ray(p_from, p_dir, &inters)) { + bool inside = false; + + if (find_intersects_ray(p_from, p_dir, inside, &inters)) { + // When inside the intersection point may be BEHIND the ray, + // so for general use we return the ray origin. + if (inside) { + return p_from; + } + return inters; } return Variant(); diff --git a/src/variant/basis.cpp b/src/variant/basis.cpp index d8a991917..67cbb3aca 100644 --- a/src/variant/basis.cpp +++ b/src/variant/basis.cpp @@ -29,31 +29,17 @@ /**************************************************************************/ #include +#include #include #include +using namespace godot; + #define cofac(row1, col1, row2, col2) \ (rows[row1][col1] * rows[row2][col2] - rows[row1][col2] * rows[row2][col1]) namespace godot { -void Basis::from_z(const Vector3 &p_z) { - if (Math::abs(p_z.z) > (real_t)Math_SQRT12) { - // choose p in y-z plane - real_t a = p_z[1] * p_z[1] + p_z[2] * p_z[2]; - real_t k = 1.0f / Math::sqrt(a); - rows[0] = Vector3(0, -p_z[2] * k, p_z[1] * k); - rows[1] = Vector3(a * k, -p_z[0] * rows[0][2], p_z[0] * rows[0][1]); - } else { - // choose p in x-y plane - real_t a = p_z.x * p_z.x + p_z.y * p_z.y; - real_t k = 1.0f / Math::sqrt(a); - rows[0] = Vector3(-p_z.y * k, p_z.x * k, 0); - rows[1] = Vector3(-p_z.z * rows[0].y, p_z.z * rows[0].x, a * k); - } - rows[2] = p_z; -} - void Basis::invert() { real_t co[3] = { cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1) @@ -107,13 +93,35 @@ Basis Basis::orthogonalized() const { return c; } +// Returns true if the basis vectors are orthogonal (perpendicular), so it has no skew or shear, and can be decomposed into rotation and scale. +// See https://en.wikipedia.org/wiki/Orthogonal_basis bool Basis::is_orthogonal() const { - Basis identity; - Basis m = (*this) * transposed(); + const Vector3 x = get_column(0); + const Vector3 y = get_column(1); + const Vector3 z = get_column(2); + return Math::is_zero_approx(x.dot(y)) && Math::is_zero_approx(x.dot(z)) && Math::is_zero_approx(y.dot(z)); +} - return m.is_equal_approx(identity); +// Returns true if the basis vectors are orthonormal (orthogonal and normalized), so it has no scale, skew, or shear. +// See https://en.wikipedia.org/wiki/Orthonormal_basis +bool Basis::is_orthonormal() const { + const Vector3 x = get_column(0); + const Vector3 y = get_column(1); + const Vector3 z = get_column(2); + return Math::is_equal_approx(x.length_squared(), 1) && Math::is_equal_approx(y.length_squared(), 1) && Math::is_equal_approx(z.length_squared(), 1) && Math::is_zero_approx(x.dot(y)) && Math::is_zero_approx(x.dot(z)) && Math::is_zero_approx(y.dot(z)); } +// Returns true if the basis is conformal (orthogonal, uniform scale, preserves angles and distance ratios). +// See https://en.wikipedia.org/wiki/Conformal_linear_transformation +bool Basis::is_conformal() const { + const Vector3 x = get_column(0); + const Vector3 y = get_column(1); + const Vector3 z = get_column(2); + const real_t x_len_sq = x.length_squared(); + return Math::is_equal_approx(x_len_sq, y.length_squared()) && Math::is_equal_approx(x_len_sq, z.length_squared()) && Math::is_zero_approx(x.dot(y)) && Math::is_zero_approx(x.dot(z)) && Math::is_zero_approx(y.dot(z)); +} + +// Returns true if the basis only has diagonal elements, so it may only have scale or flip, but no rotation, skew, or shear. bool Basis::is_diagonal() const { return ( Math::is_zero_approx(rows[0][1]) && Math::is_zero_approx(rows[0][2]) && @@ -121,8 +129,9 @@ bool Basis::is_diagonal() const { Math::is_zero_approx(rows[2][0]) && Math::is_zero_approx(rows[2][1])); } +// Returns true if the basis is a pure rotation matrix, so it has no scale, skew, shear, or flip. bool Basis::is_rotation() const { - return Math::is_equal_approx(determinant(), 1, (real_t)UNIT_EPSILON) && is_orthogonal(); + return is_conformal() && Math::is_equal_approx(determinant(), 1, (real_t)UNIT_EPSILON); } #ifdef MATH_CHECKS @@ -257,29 +266,26 @@ void Basis::scale_orthogonal(const Vector3 &p_scale) { Basis Basis::scaled_orthogonal(const Vector3 &p_scale) const { Basis m = *this; Vector3 s = Vector3(-1, -1, -1) + p_scale; + bool sign = std::signbit(s.x + s.y + s.z); + Basis b = m.orthonormalized(); + s = b.xform_inv(s); Vector3 dots; - Basis b; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { - dots[j] += s[i] * Math::abs(m.get_column(i).normalized().dot(b.get_column(j))); + dots[j] += s[i] * abs(m.get_column(i).normalized().dot(b.get_column(j))); } } + if (sign != std::signbit(dots.x + dots.y + dots.z)) { + dots = -dots; + } m.scale_local(Vector3(1, 1, 1) + dots); return m; } -float Basis::get_uniform_scale() const { +real_t Basis::get_uniform_scale() const { return (rows[0].length() + rows[1].length() + rows[2].length()) / 3.0f; } -void Basis::make_scale_uniform() { - float l = (rows[0].length() + rows[1].length() + rows[2].length()) / 3.0f; - for (int i = 0; i < 3; i++) { - rows[i].normalize(); - rows[i] *= l; - } -} - Basis Basis::scaled_local(const Vector3 &p_scale) const { return (*this) * Basis::from_scale(p_scale); } @@ -291,7 +297,7 @@ Vector3 Basis::get_scale_abs() const { Vector3(rows[0][2], rows[1][2], rows[2][2]).length()); } -Vector3 Basis::get_scale_local() const { +Vector3 Basis::get_scale_global() const { real_t det_sign = SIGN(determinant()); return det_sign * Vector3(rows[0].length(), rows[1].length(), rows[2].length()); } @@ -418,7 +424,7 @@ void Basis::rotate_to_align(Vector3 p_start_direction, Vector3 p_end_direction) real_t dot = p_start_direction.dot(p_end_direction); dot = CLAMP(dot, -1.0f, 1.0f); const real_t angle_rads = Math::acos(dot); - set_axis_angle(axis, angle_rads); + *this = Basis(axis, angle_rads) * (*this); } } @@ -453,8 +459,13 @@ void Basis::get_rotation_axis_angle_local(Vector3 &p_axis, real_t &p_angle) cons } Vector3 Basis::get_euler(EulerOrder p_order) const { + // This epsilon value results in angles within a +/- 0.04 degree range being simplified/truncated. + // Based on testing, this is the largest the epsilon can be without the angle truncation becoming + // visually noticeable. + const real_t epsilon = 0.00000025; + switch (p_order) { - case EULER_ORDER_XYZ: { + case EulerOrder::EULER_ORDER_XYZ: { // Euler angles in XYZ convention. // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix // @@ -464,8 +475,8 @@ Vector3 Basis::get_euler(EulerOrder p_order) const { Vector3 euler; real_t sy = rows[0][2]; - if (sy < (1.0f - (real_t)CMP_EPSILON)) { - if (sy > -(1.0f - (real_t)CMP_EPSILON)) { + if (sy < (1.0f - epsilon)) { + if (sy > -(1.0f - epsilon)) { // is this a pure Y rotation? if (rows[1][0] == 0 && rows[0][1] == 0 && rows[1][2] == 0 && rows[2][1] == 0 && rows[1][1] == 1) { // return the simplest form (human friendlier in editor and scripts) @@ -489,7 +500,7 @@ Vector3 Basis::get_euler(EulerOrder p_order) const { } return euler; } - case EULER_ORDER_XZY: { + case EulerOrder::EULER_ORDER_XZY: { // Euler angles in XZY convention. // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix // @@ -499,8 +510,8 @@ Vector3 Basis::get_euler(EulerOrder p_order) const { Vector3 euler; real_t sz = rows[0][1]; - if (sz < (1.0f - (real_t)CMP_EPSILON)) { - if (sz > -(1.0f - (real_t)CMP_EPSILON)) { + if (sz < (1.0f - epsilon)) { + if (sz > -(1.0f - epsilon)) { euler.x = Math::atan2(rows[2][1], rows[1][1]); euler.y = Math::atan2(rows[0][2], rows[0][0]); euler.z = Math::asin(-sz); @@ -518,7 +529,7 @@ Vector3 Basis::get_euler(EulerOrder p_order) const { } return euler; } - case EULER_ORDER_YXZ: { + case EulerOrder::EULER_ORDER_YXZ: { // Euler angles in YXZ convention. // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix // @@ -530,8 +541,8 @@ Vector3 Basis::get_euler(EulerOrder p_order) const { real_t m12 = rows[1][2]; - if (m12 < (1 - (real_t)CMP_EPSILON)) { - if (m12 > -(1 - (real_t)CMP_EPSILON)) { + if (m12 < (1 - epsilon)) { + if (m12 > -(1 - epsilon)) { // is this a pure X rotation? if (rows[1][0] == 0 && rows[0][1] == 0 && rows[0][2] == 0 && rows[2][0] == 0 && rows[0][0] == 1) { // return the simplest form (human friendlier in editor and scripts) @@ -556,7 +567,7 @@ Vector3 Basis::get_euler(EulerOrder p_order) const { return euler; } - case EULER_ORDER_YZX: { + case EulerOrder::EULER_ORDER_YZX: { // Euler angles in YZX convention. // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix // @@ -566,8 +577,8 @@ Vector3 Basis::get_euler(EulerOrder p_order) const { Vector3 euler; real_t sz = rows[1][0]; - if (sz < (1.0f - (real_t)CMP_EPSILON)) { - if (sz > -(1.0f - (real_t)CMP_EPSILON)) { + if (sz < (1.0f - epsilon)) { + if (sz > -(1.0f - epsilon)) { euler.x = Math::atan2(-rows[1][2], rows[1][1]); euler.y = Math::atan2(-rows[2][0], rows[0][0]); euler.z = Math::asin(sz); @@ -584,8 +595,8 @@ Vector3 Basis::get_euler(EulerOrder p_order) const { euler.z = Math_PI / 2.0f; } return euler; - } - case EULER_ORDER_ZXY: { + } break; + case EulerOrder::EULER_ORDER_ZXY: { // Euler angles in ZXY convention. // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix // @@ -594,8 +605,8 @@ Vector3 Basis::get_euler(EulerOrder p_order) const { // -cx*sy sx cx*cy Vector3 euler; real_t sx = rows[2][1]; - if (sx < (1.0f - (real_t)CMP_EPSILON)) { - if (sx > -(1.0f - (real_t)CMP_EPSILON)) { + if (sx < (1.0f - epsilon)) { + if (sx > -(1.0f - epsilon)) { euler.x = Math::asin(sx); euler.y = Math::atan2(-rows[2][0], rows[2][2]); euler.z = Math::atan2(-rows[0][1], rows[1][1]); @@ -612,8 +623,8 @@ Vector3 Basis::get_euler(EulerOrder p_order) const { euler.z = 0; } return euler; - } - case EULER_ORDER_ZYX: { + } break; + case EulerOrder::EULER_ORDER_ZYX: { // Euler angles in ZYX convention. // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix // @@ -622,8 +633,8 @@ Vector3 Basis::get_euler(EulerOrder p_order) const { // -sy cy*sx cy*cx Vector3 euler; real_t sy = rows[2][0]; - if (sy < (1.0f - (real_t)CMP_EPSILON)) { - if (sy > -(1.0f - (real_t)CMP_EPSILON)) { + if (sy < (1.0f - epsilon)) { + if (sy > -(1.0f - epsilon)) { euler.x = Math::atan2(rows[2][1], rows[2][2]); euler.y = Math::asin(-sy); euler.z = Math::atan2(rows[1][0], rows[0][0]); @@ -664,26 +675,26 @@ void Basis::set_euler(const Vector3 &p_euler, EulerOrder p_order) { Basis zmat(c, -s, 0, s, c, 0, 0, 0, 1); switch (p_order) { - case EULER_ORDER_XYZ: { + case EulerOrder::EULER_ORDER_XYZ: { *this = xmat * (ymat * zmat); } break; - case EULER_ORDER_XZY: { + case EulerOrder::EULER_ORDER_XZY: { *this = xmat * zmat * ymat; } break; - case EULER_ORDER_YXZ: { + case EulerOrder::EULER_ORDER_YXZ: { *this = ymat * xmat * zmat; } break; - case EULER_ORDER_YZX: { + case EulerOrder::EULER_ORDER_YZX: { *this = ymat * zmat * xmat; } break; - case EULER_ORDER_ZXY: { + case EulerOrder::EULER_ORDER_ZXY: { *this = zmat * xmat * ymat; } break; - case EULER_ORDER_ZYX: { + case EulerOrder::EULER_ORDER_ZYX: { *this = zmat * ymat * xmat; } break; default: { - ERR_FAIL_MSG("Invalid order parameter for set_euler(vec3,order)"); + ERR_FAIL_MSG("Invalid Euler order parameter."); } } } @@ -720,7 +731,7 @@ Basis::operator String() const { Quaternion Basis::get_quaternion() const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!is_rotation(), Quaternion(), "Basis must be normalized in order to be casted to a Quaternion. Use get_rotation_quaternion() or call orthonormalized() if the Basis contains linearly independent vectors."); + ERR_FAIL_COND_V_MSG(!is_rotation(), Quaternion(), "Basis " + operator String() + " must be normalized in order to be casted to a Quaternion. Use get_rotation_quaternion() or call orthonormalized() if the Basis contains linearly independent vectors."); #endif /* Allow getting a quaternion from an unnormalized transform */ Basis m = *this; @@ -828,8 +839,8 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const { z = (rows[1][0] - rows[0][1]) / s; r_axis = Vector3(x, y, z); - // CLAMP to avoid NaN if the value passed to acos is not in [0,1]. - r_angle = Math::acos(CLAMP((rows[0][0] + rows[1][1] + rows[2][2] - 1) / 2, (real_t)0.0, (real_t)1.0)); + // acos does clamping. + r_angle = Math::acos((rows[0][0] + rows[1][1] + rows[2][2] - 1) / 2); } void Basis::set_quaternion(const Quaternion &p_quaternion) { @@ -847,7 +858,7 @@ void Basis::set_quaternion(const Quaternion &p_quaternion) { void Basis::set_axis_angle(const Vector3 &p_axis, real_t p_angle) { // Rotation matrix from axis and angle, see https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_angle #ifdef MATH_CHECKS - ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 must be normalized."); + ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 " + p_axis.operator String() + " must be normalized."); #endif Vector3 axis_sq(p_axis.x * p_axis.x, p_axis.y * p_axis.y, p_axis.z * p_axis.z); real_t cosine = Math::cos(p_angle); @@ -905,7 +916,7 @@ void Basis::_set_diagonal(const Vector3 &p_diag) { rows[2][2] = p_diag.z; } -Basis Basis::lerp(const Basis &p_to, const real_t &p_weight) const { +Basis Basis::lerp(const Basis &p_to, real_t p_weight) const { Basis b; b.rows[0] = rows[0].lerp(p_to.rows[0], p_weight); b.rows[1] = rows[1].lerp(p_to.rows[1], p_weight); @@ -914,7 +925,7 @@ Basis Basis::lerp(const Basis &p_to, const real_t &p_weight) const { return b; } -Basis Basis::slerp(const Basis &p_to, const real_t &p_weight) const { +Basis Basis::slerp(const Basis &p_to, real_t p_weight) const { //consider scale Quaternion from(*this); Quaternion to(p_to); @@ -1047,9 +1058,10 @@ Basis Basis::looking_at(const Vector3 &p_target, const Vector3 &p_up, bool p_use v_z = -v_z; } Vector3 v_x = p_up.cross(v_z); -#ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(v_x.is_zero_approx(), Basis(), "The target vector and up vector can't be parallel to each other."); -#endif + if (v_x.is_zero_approx()) { + WARN_PRINT("Target and up vectors are colinear. This is not advised as it may cause unwanted rotation around local Z axis."); + v_x = p_up.get_any_perpendicular(); // Vectors are almost parallel. + } v_x.normalize(); Vector3 v_y = v_z.cross(v_x); diff --git a/src/variant/color.cpp b/src/variant/color.cpp index 4e3b870e2..1fb5211a5 100644 --- a/src/variant/color.cpp +++ b/src/variant/color.cpp @@ -29,6 +29,7 @@ /**************************************************************************/ #include +#include #include #include #include @@ -131,20 +132,20 @@ String _to_hex(float p_val) { String Color::to_html(bool p_alpha) const { String txt; - txt = txt + _to_hex(r); - txt = txt + _to_hex(g); - txt = txt + _to_hex(b); + txt += _to_hex(r); + txt += _to_hex(g); + txt += _to_hex(b); if (p_alpha) { - txt = txt + _to_hex(a); + txt += _to_hex(a); } return txt; } float Color::get_h() const { - float min = Math::min(r, g); - min = Math::min(min, b); - float max = Math::max(r, g); - max = Math::max(max, b); + float min = MIN(r, g); + min = MIN(min, b); + float max = MAX(r, g); + max = MAX(max, b); float delta = max - min; @@ -170,10 +171,10 @@ float Color::get_h() const { } float Color::get_s() const { - float min = Math::min(r, g); - min = Math::min(min, b); - float max = Math::max(r, g); - max = Math::max(max, b); + float min = MIN(r, g); + min = MIN(min, b); + float max = MAX(r, g); + max = MAX(max, b); float delta = max - min; @@ -181,8 +182,8 @@ float Color::get_s() const { } float Color::get_v() const { - float max = Math::max(r, g); - max = Math::max(max, b); + float max = MAX(r, g); + max = MAX(max, b); return max; } @@ -385,7 +386,6 @@ Color Color::named(const String &p_name) { int idx = find_named_color(p_name); if (idx == -1) { ERR_FAIL_V_MSG(Color(), "Invalid color name: " + p_name + "."); - return Color(); } return named_colors[idx].color; } @@ -400,7 +400,7 @@ Color Color::named(const String &p_name, const Color &p_default) { int Color::find_named_color(const String &p_name) { String name = p_name; - // Normalize name + // Normalize name. name = name.replace(" ", ""); name = name.replace("-", ""); name = name.replace("_", ""); @@ -408,23 +408,24 @@ int Color::find_named_color(const String &p_name) { name = name.replace(".", ""); name = name.to_upper(); - int idx = 0; - while (named_colors[idx].name != nullptr) { - if (name == String(named_colors[idx].name).replace("_", "")) { - return idx; + static HashMap named_colors_hashmap; + if (unlikely(named_colors_hashmap.is_empty())) { + const int named_color_count = get_named_color_count(); + for (int i = 0; i < named_color_count; i++) { + named_colors_hashmap[String(named_colors[i].name).replace("_", "")] = i; } - idx++; + } + + const HashMap::ConstIterator E = named_colors_hashmap.find(name); + if (E) { + return E->value; } return -1; } int Color::get_named_color_count() { - int idx = 0; - while (named_colors[idx].name != nullptr) { - idx++; - } - return idx; + return sizeof(named_colors) / sizeof(NamedColor); } String Color::get_named_color_name(int p_idx) { @@ -467,6 +468,10 @@ Color Color::from_rgbe9995(uint32_t p_rgbe) { return Color(rd, gd, bd, 1.0f); } +Color Color::from_rgba8(int64_t p_r8, int64_t p_g8, int64_t p_b8, int64_t p_a8) { + return Color(p_r8 / 255.0f, p_g8 / 255.0f, p_b8 / 255.0f, p_a8 / 255.0f); +} + Color::operator String() const { return "(" + String::num(r, 4) + ", " + String::num(g, 4) + ", " + String::num(b, 4) + ", " + String::num(a, 4) + ")"; } diff --git a/src/variant/plane.cpp b/src/variant/plane.cpp index caea516e1..05aadcaa9 100644 --- a/src/variant/plane.cpp +++ b/src/variant/plane.cpp @@ -60,7 +60,7 @@ Vector3 Plane::get_any_perpendicular_normal() const { static const Vector3 p2 = Vector3(0, 1, 0); Vector3 p; - if (Math::abs(normal.dot(p1)) > 0.99f) { // if too similar to p1 + if (ABS(normal.dot(p1)) > 0.99f) { // if too similar to p1 p = p2; // use p2 } else { p = p1; // use p1 @@ -100,13 +100,11 @@ bool Plane::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 Vector3 segment = p_dir; real_t den = normal.dot(segment); - //printf("den is %i\n",den); if (Math::is_zero_approx(den)) { return false; } real_t dist = (normal.dot(p_from) - d) / den; - //printf("dist is %i\n",dist); if (dist > (real_t)CMP_EPSILON) { //this is a ray, before the emitting pos (p_from) doesn't exist @@ -123,13 +121,11 @@ bool Plane::intersects_segment(const Vector3 &p_begin, const Vector3 &p_end, Vec Vector3 segment = p_begin - p_end; real_t den = normal.dot(segment); - //printf("den is %i\n",den); if (Math::is_zero_approx(den)) { return false; } real_t dist = (normal.dot(p_begin) - d) / den; - //printf("dist is %i\n",dist); if (dist < (real_t)-CMP_EPSILON || dist > (1.0f + (real_t)CMP_EPSILON)) { return false; diff --git a/src/variant/projection.cpp b/src/variant/projection.cpp index ddedc93f9..e983cd204 100644 --- a/src/variant/projection.cpp +++ b/src/variant/projection.cpp @@ -39,7 +39,7 @@ namespace godot { -float Projection::determinant() const { +real_t Projection::determinant() const { return columns[0][3] * columns[1][2] * columns[2][1] * columns[3][0] - columns[0][2] * columns[1][3] * columns[2][1] * columns[3][0] - columns[0][3] * columns[1][1] * columns[2][2] * columns[3][0] + columns[0][1] * columns[1][3] * columns[2][2] * columns[3][0] + columns[0][2] * columns[1][1] * columns[2][3] * columns[3][0] - columns[0][1] * columns[1][2] * columns[2][3] * columns[3][0] - @@ -171,7 +171,7 @@ Projection Projection::perspective_znear_adjusted(real_t p_new_znear) const { } Plane Projection::get_projection_plane(Planes p_plane) const { - const real_t *matrix = (const real_t *)this->columns; + const real_t *matrix = (const real_t *)columns; switch (p_plane) { case PLANE_NEAR: { @@ -404,20 +404,19 @@ void Projection::set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset, r } real_t Projection::get_z_far() const { - const real_t *matrix = (const real_t *)this->columns; + const real_t *matrix = (const real_t *)columns; Plane new_plane = Plane(matrix[3] - matrix[2], matrix[7] - matrix[6], matrix[11] - matrix[10], matrix[15] - matrix[14]); - new_plane.normal = -new_plane.normal; new_plane.normalize(); return new_plane.d; } real_t Projection::get_z_near() const { - const real_t *matrix = (const real_t *)this->columns; + const real_t *matrix = (const real_t *)columns; Plane new_plane = Plane(matrix[3] + matrix[2], matrix[7] + matrix[6], matrix[11] + matrix[10], @@ -428,7 +427,7 @@ real_t Projection::get_z_near() const { } Vector2 Projection::get_viewport_half_extents() const { - const real_t *matrix = (const real_t *)this->columns; + const real_t *matrix = (const real_t *)columns; ///////--- Near Plane ---/////// Plane near_plane = Plane(matrix[3] + matrix[2], matrix[7] + matrix[6], @@ -456,7 +455,7 @@ Vector2 Projection::get_viewport_half_extents() const { } Vector2 Projection::get_far_plane_half_extents() const { - const real_t *matrix = (const real_t *)this->columns; + const real_t *matrix = (const real_t *)columns; ///////--- Far Plane ---/////// Plane far_plane = Plane(matrix[3] - matrix[2], matrix[7] - matrix[6], @@ -484,7 +483,7 @@ Vector2 Projection::get_far_plane_half_extents() const { } bool Projection::get_endpoints(const Transform3D &p_transform, Vector3 *p_8points) const { - Array planes = get_projection_planes(Transform3D()); + Vector planes = get_projection_planes(Transform3D()); const Planes intersections[8][3] = { { PLANE_FAR, PLANE_LEFT, PLANE_TOP }, { PLANE_FAR, PLANE_LEFT, PLANE_BOTTOM }, @@ -509,17 +508,17 @@ bool Projection::get_endpoints(const Transform3D &p_transform, Vector3 *p_8point return true; } -Array Projection::get_projection_planes(const Transform3D &p_transform) const { +Vector Projection::get_projection_planes(const Transform3D &p_transform) const { /** Fast Plane Extraction from combined modelview/projection matrices. * References: * https://web.archive.org/web/20011221205252/https://www.markmorley.com/opengl/frustumculling.html * https://web.archive.org/web/20061020020112/https://www2.ravensoft.com/users/ggribb/plane%20extraction.pdf */ - Array planes; + Vector planes; planes.resize(6); - const real_t *matrix = (const real_t *)this->columns; + const real_t *matrix = (const real_t *)columns; Plane new_plane; @@ -532,7 +531,7 @@ Array Projection::get_projection_planes(const Transform3D &p_transform) const { new_plane.normal = -new_plane.normal; new_plane.normalize(); - planes[0] = p_transform.xform(new_plane); + planes.write[0] = p_transform.xform(new_plane); ///////--- Far Plane ---/////// new_plane = Plane(matrix[3] - matrix[2], @@ -543,7 +542,7 @@ Array Projection::get_projection_planes(const Transform3D &p_transform) const { new_plane.normal = -new_plane.normal; new_plane.normalize(); - planes[1] = p_transform.xform(new_plane); + planes.write[1] = p_transform.xform(new_plane); ///////--- Left Plane ---/////// new_plane = Plane(matrix[3] + matrix[0], @@ -554,7 +553,7 @@ Array Projection::get_projection_planes(const Transform3D &p_transform) const { new_plane.normal = -new_plane.normal; new_plane.normalize(); - planes[2] = p_transform.xform(new_plane); + planes.write[2] = p_transform.xform(new_plane); ///////--- Top Plane ---/////// new_plane = Plane(matrix[3] - matrix[1], @@ -565,7 +564,7 @@ Array Projection::get_projection_planes(const Transform3D &p_transform) const { new_plane.normal = -new_plane.normal; new_plane.normalize(); - planes[3] = p_transform.xform(new_plane); + planes.write[3] = p_transform.xform(new_plane); ///////--- Right Plane ---/////// new_plane = Plane(matrix[3] - matrix[0], @@ -576,7 +575,7 @@ Array Projection::get_projection_planes(const Transform3D &p_transform) const { new_plane.normal = -new_plane.normal; new_plane.normalize(); - planes[4] = p_transform.xform(new_plane); + planes.write[4] = p_transform.xform(new_plane); ///////--- Bottom Plane ---/////// new_plane = Plane(matrix[3] + matrix[1], @@ -587,7 +586,7 @@ Array Projection::get_projection_planes(const Transform3D &p_transform) const { new_plane.normal = -new_plane.normal; new_plane.normalize(); - planes[5] = p_transform.xform(new_plane); + planes.write[5] = p_transform.xform(new_plane); return planes; } @@ -599,101 +598,229 @@ Projection Projection::inverse() const { } void Projection::invert() { - int i, j, k; - int pvt_i[4], pvt_j[4]; /* Locations of pivot matrix */ - real_t pvt_val; /* Value of current pivot element */ - real_t hold; /* Temporary storage */ - real_t determinant = 1.0f; - for (k = 0; k < 4; k++) { - /** Locate k'th pivot element **/ - pvt_val = columns[k][k]; /** Initialize for search **/ - pvt_i[k] = k; - pvt_j[k] = k; - for (i = k; i < 4; i++) { - for (j = k; j < 4; j++) { - if (Math::abs(columns[i][j]) > Math::abs(pvt_val)) { - pvt_i[k] = i; - pvt_j[k] = j; - pvt_val = columns[i][j]; - } - } - } - - /** Product of pivots, gives determinant when finished **/ - determinant *= pvt_val; - if (Math::is_zero_approx(determinant)) { - return; /** Matrix is singular (zero determinant). **/ - } - - /** "Interchange" rows (with sign change stuff) **/ - i = pvt_i[k]; - if (i != k) { /** If rows are different **/ - for (j = 0; j < 4; j++) { - hold = -columns[k][j]; - columns[k][j] = columns[i][j]; - columns[i][j] = hold; - } - } - - /** "Interchange" columns **/ - j = pvt_j[k]; - if (j != k) { /** If columns are different **/ - for (i = 0; i < 4; i++) { - hold = -columns[i][k]; - columns[i][k] = columns[i][j]; - columns[i][j] = hold; - } - } - - /** Divide column by minus pivot value **/ - for (i = 0; i < 4; i++) { - if (i != k) { - columns[i][k] /= (-pvt_val); - } - } - - /** Reduce the matrix **/ - for (i = 0; i < 4; i++) { - hold = columns[i][k]; - for (j = 0; j < 4; j++) { - if (i != k && j != k) { - columns[i][j] += hold * columns[k][j]; - } - } - } - - /** Divide row by pivot **/ - for (j = 0; j < 4; j++) { - if (j != k) { - columns[k][j] /= pvt_val; - } - } - - /** Replace pivot by reciprocal (at last we can touch it). **/ - columns[k][k] = 1.0 / pvt_val; + // Adapted from Mesa's `src/util/u_math.c` `util_invert_mat4x4`. + // MIT licensed. Copyright 2008 VMware, Inc. Authored by Jacques Leroy. + Projection temp; + real_t *out = (real_t *)temp.columns; + real_t *m = (real_t *)columns; + + real_t wtmp[4][8]; + real_t m0, m1, m2, m3, s; + real_t *r0, *r1, *r2, *r3; + +#define MAT(m, r, c) (m)[(c) * 4 + (r)] + + r0 = wtmp[0]; + r1 = wtmp[1]; + r2 = wtmp[2]; + r3 = wtmp[3]; + + r0[0] = MAT(m, 0, 0); + r0[1] = MAT(m, 0, 1); + r0[2] = MAT(m, 0, 2); + r0[3] = MAT(m, 0, 3); + r0[4] = 1.0; + r0[5] = 0.0; + r0[6] = 0.0; + r0[7] = 0.0; + + r1[0] = MAT(m, 1, 0); + r1[1] = MAT(m, 1, 1); + r1[2] = MAT(m, 1, 2); + r1[3] = MAT(m, 1, 3); + r1[5] = 1.0; + r1[4] = 0.0; + r1[6] = 0.0; + r1[7] = 0.0; + + r2[0] = MAT(m, 2, 0); + r2[1] = MAT(m, 2, 1); + r2[2] = MAT(m, 2, 2); + r2[3] = MAT(m, 2, 3); + r2[6] = 1.0; + r2[4] = 0.0; + r2[5] = 0.0; + r2[7] = 0.0; + + r3[0] = MAT(m, 3, 0); + r3[1] = MAT(m, 3, 1); + r3[2] = MAT(m, 3, 2); + r3[3] = MAT(m, 3, 3); + + r3[7] = 1.0; + r3[4] = 0.0; + r3[5] = 0.0; + r3[6] = 0.0; + + /* choose pivot - or die */ + if (Math::abs(r3[0]) > Math::abs(r2[0])) { + SWAP(r3, r2); + } + if (Math::abs(r2[0]) > Math::abs(r1[0])) { + SWAP(r2, r1); + } + if (Math::abs(r1[0]) > Math::abs(r0[0])) { + SWAP(r1, r0); + } + ERR_FAIL_COND(0.0 == r0[0]); + + /* eliminate first variable */ + m1 = r1[0] / r0[0]; + m2 = r2[0] / r0[0]; + m3 = r3[0] / r0[0]; + s = r0[1]; + r1[1] -= m1 * s; + r2[1] -= m2 * s; + r3[1] -= m3 * s; + s = r0[2]; + r1[2] -= m1 * s; + r2[2] -= m2 * s; + r3[2] -= m3 * s; + s = r0[3]; + r1[3] -= m1 * s; + r2[3] -= m2 * s; + r3[3] -= m3 * s; + s = r0[4]; + if (s != 0.0) { + r1[4] -= m1 * s; + r2[4] -= m2 * s; + r3[4] -= m3 * s; + } + s = r0[5]; + if (s != 0.0) { + r1[5] -= m1 * s; + r2[5] -= m2 * s; + r3[5] -= m3 * s; + } + s = r0[6]; + if (s != 0.0) { + r1[6] -= m1 * s; + r2[6] -= m2 * s; + r3[6] -= m3 * s; + } + s = r0[7]; + if (s != 0.0) { + r1[7] -= m1 * s; + r2[7] -= m2 * s; + r3[7] -= m3 * s; } - /* That was most of the work, one final pass of row/column interchange */ - /* to finish */ - for (k = 4 - 2; k >= 0; k--) { /* Don't need to work with 1 by 1 corner*/ - i = pvt_j[k]; /* Rows to swap correspond to pivot COLUMN */ - if (i != k) { /* If rows are different */ - for (j = 0; j < 4; j++) { - hold = columns[k][j]; - columns[k][j] = -columns[i][j]; - columns[i][j] = hold; - } - } + /* choose pivot - or die */ + if (Math::abs(r3[1]) > Math::abs(r2[1])) { + SWAP(r3, r2); + } + if (Math::abs(r2[1]) > Math::abs(r1[1])) { + SWAP(r2, r1); + } + ERR_FAIL_COND(0.0 == r1[1]); + + /* eliminate second variable */ + m2 = r2[1] / r1[1]; + m3 = r3[1] / r1[1]; + r2[2] -= m2 * r1[2]; + r3[2] -= m3 * r1[2]; + r2[3] -= m2 * r1[3]; + r3[3] -= m3 * r1[3]; + s = r1[4]; + if (0.0 != s) { + r2[4] -= m2 * s; + r3[4] -= m3 * s; + } + s = r1[5]; + if (0.0 != s) { + r2[5] -= m2 * s; + r3[5] -= m3 * s; + } + s = r1[6]; + if (0.0 != s) { + r2[6] -= m2 * s; + r3[6] -= m3 * s; + } + s = r1[7]; + if (0.0 != s) { + r2[7] -= m2 * s; + r3[7] -= m3 * s; + } - j = pvt_i[k]; /* Columns to swap correspond to pivot ROW */ - if (j != k) { /* If columns are different */ - for (i = 0; i < 4; i++) { - hold = columns[i][k]; - columns[i][k] = -columns[i][j]; - columns[i][j] = hold; - } - } + /* choose pivot - or die */ + if (Math::abs(r3[2]) > Math::abs(r2[2])) { + SWAP(r3, r2); } + ERR_FAIL_COND(0.0 == r2[2]); + + /* eliminate third variable */ + m3 = r3[2] / r2[2]; + r3[3] -= m3 * r2[3]; + r3[4] -= m3 * r2[4]; + r3[5] -= m3 * r2[5]; + r3[6] -= m3 * r2[6]; + r3[7] -= m3 * r2[7]; + + /* last check */ + ERR_FAIL_COND(0.0 == r3[3]); + + s = 1.0 / r3[3]; /* now back substitute row 3 */ + r3[4] *= s; + r3[5] *= s; + r3[6] *= s; + r3[7] *= s; + + m2 = r2[3]; /* now back substitute row 2 */ + s = 1.0 / r2[2]; + r2[4] = s * (r2[4] - r3[4] * m2); + r2[5] = s * (r2[5] - r3[5] * m2); + r2[6] = s * (r2[6] - r3[6] * m2); + r2[7] = s * (r2[7] - r3[7] * m2); + m1 = r1[3]; + r1[4] -= r3[4] * m1; + r1[5] -= r3[5] * m1; + r1[6] -= r3[6] * m1; + r1[7] -= r3[7] * m1; + m0 = r0[3]; + r0[4] -= r3[4] * m0; + r0[5] -= r3[5] * m0; + r0[6] -= r3[6] * m0; + r0[7] -= r3[7] * m0; + + m1 = r1[2]; /* now back substitute row 1 */ + s = 1.0 / r1[1]; + r1[4] = s * (r1[4] - r2[4] * m1); + r1[5] = s * (r1[5] - r2[5] * m1), + r1[6] = s * (r1[6] - r2[6] * m1); + r1[7] = s * (r1[7] - r2[7] * m1); + m0 = r0[2]; + r0[4] -= r2[4] * m0; + r0[5] -= r2[5] * m0; + r0[6] -= r2[6] * m0; + r0[7] -= r2[7] * m0; + + m0 = r0[1]; /* now back substitute row 0 */ + s = 1.0 / r0[0]; + r0[4] = s * (r0[4] - r1[4] * m0); + r0[5] = s * (r0[5] - r1[5] * m0), + r0[6] = s * (r0[6] - r1[6] * m0); + r0[7] = s * (r0[7] - r1[7] * m0); + + MAT(out, 0, 0) = r0[4]; + MAT(out, 0, 1) = r0[5]; + MAT(out, 0, 2) = r0[6]; + MAT(out, 0, 3) = r0[7]; + MAT(out, 1, 0) = r1[4]; + MAT(out, 1, 1) = r1[5]; + MAT(out, 1, 2) = r1[6]; + MAT(out, 1, 3) = r1[7]; + MAT(out, 2, 0) = r2[4]; + MAT(out, 2, 1) = r2[5]; + MAT(out, 2, 2) = r2[6]; + MAT(out, 2, 3) = r2[7]; + MAT(out, 3, 0) = r3[4]; + MAT(out, 3, 1) = r3[5]; + MAT(out, 3, 2) = r3[6]; + MAT(out, 3, 3) = r3[7]; + +#undef MAT + + *this = temp; } void Projection::flip_y() { @@ -722,7 +849,8 @@ Projection Projection::operator*(const Projection &p_matrix) const { return new_matrix; } -void Projection::set_depth_correction(bool p_flip_y) { +void Projection::set_depth_correction(bool p_flip_y, bool p_reverse_z, bool p_remap_z) { + // p_remap_z is used to convert from OpenGL-style clip space (-1 - 1) to Vulkan style (0 - 1). real_t *m = &columns[0][0]; m[0] = 1; @@ -735,11 +863,11 @@ void Projection::set_depth_correction(bool p_flip_y) { m[7] = 0.0; m[8] = 0.0; m[9] = 0.0; - m[10] = 0.5; + m[10] = p_remap_z ? (p_reverse_z ? -0.5 : 0.5) : (p_reverse_z ? -1.0 : 1.0); m[11] = 0.0; m[12] = 0.0; m[13] = 0.0; - m[14] = 0.5; + m[14] = p_remap_z ? 0.5 : 0.0; m[15] = 1.0; } @@ -786,14 +914,10 @@ void Projection::set_light_atlas_rect(const Rect2 &p_rect) { } Projection::operator String() const { - String str; - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - str = str + String((j > 0) ? ", " : "\n") + rtos(columns[i][j]); - } - } - - return str; + return "[X: " + columns[0].operator String() + + ", Y: " + columns[1].operator String() + + ", Z: " + columns[2].operator String() + + ", W: " + columns[3].operator String() + "]"; } real_t Projection::get_aspect() const { @@ -812,7 +936,7 @@ bool Projection::is_orthogonal() const { } real_t Projection::get_fov() const { - const real_t *matrix = (const real_t *)this->columns; + const real_t *matrix = (const real_t *)columns; Plane right_plane = Plane(matrix[3] - matrix[0], matrix[7] - matrix[4], @@ -834,13 +958,13 @@ real_t Projection::get_fov() const { } } -float Projection::get_lod_multiplier() const { +real_t Projection::get_lod_multiplier() const { if (is_orthogonal()) { return get_viewport_half_extents().x; } else { - float zn = get_z_near(); - float width = get_viewport_half_extents().x * 2.0; - return 1.0 / (zn / width); + const real_t zn = get_z_near(); + const real_t width = get_viewport_half_extents().x * 2.0f; + return 1.0f / (zn / width); } // Usage is lod_size / (lod_distance * multiplier) < threshold diff --git a/src/variant/quaternion.cpp b/src/variant/quaternion.cpp index 3dd7af54a..af75cf450 100644 --- a/src/variant/quaternion.cpp +++ b/src/variant/quaternion.cpp @@ -194,11 +194,11 @@ Quaternion Quaternion::spherical_cubic_interpolate(const Quaternion &p_b, const post_q = Basis(post_q).get_rotation_quaternion(); // Flip quaternions to shortest path if necessary. - bool flip1 = Math::sign(from_q.dot(pre_q)); + bool flip1 = std::signbit(from_q.dot(pre_q)); pre_q = flip1 ? -pre_q : pre_q; - bool flip2 = Math::sign(from_q.dot(to_q)); + bool flip2 = std::signbit(from_q.dot(to_q)); to_q = flip2 ? -to_q : to_q; - bool flip3 = flip2 ? to_q.dot(post_q) <= 0 : Math::sign(to_q.dot(post_q)); + bool flip3 = flip2 ? to_q.dot(post_q) <= 0 : std::signbit(to_q.dot(post_q)); post_q = flip3 ? -post_q : post_q; // Calc by Expmap in from_q space. @@ -245,11 +245,11 @@ Quaternion Quaternion::spherical_cubic_interpolate_in_time(const Quaternion &p_b post_q = Basis(post_q).get_rotation_quaternion(); // Flip quaternions to shortest path if necessary. - bool flip1 = Math::sign(from_q.dot(pre_q)); + bool flip1 = std::signbit(from_q.dot(pre_q)); pre_q = flip1 ? -pre_q : pre_q; - bool flip2 = Math::sign(from_q.dot(to_q)); + bool flip2 = std::signbit(from_q.dot(to_q)); to_q = flip2 ? -to_q : to_q; - bool flip3 = flip2 ? to_q.dot(post_q) <= 0 : Math::sign(to_q.dot(post_q)); + bool flip3 = flip2 ? to_q.dot(post_q) <= 0 : std::signbit(to_q.dot(post_q)); post_q = flip3 ? -post_q : post_q; // Calc by Expmap in from_q space. diff --git a/src/variant/rect2.cpp b/src/variant/rect2.cpp index 62730a9d4..7192a7111 100644 --- a/src/variant/rect2.cpp +++ b/src/variant/rect2.cpp @@ -211,31 +211,31 @@ bool Rect2::intersects_transformed(const Transform2D &p_xform, const Rect2 &p_re real_t mina = maxa; real_t dp = p_xform.columns[0].dot(xf_points2[1]); - maxa = Math::max(dp, maxa); - mina = Math::min(dp, mina); + maxa = MAX(dp, maxa); + mina = MIN(dp, mina); dp = p_xform.columns[0].dot(xf_points2[2]); - maxa = Math::max(dp, maxa); - mina = Math::min(dp, mina); + maxa = MAX(dp, maxa); + mina = MIN(dp, mina); dp = p_xform.columns[0].dot(xf_points2[3]); - maxa = Math::max(dp, maxa); - mina = Math::min(dp, mina); + maxa = MAX(dp, maxa); + mina = MIN(dp, mina); real_t maxb = p_xform.columns[0].dot(xf_points[0]); real_t minb = maxb; dp = p_xform.columns[0].dot(xf_points[1]); - maxb = Math::max(dp, maxb); - minb = Math::min(dp, minb); + maxb = MAX(dp, maxb); + minb = MIN(dp, minb); dp = p_xform.columns[0].dot(xf_points[2]); - maxb = Math::max(dp, maxb); - minb = Math::min(dp, minb); + maxb = MAX(dp, maxb); + minb = MIN(dp, minb); dp = p_xform.columns[0].dot(xf_points[3]); - maxb = Math::max(dp, maxb); - minb = Math::min(dp, minb); + maxb = MAX(dp, maxb); + minb = MIN(dp, minb); if (mina > maxb) { return false; @@ -248,31 +248,31 @@ bool Rect2::intersects_transformed(const Transform2D &p_xform, const Rect2 &p_re mina = maxa; dp = p_xform.columns[1].dot(xf_points2[1]); - maxa = Math::max(dp, maxa); - mina = Math::min(dp, mina); + maxa = MAX(dp, maxa); + mina = MIN(dp, mina); dp = p_xform.columns[1].dot(xf_points2[2]); - maxa = Math::max(dp, maxa); - mina = Math::min(dp, mina); + maxa = MAX(dp, maxa); + mina = MIN(dp, mina); dp = p_xform.columns[1].dot(xf_points2[3]); - maxa = Math::max(dp, maxa); - mina = Math::min(dp, mina); + maxa = MAX(dp, maxa); + mina = MIN(dp, mina); maxb = p_xform.columns[1].dot(xf_points[0]); minb = maxb; dp = p_xform.columns[1].dot(xf_points[1]); - maxb = Math::max(dp, maxb); - minb = Math::min(dp, minb); + maxb = MAX(dp, maxb); + minb = MIN(dp, minb); dp = p_xform.columns[1].dot(xf_points[2]); - maxb = Math::max(dp, maxb); - minb = Math::min(dp, minb); + maxb = MAX(dp, maxb); + minb = MIN(dp, minb); dp = p_xform.columns[1].dot(xf_points[3]); - maxb = Math::max(dp, maxb); - minb = Math::min(dp, minb); + maxb = MAX(dp, maxb); + minb = MIN(dp, minb); if (mina > maxb) { return false; @@ -285,7 +285,7 @@ bool Rect2::intersects_transformed(const Transform2D &p_xform, const Rect2 &p_re } Rect2::operator String() const { - return "[P: " + position.operator String() + ", S: " + size + "]"; + return "[P: " + position.operator String() + ", S: " + size.operator String() + "]"; } Rect2::operator Rect2i() const { diff --git a/src/variant/transform2d.cpp b/src/variant/transform2d.cpp index 3b2c0b09e..b6b330bda 100644 --- a/src/variant/transform2d.cpp +++ b/src/variant/transform2d.cpp @@ -48,7 +48,7 @@ Transform2D Transform2D::inverse() const { } void Transform2D::affine_invert() { - real_t det = basis_determinant(); + real_t det = determinant(); #ifdef MATH_CHECKS ERR_FAIL_COND(det == 0); #endif @@ -67,17 +67,17 @@ Transform2D Transform2D::affine_inverse() const { return inv; } -void Transform2D::rotate(const real_t p_angle) { +void Transform2D::rotate(real_t p_angle) { *this = Transform2D(p_angle, Vector2()) * (*this); } real_t Transform2D::get_skew() const { - real_t det = basis_determinant(); + real_t det = determinant(); return Math::acos(columns[0].normalized().dot(SIGN(det) * columns[1].normalized())) - (real_t)Math_PI * 0.5f; } -void Transform2D::set_skew(const real_t p_angle) { - real_t det = basis_determinant(); +void Transform2D::set_skew(real_t p_angle) { + real_t det = determinant(); columns[1] = SIGN(det) * columns[0].rotated(((real_t)Math_PI * 0.5f + p_angle)).normalized() * columns[1].length(); } @@ -85,7 +85,7 @@ real_t Transform2D::get_rotation() const { return Math::atan2(columns[0].y, columns[0].x); } -void Transform2D::set_rotation(const real_t p_rot) { +void Transform2D::set_rotation(real_t p_rot) { Size2 scale = get_scale(); real_t cr = Math::cos(p_rot); real_t sr = Math::sin(p_rot); @@ -96,7 +96,7 @@ void Transform2D::set_rotation(const real_t p_rot) { set_scale(scale); } -Transform2D::Transform2D(const real_t p_rot, const Vector2 &p_pos) { +Transform2D::Transform2D(real_t p_rot, const Vector2 &p_pos) { real_t cr = Math::cos(p_rot); real_t sr = Math::sin(p_rot); columns[0][0] = cr; @@ -106,7 +106,7 @@ Transform2D::Transform2D(const real_t p_rot, const Vector2 &p_pos) { columns[2] = p_pos; } -Transform2D::Transform2D(const real_t p_rot, const Size2 &p_scale, const real_t p_skew, const Vector2 &p_pos) { +Transform2D::Transform2D(real_t p_rot, const Size2 &p_scale, real_t p_skew, const Vector2 &p_pos) { columns[0][0] = Math::cos(p_rot) * p_scale.x; columns[1][1] = Math::cos(p_rot + p_skew) * p_scale.y; columns[1][0] = -Math::sin(p_rot + p_skew) * p_scale.y; @@ -115,7 +115,7 @@ Transform2D::Transform2D(const real_t p_rot, const Size2 &p_scale, const real_t } Size2 Transform2D::get_scale() const { - real_t det_sign = Math::sign(basis_determinant()); + real_t det_sign = SIGN(determinant()); return Size2(columns[0].length(), det_sign * columns[1].length()); } @@ -138,7 +138,7 @@ void Transform2D::scale_basis(const Size2 &p_scale) { columns[1][1] *= p_scale.y; } -void Transform2D::translate_local(const real_t p_tx, const real_t p_ty) { +void Transform2D::translate_local(real_t p_tx, real_t p_ty) { translate_local(Vector2(p_tx, p_ty)); } @@ -153,7 +153,7 @@ void Transform2D::orthonormalize() { Vector2 y = columns[1]; x.normalize(); - y = (y - x * (x.dot(y))); + y = y - x * x.dot(y); y.normalize(); columns[0] = x; @@ -161,9 +161,21 @@ void Transform2D::orthonormalize() { } Transform2D Transform2D::orthonormalized() const { - Transform2D on = *this; - on.orthonormalize(); - return on; + Transform2D ortho = *this; + ortho.orthonormalize(); + return ortho; +} + +bool Transform2D::is_conformal() const { + // Non-flipped case. + if (Math::is_equal_approx(columns[0][0], columns[1][1]) && Math::is_equal_approx(columns[0][1], -columns[1][0])) { + return true; + } + // Flipped case. + if (Math::is_equal_approx(columns[0][0], -columns[1][1]) && Math::is_equal_approx(columns[0][1], columns[1][0])) { + return true; + } + return false; } bool Transform2D::is_equal_approx(const Transform2D &p_transform) const { @@ -223,12 +235,6 @@ Transform2D Transform2D::operator*(const Transform2D &p_transform) const { return t; } -Transform2D Transform2D::basis_scaled(const Size2 &p_scale) const { - Transform2D copy = *this; - copy.scale_basis(p_scale); - return copy; -} - Transform2D Transform2D::scaled(const Size2 &p_scale) const { // Equivalent to left multiplication Transform2D copy = *this; @@ -257,67 +263,52 @@ Transform2D Transform2D::translated_local(const Vector2 &p_offset) const { return Transform2D(columns[0], columns[1], columns[2] + basis_xform(p_offset)); } -Transform2D Transform2D::rotated(const real_t p_angle) const { +Transform2D Transform2D::rotated(real_t p_angle) const { // Equivalent to left multiplication return Transform2D(p_angle, Vector2()) * (*this); } -Transform2D Transform2D::rotated_local(const real_t p_angle) const { +Transform2D Transform2D::rotated_local(real_t p_angle) const { // Equivalent to right multiplication return (*this) * Transform2D(p_angle, Vector2()); // Could be optimized, because origin transform can be skipped. } -real_t Transform2D::basis_determinant() const { +real_t Transform2D::determinant() const { return columns[0].x * columns[1].y - columns[0].y * columns[1].x; } -Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, const real_t p_c) const { - //extract parameters - Vector2 p1 = get_origin(); - Vector2 p2 = p_transform.get_origin(); - - real_t r1 = get_rotation(); - real_t r2 = p_transform.get_rotation(); - - Size2 s1 = get_scale(); - Size2 s2 = p_transform.get_scale(); - - //slerp rotation - Vector2 v1(Math::cos(r1), Math::sin(r1)); - Vector2 v2(Math::cos(r2), Math::sin(r2)); - - real_t dot = v1.dot(v2); - - dot = Math::clamp(dot, (real_t)-1.0, (real_t)1.0); - - Vector2 v; - - if (dot > 0.9995f) { - v = v1.lerp(v2, p_c).normalized(); //linearly interpolate to avoid numerical precision issues - } else { - real_t angle = p_c * Math::acos(dot); - Vector2 v3 = (v2 - v1 * dot).normalized(); - v = v1 * Math::cos(angle) + v3 * Math::sin(angle); - } - - //construct matrix - Transform2D res(v.angle(), p1.lerp(p2, p_c)); - res.scale_basis(s1.lerp(s2, p_c)); - return res; +Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, real_t p_weight) const { + return Transform2D( + Math::lerp_angle(get_rotation(), p_transform.get_rotation(), p_weight), + get_scale().lerp(p_transform.get_scale(), p_weight), + Math::lerp_angle(get_skew(), p_transform.get_skew(), p_weight), + get_origin().lerp(p_transform.get_origin(), p_weight)); } -void Transform2D::operator*=(const real_t p_val) { +void Transform2D::operator*=(real_t p_val) { columns[0] *= p_val; columns[1] *= p_val; columns[2] *= p_val; } -Transform2D Transform2D::operator*(const real_t p_val) const { +Transform2D Transform2D::operator*(real_t p_val) const { Transform2D ret(*this); ret *= p_val; return ret; } +void Transform2D::operator/=(real_t p_val) { + columns[0] /= p_val; + columns[1] /= p_val; + columns[2] /= p_val; +} + +Transform2D Transform2D::operator/(real_t p_val) const { + Transform2D ret(*this); + ret /= p_val; + return ret; +} + Transform2D::operator String() const { return "[X: " + columns[0].operator String() + ", Y: " + columns[1].operator String() + diff --git a/src/variant/transform3d.cpp b/src/variant/transform3d.cpp index d71e91911..765bc62e7 100644 --- a/src/variant/transform3d.cpp +++ b/src/variant/transform3d.cpp @@ -78,20 +78,20 @@ void Transform3D::rotate_basis(const Vector3 &p_axis, real_t p_angle) { basis.rotate(p_axis, p_angle); } -Transform3D Transform3D::looking_at(const Vector3 &p_target, const Vector3 &p_up) const { +Transform3D Transform3D::looking_at(const Vector3 &p_target, const Vector3 &p_up, bool p_use_model_front) const { #ifdef MATH_CHECKS ERR_FAIL_COND_V_MSG(origin.is_equal_approx(p_target), Transform3D(), "The transform's origin and target can't be equal."); #endif Transform3D t = *this; - t.basis = Basis::looking_at(p_target - origin, p_up); + t.basis = Basis::looking_at(p_target - origin, p_up, p_use_model_front); return t; } -void Transform3D::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up) { +void Transform3D::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up, bool p_use_model_front) { #ifdef MATH_CHECKS ERR_FAIL_COND_MSG(p_eye.is_equal_approx(p_target), "The eye and target vectors can't be equal."); #endif - basis = Basis::looking_at(p_target - p_eye, p_up); + basis = Basis::looking_at(p_target - p_eye, p_up, p_use_model_front); origin = p_eye; } @@ -198,17 +198,28 @@ Transform3D Transform3D::operator*(const Transform3D &p_transform) const { return t; } -void Transform3D::operator*=(const real_t p_val) { +void Transform3D::operator*=(real_t p_val) { origin *= p_val; basis *= p_val; } -Transform3D Transform3D::operator*(const real_t p_val) const { +Transform3D Transform3D::operator*(real_t p_val) const { Transform3D ret(*this); ret *= p_val; return ret; } +void Transform3D::operator/=(real_t p_val) { + basis /= p_val; + origin /= p_val; +} + +Transform3D Transform3D::operator/(real_t p_val) const { + Transform3D ret(*this); + ret /= p_val; + return ret; +} + Transform3D::operator String() const { return "[X: " + basis.get_column(0).operator String() + ", Y: " + basis.get_column(1).operator String() + @@ -228,9 +239,9 @@ Transform3D::Transform3D(const Vector3 &p_x, const Vector3 &p_y, const Vector3 & basis.set_column(2, p_z); } -Transform3D::Transform3D(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t ox, real_t oy, real_t oz) { - basis = Basis(xx, xy, xz, yx, yy, yz, zx, zy, zz); - origin = Vector3(ox, oy, oz); +Transform3D::Transform3D(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_zx, real_t p_zy, real_t p_zz, real_t p_ox, real_t p_oy, real_t p_oz) { + basis = Basis(p_xx, p_xy, p_xz, p_yx, p_yy, p_yz, p_zx, p_zy, p_zz); + origin = Vector3(p_ox, p_oy, p_oz); } } // namespace godot diff --git a/src/variant/vector2.cpp b/src/variant/vector2.cpp index 12201f1fd..cb190db12 100644 --- a/src/variant/vector2.cpp +++ b/src/variant/vector2.cpp @@ -39,7 +39,7 @@ real_t Vector2::angle() const { return Math::atan2(y, x); } -Vector2 Vector2::from_angle(const real_t p_angle) { +Vector2 Vector2::from_angle(real_t p_angle) { return Vector2(Math::cos(p_angle), Math::sin(p_angle)); } @@ -111,7 +111,7 @@ Vector2 Vector2::round() const { return Vector2(Math::round(x), Math::round(y)); } -Vector2 Vector2::rotated(const real_t p_by) const { +Vector2 Vector2::rotated(real_t p_by) const { real_t sine = Math::sin(p_by); real_t cosi = Math::cos(p_by); return Vector2( @@ -119,7 +119,7 @@ Vector2 Vector2::rotated(const real_t p_by) const { x * sine + y * cosi); } -Vector2 Vector2::posmod(const real_t p_mod) const { +Vector2 Vector2::posmod(real_t p_mod) const { return Vector2(Math::fposmod(x, p_mod), Math::fposmod(y, p_mod)); } @@ -155,7 +155,7 @@ Vector2 Vector2::snappedf(real_t p_step) const { Math::snapped(y, p_step)); } -Vector2 Vector2::limit_length(const real_t p_len) const { +Vector2 Vector2::limit_length(real_t p_len) const { const real_t l = length(); Vector2 v = *this; if (l > 0 && p_len < l) { @@ -166,7 +166,7 @@ Vector2 Vector2::limit_length(const real_t p_len) const { return v; } -Vector2 Vector2::move_toward(const Vector2 &p_to, const real_t p_delta) const { +Vector2 Vector2::move_toward(const Vector2 &p_to, real_t p_delta) const { Vector2 v = *this; Vector2 vd = p_to - v; real_t len = vd.length(); @@ -176,9 +176,9 @@ Vector2 Vector2::move_toward(const Vector2 &p_to, const real_t p_delta) const { // slide returns the component of the vector along the given plane, specified by its normal vector. Vector2 Vector2::slide(const Vector2 &p_normal) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector2(), "The normal Vector2 must be normalized."); + ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector2(), "The normal Vector2 " + p_normal.operator String() + "must be normalized."); #endif - return *this - p_normal * this->dot(p_normal); + return *this - p_normal * dot(p_normal); } Vector2 Vector2::bounce(const Vector2 &p_normal) const { @@ -187,9 +187,9 @@ Vector2 Vector2::bounce(const Vector2 &p_normal) const { Vector2 Vector2::reflect(const Vector2 &p_normal) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector2(), "The normal Vector2 must be normalized."); + ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector2(), "The normal Vector2 " + p_normal.operator String() + "must be normalized."); #endif - return 2.0f * p_normal * this->dot(p_normal) - *this; + return 2.0f * p_normal * dot(p_normal) - *this; } bool Vector2::is_equal_approx(const Vector2 &p_v) const { @@ -205,7 +205,7 @@ bool Vector2::is_finite() const { } Vector2::operator String() const { - return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ")"; + return "(" + String::num_real(x, true) + ", " + String::num_real(y, true) + ")"; } Vector2::operator Vector2i() const { diff --git a/src/variant/vector2i.cpp b/src/variant/vector2i.cpp index 4baff3bb3..d39cb7b4e 100644 --- a/src/variant/vector2i.cpp +++ b/src/variant/vector2i.cpp @@ -35,18 +35,6 @@ namespace godot { -Vector2i Vector2i::snapped(const Vector2i &p_step) const { - return Vector2i( - Math::snapped(x, p_step.x), - Math::snapped(y, p_step.y)); -} - -Vector2i Vector2i::snappedi(int32_t p_step) const { - return Vector2i( - Math::snapped(x, p_step), - Math::snapped(y, p_step)); -} - Vector2i Vector2i::clamp(const Vector2i &p_min, const Vector2i &p_max) const { return Vector2i( CLAMP(x, p_min.x, p_max.x), @@ -59,20 +47,24 @@ Vector2i Vector2i::clampi(int32_t p_min, int32_t p_max) const { CLAMP(y, p_min, p_max)); } -int64_t Vector2i::length_squared() const { - return x * (int64_t)x + y * (int64_t)y; +Vector2i Vector2i::snapped(const Vector2i &p_step) const { + return Vector2i( + Math::snapped(x, p_step.x), + Math::snapped(y, p_step.y)); } -double Vector2i::length() const { - return Math::sqrt((double)length_squared()); +Vector2i Vector2i::snappedi(int32_t p_step) const { + return Vector2i( + Math::snapped(x, p_step), + Math::snapped(y, p_step)); } -int64_t Vector2i::distance_squared_to(const Vector2i &p_to) const { - return (p_to - *this).length_squared(); +int64_t Vector2i::length_squared() const { + return x * (int64_t)x + y * (int64_t)y; } -double Vector2i::distance_to(const Vector2i &p_to) const { - return (p_to - *this).length(); +double Vector2i::length() const { + return Math::sqrt((double)length_squared()); } Vector2i Vector2i::operator+(const Vector2i &p_v) const { @@ -97,39 +89,39 @@ Vector2i Vector2i::operator*(const Vector2i &p_v1) const { return Vector2i(x * p_v1.x, y * p_v1.y); } -Vector2i Vector2i::operator*(const int32_t &rvalue) const { - return Vector2i(x * rvalue, y * rvalue); +Vector2i Vector2i::operator*(int32_t p_rvalue) const { + return Vector2i(x * p_rvalue, y * p_rvalue); } -void Vector2i::operator*=(const int32_t &rvalue) { - x *= rvalue; - y *= rvalue; +void Vector2i::operator*=(int32_t p_rvalue) { + x *= p_rvalue; + y *= p_rvalue; } Vector2i Vector2i::operator/(const Vector2i &p_v1) const { return Vector2i(x / p_v1.x, y / p_v1.y); } -Vector2i Vector2i::operator/(const int32_t &rvalue) const { - return Vector2i(x / rvalue, y / rvalue); +Vector2i Vector2i::operator/(int32_t p_rvalue) const { + return Vector2i(x / p_rvalue, y / p_rvalue); } -void Vector2i::operator/=(const int32_t &rvalue) { - x /= rvalue; - y /= rvalue; +void Vector2i::operator/=(int32_t p_rvalue) { + x /= p_rvalue; + y /= p_rvalue; } Vector2i Vector2i::operator%(const Vector2i &p_v1) const { return Vector2i(x % p_v1.x, y % p_v1.y); } -Vector2i Vector2i::operator%(const int32_t &rvalue) const { - return Vector2i(x % rvalue, y % rvalue); +Vector2i Vector2i::operator%(int32_t p_rvalue) const { + return Vector2i(x % p_rvalue, y % p_rvalue); } -void Vector2i::operator%=(const int32_t &rvalue) { - x %= rvalue; - y %= rvalue; +void Vector2i::operator%=(int32_t p_rvalue) { + x %= p_rvalue; + y %= p_rvalue; } Vector2i Vector2i::operator-() const { diff --git a/src/variant/vector3.cpp b/src/variant/vector3.cpp index d2ad6a9fa..fe42c189d 100644 --- a/src/variant/vector3.cpp +++ b/src/variant/vector3.cpp @@ -37,11 +37,11 @@ namespace godot { -void Vector3::rotate(const Vector3 &p_axis, const real_t p_angle) { +void Vector3::rotate(const Vector3 &p_axis, real_t p_angle) { *this = Basis(p_axis, p_angle).xform(*this); } -Vector3 Vector3::rotated(const Vector3 &p_axis, const real_t p_angle) const { +Vector3 Vector3::rotated(const Vector3 &p_axis, real_t p_angle) const { Vector3 r = *this; r.rotate(p_axis, p_angle); return r; @@ -61,31 +61,31 @@ Vector3 Vector3::clampf(real_t p_min, real_t p_max) const { CLAMP(z, p_min, p_max)); } -void Vector3::snap(const Vector3 p_step) { +void Vector3::snap(const Vector3 &p_step) { x = Math::snapped(x, p_step.x); y = Math::snapped(y, p_step.y); z = Math::snapped(z, p_step.z); } +Vector3 Vector3::snapped(const Vector3 &p_step) const { + Vector3 v = *this; + v.snap(p_step); + return v; +} + void Vector3::snapf(real_t p_step) { x = Math::snapped(x, p_step); y = Math::snapped(y, p_step); z = Math::snapped(z, p_step); } -Vector3 Vector3::snapped(const Vector3 p_step) const { - Vector3 v = *this; - v.snap(p_step); - return v; -} - Vector3 Vector3::snappedf(real_t p_step) const { Vector3 v = *this; v.snapf(p_step); return v; } -Vector3 Vector3::limit_length(const real_t p_len) const { +Vector3 Vector3::limit_length(real_t p_len) const { const real_t l = length(); Vector3 v = *this; if (l > 0 && p_len < l) { @@ -96,7 +96,7 @@ Vector3 Vector3::limit_length(const real_t p_len) const { return v; } -Vector3 Vector3::move_toward(const Vector3 &p_to, const real_t p_delta) const { +Vector3 Vector3::move_toward(const Vector3 &p_to, real_t p_delta) const { Vector3 v = *this; Vector3 vd = p_to - v; real_t len = vd.length(); @@ -122,23 +122,25 @@ Vector2 Vector3::octahedron_encode() const { Vector3 Vector3::octahedron_decode(const Vector2 &p_oct) { Vector2 f(p_oct.x * 2.0f - 1.0f, p_oct.y * 2.0f - 1.0f); Vector3 n(f.x, f.y, 1.0f - Math::abs(f.x) - Math::abs(f.y)); - float t = CLAMP(-n.z, 0.0f, 1.0f); + const real_t t = CLAMP(-n.z, 0.0f, 1.0f); n.x += n.x >= 0 ? -t : t; n.y += n.y >= 0 ? -t : t; return n.normalized(); } -Vector2 Vector3::octahedron_tangent_encode(const float sign) const { - Vector2 res = this->octahedron_encode(); +Vector2 Vector3::octahedron_tangent_encode(float p_sign) const { + const real_t bias = 1.0f / (real_t)32767.0f; + Vector2 res = octahedron_encode(); + res.y = MAX(res.y, bias); res.y = res.y * 0.5f + 0.5f; - res.y = sign >= 0.0f ? res.y : 1 - res.y; + res.y = p_sign >= 0.0f ? res.y : 1 - res.y; return res; } -Vector3 Vector3::octahedron_tangent_decode(const Vector2 &p_oct, float *sign) { +Vector3 Vector3::octahedron_tangent_decode(const Vector2 &p_oct, float *r_sign) { Vector2 oct_compressed = p_oct; oct_compressed.y = oct_compressed.y * 2 - 1; - *sign = oct_compressed.y >= 0.0f ? 1.0f : -1.0f; + *r_sign = oct_compressed.y >= 0.0f ? 1.0f : -1.0f; oct_compressed.y = Math::abs(oct_compressed.y); Vector3 res = Vector3::octahedron_decode(oct_compressed); return res; @@ -165,7 +167,7 @@ bool Vector3::is_finite() const { } Vector3::operator String() const { - return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ", " + String::num_real(z, false) + ")"; + return "(" + String::num_real(x, true) + ", " + String::num_real(y, true) + ", " + String::num_real(z, true) + ")"; } Vector3::operator Vector3i() const { diff --git a/src/variant/vector3i.cpp b/src/variant/vector3i.cpp index 7b25d8979..a1e7213b9 100644 --- a/src/variant/vector3i.cpp +++ b/src/variant/vector3i.cpp @@ -35,20 +35,6 @@ namespace godot { -Vector3i Vector3i::snapped(const Vector3i &p_step) const { - return Vector3i( - Math::snapped(x, p_step.x), - Math::snapped(y, p_step.y), - Math::snapped(z, p_step.z)); -} - -Vector3i Vector3i::snappedi(int32_t p_step) const { - return Vector3i( - Math::snapped(x, p_step), - Math::snapped(y, p_step), - Math::snapped(z, p_step)); -} - Vector3i::Axis Vector3i::min_axis_index() const { return x < y ? (x < z ? Vector3i::AXIS_X : Vector3i::AXIS_Z) : (y < z ? Vector3i::AXIS_Y : Vector3i::AXIS_Z); } @@ -71,6 +57,20 @@ Vector3i Vector3i::clampi(int32_t p_min, int32_t p_max) const { CLAMP(z, p_min, p_max)); } +Vector3i Vector3i::snapped(const Vector3i &p_step) const { + return Vector3i( + Math::snapped(x, p_step.x), + Math::snapped(y, p_step.y), + Math::snapped(z, p_step.z)); +} + +Vector3i Vector3i::snappedi(int32_t p_step) const { + return Vector3i( + Math::snapped(x, p_step), + Math::snapped(y, p_step), + Math::snapped(z, p_step)); +} + Vector3i::operator String() const { return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ")"; } diff --git a/src/variant/vector4.cpp b/src/variant/vector4.cpp index 2f1bb5926..9b58c9400 100644 --- a/src/variant/vector4.cpp +++ b/src/variant/vector4.cpp @@ -117,7 +117,7 @@ Vector4 Vector4::abs() const { } Vector4 Vector4::sign() const { - return Vector4(Math::sign(x), Math::sign(y), Math::sign(z), Math::sign(w)); + return Vector4(SIGN(x), SIGN(y), SIGN(z), SIGN(w)); } Vector4 Vector4::floor() const { @@ -132,15 +132,16 @@ Vector4 Vector4::round() const { return Vector4(Math::round(x), Math::round(y), Math::round(z), Math::round(w)); } -Vector4 Vector4::lerp(const Vector4 &p_to, const real_t p_weight) const { - return Vector4( - x + (p_weight * (p_to.x - x)), - y + (p_weight * (p_to.y - y)), - z + (p_weight * (p_to.z - z)), - w + (p_weight * (p_to.w - w))); +Vector4 Vector4::lerp(const Vector4 &p_to, real_t p_weight) const { + Vector4 res = *this; + res.x = Math::lerp(res.x, p_to.x, p_weight); + res.y = Math::lerp(res.y, p_to.y, p_weight); + res.z = Math::lerp(res.z, p_to.z, p_weight); + res.w = Math::lerp(res.w, p_to.w, p_weight); + return res; } -Vector4 Vector4::cubic_interpolate(const Vector4 &p_b, const Vector4 &p_pre_a, const Vector4 &p_post_b, const real_t p_weight) const { +Vector4 Vector4::cubic_interpolate(const Vector4 &p_b, const Vector4 &p_pre_a, const Vector4 &p_post_b, real_t p_weight) const { Vector4 res = *this; res.x = Math::cubic_interpolate(res.x, p_b.x, p_pre_a.x, p_post_b.x, p_weight); res.y = Math::cubic_interpolate(res.y, p_b.y, p_pre_a.y, p_post_b.y, p_weight); @@ -149,7 +150,7 @@ Vector4 Vector4::cubic_interpolate(const Vector4 &p_b, const Vector4 &p_pre_a, c return res; } -Vector4 Vector4::cubic_interpolate_in_time(const Vector4 &p_b, const Vector4 &p_pre_a, const Vector4 &p_post_b, const real_t p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const { +Vector4 Vector4::cubic_interpolate_in_time(const Vector4 &p_b, const Vector4 &p_pre_a, const Vector4 &p_post_b, real_t p_weight, real_t p_b_t, real_t p_pre_a_t, real_t p_post_b_t) const { Vector4 res = *this; res.x = Math::cubic_interpolate_in_time(res.x, p_b.x, p_pre_a.x, p_post_b.x, p_weight, p_b_t, p_pre_a_t, p_post_b_t); res.y = Math::cubic_interpolate_in_time(res.y, p_b.y, p_pre_a.y, p_post_b.y, p_weight, p_b_t, p_pre_a_t, p_post_b_t); @@ -158,7 +159,7 @@ Vector4 Vector4::cubic_interpolate_in_time(const Vector4 &p_b, const Vector4 &p_ return res; } -Vector4 Vector4::posmod(const real_t p_mod) const { +Vector4 Vector4::posmod(real_t p_mod) const { return Vector4(Math::fposmod(x, p_mod), Math::fposmod(y, p_mod), Math::fposmod(z, p_mod), Math::fposmod(w, p_mod)); } @@ -213,9 +214,13 @@ Vector4 Vector4::clampf(real_t p_min, real_t p_max) const { } Vector4::operator String() const { - return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ", " + String::num_real(z, false) + ", " + String::num_real(w, false) + ")"; + return "(" + String::num_real(x, true) + ", " + String::num_real(y, true) + ", " + String::num_real(z, true) + ", " + String::num_real(w, true) + ")"; } static_assert(sizeof(Vector4) == 4 * sizeof(real_t)); +Vector4::operator Vector4i() const { + return Vector4i(x, y, z, w); +} + } // namespace godot diff --git a/src/variant/vector4i.cpp b/src/variant/vector4i.cpp index b0e330ca2..d138610d9 100644 --- a/src/variant/vector4i.cpp +++ b/src/variant/vector4i.cpp @@ -35,22 +35,6 @@ namespace godot { -Vector4i Vector4i::snapped(const Vector4i &p_step) const { - return Vector4i( - Math::snapped(x, p_step.x), - Math::snapped(y, p_step.y), - Math::snapped(z, p_step.z), - Math::snapped(w, p_step.w)); -} - -Vector4i Vector4i::snappedi(int32_t p_step) const { - return Vector4i( - Math::snapped(x, p_step), - Math::snapped(y, p_step), - Math::snapped(z, p_step), - Math::snapped(w, p_step)); -} - Vector4i::Axis Vector4i::min_axis_index() const { uint32_t min_index = 0; int32_t min_value = x; @@ -91,6 +75,22 @@ Vector4i Vector4i::clampi(int32_t p_min, int32_t p_max) const { CLAMP(w, p_min, p_max)); } +Vector4i Vector4i::snapped(const Vector4i &p_step) const { + return Vector4i( + Math::snapped(x, p_step.x), + Math::snapped(y, p_step.y), + Math::snapped(z, p_step.z), + Math::snapped(w, p_step.w)); +} + +Vector4i Vector4i::snappedi(int32_t p_step) const { + return Vector4i( + Math::snapped(x, p_step), + Math::snapped(y, p_step), + Math::snapped(z, p_step), + Math::snapped(w, p_step)); +} + Vector4i::operator String() const { return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ", " + itos(w) + ")"; } From 0a39efe3d32ec68902ee4bc16c9d97e830188ba9 Mon Sep 17 00:00:00 2001 From: David Snopek Date: Tue, 25 Feb 2025 09:29:22 -0600 Subject: [PATCH 06/41] Synchronize most shared template code with Godot 4.4 (cherry picked from commit 1edfca295b87e37c675a7dac1dddd4e87739ea26) --- include/godot_cpp/templates/cowdata.hpp | 139 +++++++++----- include/godot_cpp/templates/hash_map.hpp | 127 +++++++++++-- include/godot_cpp/templates/hash_set.hpp | 46 +++-- include/godot_cpp/templates/hashfuncs.hpp | 167 ++++++++++++++--- include/godot_cpp/templates/list.hpp | 76 ++++++-- include/godot_cpp/templates/local_vector.hpp | 104 ++++++++--- include/godot_cpp/templates/pair.hpp | 9 + include/godot_cpp/templates/rb_map.hpp | 30 ++- include/godot_cpp/templates/rb_set.hpp | 10 +- include/godot_cpp/templates/safe_refcount.hpp | 173 ++++-------------- include/godot_cpp/templates/search_array.hpp | 10 +- include/godot_cpp/templates/self_list.hpp | 68 ++++++- include/godot_cpp/templates/sort_array.hpp | 78 ++++---- include/godot_cpp/templates/vector.hpp | 28 +-- include/godot_cpp/templates/vmap.hpp | 15 +- include/godot_cpp/templates/vset.hpp | 14 +- 16 files changed, 725 insertions(+), 369 deletions(-) diff --git a/include/godot_cpp/templates/cowdata.hpp b/include/godot_cpp/templates/cowdata.hpp index 68918f7ac..39ba5c8e7 100644 --- a/include/godot_cpp/templates/cowdata.hpp +++ b/include/godot_cpp/templates/cowdata.hpp @@ -37,8 +37,10 @@ #include #include +#include #include #include +#include namespace godot { @@ -166,13 +168,25 @@ class CowData { return *out; } - void _unref(void *p_data); + // Decrements the reference count. Deallocates the backing buffer if needed. + // After this function, _ptr is guaranteed to be NULL. + void _unref(); void _ref(const CowData *p_from); void _ref(const CowData &p_from); USize _copy_on_write(); + Error _realloc(Size p_alloc_size); public: void operator=(const CowData &p_from) { _ref(p_from); } + void operator=(CowData &&p_from) { + if (_ptr == p_from._ptr) { + return; + } + + _unref(); + _ptr = p_from._ptr; + p_from._ptr = nullptr; + } _FORCE_INLINE_ T *ptrw() { _copy_on_write(); @@ -221,19 +235,22 @@ class CowData { T *p = ptrw(); Size len = size(); for (Size i = p_index; i < len - 1; i++) { - p[i] = p[i + 1]; + p[i] = std::move(p[i + 1]); } resize(len - 1); } Error insert(Size p_pos, const T &p_val) { - ERR_FAIL_INDEX_V(p_pos, size() + 1, ERR_INVALID_PARAMETER); - resize(size() + 1); - for (Size i = (size() - 1); i > p_pos; i--) { - set(i, get(i - 1)); + Size new_size = size() + 1; + ERR_FAIL_INDEX_V(p_pos, new_size, ERR_INVALID_PARAMETER); + Error err = resize(new_size); + ERR_FAIL_COND_V(err, err); + T *p = ptrw(); + for (Size i = new_size - 1; i > p_pos; i--) { + p[i] = std::move(p[i - 1]); } - set(p_pos, p_val); + p[p_pos] = p_val; return OK; } @@ -243,35 +260,47 @@ class CowData { Size count(const T &p_val) const; _FORCE_INLINE_ CowData() {} - _FORCE_INLINE_ ~CowData(); - _FORCE_INLINE_ CowData(CowData &p_from) { _ref(p_from); }; + _FORCE_INLINE_ ~CowData() { _unref(); } + _FORCE_INLINE_ CowData(std::initializer_list p_init); + _FORCE_INLINE_ CowData(const CowData &p_from) { _ref(p_from); } + _FORCE_INLINE_ CowData(CowData &&p_from) { + _ptr = p_from._ptr; + p_from._ptr = nullptr; + } }; template -void CowData::_unref(void *p_data) { - if (!p_data) { +void CowData::_unref() { + if (!_ptr) { return; } SafeNumeric *refc = _get_refcount(); - if (refc->decrement() > 0) { - return; // still in use + // Data is still in use elsewhere. + _ptr = nullptr; + return; } - // clean up + // Clean up. + // First, invalidate our own reference. + // NOTE: It is required to do so immediately because it must not be observable outside of this + // function after refcount has already been reduced to 0. + // WARNING: It must be done before calling the destructors, because one of them may otherwise + // observe it through a reference to us. In this case, it may try to access the buffer, + // which is illegal after some of the elements in it have already been destructed, and + // may lead to a segmentation fault. + USize current_size = *_get_size(); + T *prev_ptr = _ptr; + _ptr = nullptr; if constexpr (!std::is_trivially_destructible_v) { - USize *count = _get_size(); - T *data = (T *)(count + 1); - - for (USize i = 0; i < *count; ++i) { - // call destructors - data[i].~T(); + for (USize i = 0; i < current_size; ++i) { + prev_ptr[i].~T(); } } // free mem - Memory::free_static(((uint8_t *)p_data) - DATA_OFFSET, false); + Memory::free_static((uint8_t *)prev_ptr - DATA_OFFSET, false); } template @@ -306,7 +335,7 @@ typename CowData::USize CowData::_copy_on_write() { } } - _unref(_ptr); + _unref(); _ptr = _data_ptr; rc = 1; @@ -326,14 +355,13 @@ Error CowData::resize(Size p_size) { } if (p_size == 0) { - // wants to clean up - _unref(_ptr); - _ptr = nullptr; + // Wants to clean up. + _unref(); // Resets _ptr to nullptr. return OK; } // possibly changing size, copy on write - USize rc = _copy_on_write(); + _copy_on_write(); USize current_alloc_size = _get_alloc_size(current_size); USize alloc_size; @@ -354,16 +382,12 @@ Error CowData::resize(Size p_size) { *(_size_ptr) = 0; //size, currently none _ptr = _data_ptr; - } else { - uint8_t *mem_new = (uint8_t *)Memory::realloc_static(((uint8_t *)_ptr) - DATA_OFFSET, alloc_size + DATA_OFFSET, false); - ERR_FAIL_NULL_V(mem_new, ERR_OUT_OF_MEMORY); - - SafeNumeric *_refc_ptr = _get_refcount_ptr(mem_new); - T *_data_ptr = _get_data_ptr(mem_new); - new (_refc_ptr) SafeNumeric(rc); //refcount - - _ptr = _data_ptr; + } else { + const Error error = _realloc(alloc_size); + if (error) { + return error; + } } } @@ -389,15 +413,10 @@ Error CowData::resize(Size p_size) { } if (alloc_size != current_alloc_size) { - uint8_t *mem_new = (uint8_t *)Memory::realloc_static(((uint8_t *)_ptr) - DATA_OFFSET, alloc_size + DATA_OFFSET, false); - ERR_FAIL_NULL_V(mem_new, ERR_OUT_OF_MEMORY); - - SafeNumeric *_refc_ptr = _get_refcount_ptr(mem_new); - T *_data_ptr = _get_data_ptr(mem_new); - - new (_refc_ptr) SafeNumeric(rc); //refcount - - _ptr = _data_ptr; + const Error error = _realloc(alloc_size); + if (error) { + return error; + } } *_get_size() = p_size; @@ -406,6 +425,21 @@ Error CowData::resize(Size p_size) { return OK; } +template +Error CowData::_realloc(Size p_alloc_size) { + uint8_t *mem_new = (uint8_t *)Memory::realloc_static(((uint8_t *)_ptr) - DATA_OFFSET, p_alloc_size + DATA_OFFSET, false); + ERR_FAIL_NULL_V(mem_new, ERR_OUT_OF_MEMORY); + + SafeNumeric *_refc_ptr = _get_refcount_ptr(mem_new); + T *_data_ptr = _get_data_ptr(mem_new); + + // If we realloc, we're guaranteed to be the only reference. + new (_refc_ptr) SafeNumeric(1); + _ptr = _data_ptr; + + return OK; +} + template typename CowData::Size CowData::find(const T &p_val, Size p_from) const { Size ret = -1; @@ -465,11 +499,10 @@ void CowData::_ref(const CowData &p_from) { return; // self assign, do nothing. } - _unref(_ptr); - _ptr = nullptr; + _unref(); // Resets _ptr to nullptr. if (!p_from._ptr) { - return; // nothing to do + return; //nothing to do } if (p_from._get_refcount()->conditional_increment() > 0) { // could reference @@ -478,8 +511,16 @@ void CowData::_ref(const CowData &p_from) { } template -CowData::~CowData() { - _unref(_ptr); +CowData::CowData(std::initializer_list p_init) { + Error err = resize(p_init.size()); + if (err != OK) { + return; + } + + Size i = 0; + for (const T &element : p_init) { + set(i++, element); + } } #if defined(__GNUC__) && !defined(__clang__) diff --git a/include/godot_cpp/templates/hash_map.hpp b/include/godot_cpp/templates/hash_map.hpp index 67dfb4e77..a0a8cadab 100644 --- a/include/godot_cpp/templates/hash_map.hpp +++ b/include/godot_cpp/templates/hash_map.hpp @@ -61,15 +61,17 @@ struct HashMapElement { data(p_key, p_value) {} }; +bool _hashmap_variant_less_than(const Variant &p_left, const Variant &p_right); + template , typename Allocator = DefaultTypedAllocator>> class HashMap { public: - const uint32_t MIN_CAPACITY_INDEX = 2; // Use a prime. - const float MAX_OCCUPANCY = 0.75; - const uint32_t EMPTY_HASH = 0; + static constexpr uint32_t MIN_CAPACITY_INDEX = 2; // Use a prime. + static constexpr float MAX_OCCUPANCY = 0.75; + static constexpr uint32_t EMPTY_HASH = 0; private: Allocator element_alloc; @@ -91,19 +93,20 @@ class HashMap { return hash; } - _FORCE_INLINE_ uint32_t _get_probe_length(uint32_t p_pos, uint32_t p_hash, uint32_t p_capacity) const { - uint32_t original_pos = p_hash % p_capacity; - return (p_pos - original_pos + p_capacity) % p_capacity; + static _FORCE_INLINE_ uint32_t _get_probe_length(const uint32_t p_pos, const uint32_t p_hash, const uint32_t p_capacity, const uint64_t p_capacity_inv) { + const uint32_t original_pos = fastmod(p_hash, p_capacity_inv, p_capacity); + return fastmod(p_pos - original_pos + p_capacity, p_capacity_inv, p_capacity); } bool _lookup_pos(const TKey &p_key, uint32_t &r_pos) const { - if (elements == nullptr) { + if (elements == nullptr || num_elements == 0) { return false; // Failed lookups, no elements } - uint32_t capacity = hash_table_size_primes[capacity_index]; + const uint32_t capacity = hash_table_size_primes[capacity_index]; + const uint64_t capacity_inv = hash_table_size_primes_inv[capacity_index]; uint32_t hash = _hash(p_key); - uint32_t pos = hash % capacity; + uint32_t pos = fastmod(hash, capacity_inv, capacity); uint32_t distance = 0; while (true) { @@ -111,7 +114,7 @@ class HashMap { return false; } - if (distance > _get_probe_length(pos, hashes[pos], capacity)) { + if (distance > _get_probe_length(pos, hashes[pos], capacity, capacity_inv)) { return false; } @@ -120,17 +123,18 @@ class HashMap { return true; } - pos = (pos + 1) % capacity; + pos = fastmod((pos + 1), capacity_inv, capacity); distance++; } } void _insert_with_hash(uint32_t p_hash, HashMapElement *p_value) { - uint32_t capacity = hash_table_size_primes[capacity_index]; + const uint32_t capacity = hash_table_size_primes[capacity_index]; + const uint64_t capacity_inv = hash_table_size_primes_inv[capacity_index]; uint32_t hash = p_hash; HashMapElement *value = p_value; uint32_t distance = 0; - uint32_t pos = hash % capacity; + uint32_t pos = fastmod(hash, capacity_inv, capacity); while (true) { if (hashes[pos] == EMPTY_HASH) { @@ -143,14 +147,14 @@ class HashMap { } // Not an empty slot, let's check the probing length of the existing one. - uint32_t existing_probe_len = _get_probe_length(pos, hashes[pos], capacity); + uint32_t existing_probe_len = _get_probe_length(pos, hashes[pos], capacity, capacity_inv); if (existing_probe_len < distance) { SWAP(hash, hashes[pos]); SWAP(value, elements[pos]); distance = existing_probe_len; } - pos = (pos + 1) % capacity; + pos = fastmod((pos + 1), capacity_inv, capacity); distance++; } } @@ -250,7 +254,7 @@ class HashMap { } void clear() { - if (elements == nullptr) { + if (elements == nullptr || num_elements == 0) { return; } uint32_t capacity = hash_table_size_primes[capacity_index]; @@ -269,6 +273,47 @@ class HashMap { num_elements = 0; } + void sort() { + if (elements == nullptr || num_elements < 2) { + return; // An empty or single element HashMap is already sorted. + } + // Use insertion sort because we want this operation to be fast for the + // common case where the input is already sorted or nearly sorted. + HashMapElement *inserting = head_element->next; + while (inserting != nullptr) { + HashMapElement *after = nullptr; + for (HashMapElement *current = inserting->prev; current != nullptr; current = current->prev) { + if (_hashmap_variant_less_than(inserting->data.key, current->data.key)) { + after = current; + } else { + break; + } + } + HashMapElement *next = inserting->next; + if (after != nullptr) { + // Modify the elements around `inserting` to remove it from its current position. + inserting->prev->next = next; + if (next == nullptr) { + tail_element = inserting->prev; + } else { + next->prev = inserting->prev; + } + // Modify `before` and `after` to insert `inserting` between them. + HashMapElement *before = after->prev; + if (before == nullptr) { + head_element = inserting; + } else { + before->next = inserting; + } + after->prev = inserting; + // Point `inserting` to its new surroundings. + inserting->prev = before; + inserting->next = after; + } + inserting = next; + } + } + TValue &get(const TKey &p_key) { uint32_t pos = 0; bool exists = _lookup_pos(p_key, pos); @@ -316,13 +361,14 @@ class HashMap { return false; } - uint32_t capacity = hash_table_size_primes[capacity_index]; - uint32_t next_pos = (pos + 1) % capacity; - while (hashes[next_pos] != EMPTY_HASH && _get_probe_length(next_pos, hashes[next_pos], capacity) != 0) { + const uint32_t capacity = hash_table_size_primes[capacity_index]; + const uint64_t capacity_inv = hash_table_size_primes_inv[capacity_index]; + uint32_t next_pos = fastmod((pos + 1), capacity_inv, capacity); + while (hashes[next_pos] != EMPTY_HASH && _get_probe_length(next_pos, hashes[next_pos], capacity, capacity_inv) != 0) { SWAP(hashes[next_pos], hashes[pos]); SWAP(elements[next_pos], elements[pos]); pos = next_pos; - next_pos = (pos + 1) % capacity; + next_pos = fastmod((pos + 1), capacity_inv, capacity); } hashes[pos] = EMPTY_HASH; @@ -350,6 +396,40 @@ class HashMap { return true; } + // Replace the key of an entry in-place, without invalidating iterators or changing the entries position during iteration. + // p_old_key must exist in the map and p_new_key must not, unless it is equal to p_old_key. + bool replace_key(const TKey &p_old_key, const TKey &p_new_key) { + if (p_old_key == p_new_key) { + return true; + } + uint32_t pos = 0; + ERR_FAIL_COND_V(_lookup_pos(p_new_key, pos), false); + ERR_FAIL_COND_V(!_lookup_pos(p_old_key, pos), false); + HashMapElement *element = elements[pos]; + + // Delete the old entries in hashes and elements. + const uint32_t capacity = hash_table_size_primes[capacity_index]; + const uint64_t capacity_inv = hash_table_size_primes_inv[capacity_index]; + uint32_t next_pos = fastmod((pos + 1), capacity_inv, capacity); + while (hashes[next_pos] != EMPTY_HASH && _get_probe_length(next_pos, hashes[next_pos], capacity, capacity_inv) != 0) { + SWAP(hashes[next_pos], hashes[pos]); + SWAP(elements[next_pos], elements[pos]); + pos = next_pos; + next_pos = fastmod((pos + 1), capacity_inv, capacity); + } + hashes[pos] = EMPTY_HASH; + elements[pos] = nullptr; + // _insert_with_hash will increment this again. + num_elements--; + + // Update the HashMapElement with the new key and reinsert it. + const_cast(element->data.key) = p_new_key; + uint32_t hash = _hash(p_new_key); + _insert_with_hash(hash, element); + + return true; + } + // Reserves space for a number of elements, useful to avoid many resizes and rehashes. // If adding a known (possibly large) number of elements at once, must be larger than old capacity. void reserve(uint32_t p_new_capacity) { @@ -560,6 +640,13 @@ class HashMap { capacity_index = MIN_CAPACITY_INDEX; } + HashMap(std::initializer_list> p_init) { + reserve(p_init.size()); + for (const KeyValue &E : p_init) { + insert(E.key, E.value); + } + } + uint32_t debug_get_hash(uint32_t p_index) { if (num_elements == 0) { return 0; diff --git a/include/godot_cpp/templates/hash_set.hpp b/include/godot_cpp/templates/hash_set.hpp index 67ba443aa..a4eb68546 100644 --- a/include/godot_cpp/templates/hash_set.hpp +++ b/include/godot_cpp/templates/hash_set.hpp @@ -75,19 +75,20 @@ class HashSet { return hash; } - _FORCE_INLINE_ uint32_t _get_probe_length(uint32_t p_pos, uint32_t p_hash, uint32_t p_capacity) const { - uint32_t original_pos = p_hash % p_capacity; - return (p_pos - original_pos + p_capacity) % p_capacity; + static _FORCE_INLINE_ uint32_t _get_probe_length(const uint32_t p_pos, const uint32_t p_hash, const uint32_t p_capacity, const uint64_t p_capacity_inv) { + const uint32_t original_pos = fastmod(p_hash, p_capacity_inv, p_capacity); + return fastmod(p_pos - original_pos + p_capacity, p_capacity_inv, p_capacity); } bool _lookup_pos(const TKey &p_key, uint32_t &r_pos) const { - if (keys == nullptr) { + if (keys == nullptr || num_elements == 0) { return false; // Failed lookups, no elements } - uint32_t capacity = hash_table_size_primes[capacity_index]; + const uint32_t capacity = hash_table_size_primes[capacity_index]; + const uint64_t capacity_inv = hash_table_size_primes_inv[capacity_index]; uint32_t hash = _hash(p_key); - uint32_t pos = hash % capacity; + uint32_t pos = fastmod(hash, capacity_inv, capacity); uint32_t distance = 0; while (true) { @@ -95,7 +96,7 @@ class HashSet { return false; } - if (distance > _get_probe_length(pos, hashes[pos], capacity)) { + if (distance > _get_probe_length(pos, hashes[pos], capacity, capacity_inv)) { return false; } @@ -104,17 +105,18 @@ class HashSet { return true; } - pos = (pos + 1) % capacity; + pos = fastmod(pos + 1, capacity_inv, capacity); distance++; } } uint32_t _insert_with_hash(uint32_t p_hash, uint32_t p_index) { - uint32_t capacity = hash_table_size_primes[capacity_index]; + const uint32_t capacity = hash_table_size_primes[capacity_index]; + const uint64_t capacity_inv = hash_table_size_primes_inv[capacity_index]; uint32_t hash = p_hash; uint32_t index = p_index; uint32_t distance = 0; - uint32_t pos = hash % capacity; + uint32_t pos = fastmod(hash, capacity_inv, capacity); while (true) { if (hashes[pos] == EMPTY_HASH) { @@ -125,7 +127,7 @@ class HashSet { } // Not an empty slot, let's check the probing length of the existing one. - uint32_t existing_probe_len = _get_probe_length(pos, hashes[pos], capacity); + uint32_t existing_probe_len = _get_probe_length(pos, hashes[pos], capacity, capacity_inv); if (existing_probe_len < distance) { key_to_hash[index] = pos; SWAP(hash, hashes[pos]); @@ -133,7 +135,7 @@ class HashSet { distance = existing_probe_len; } - pos = (pos + 1) % capacity; + pos = fastmod(pos + 1, capacity_inv, capacity); distance++; } } @@ -236,7 +238,7 @@ class HashSet { } void clear() { - if (keys == nullptr) { + if (keys == nullptr || num_elements == 0) { return; } uint32_t capacity = hash_table_size_primes[capacity_index]; @@ -264,11 +266,12 @@ class HashSet { } uint32_t key_pos = pos; - pos = key_to_hash[pos]; // make hash pos + pos = key_to_hash[pos]; //make hash pos - uint32_t capacity = hash_table_size_primes[capacity_index]; - uint32_t next_pos = (pos + 1) % capacity; - while (hashes[next_pos] != EMPTY_HASH && _get_probe_length(next_pos, hashes[next_pos], capacity) != 0) { + const uint32_t capacity = hash_table_size_primes[capacity_index]; + const uint64_t capacity_inv = hash_table_size_primes_inv[capacity_index]; + uint32_t next_pos = fastmod(pos + 1, capacity_inv, capacity); + while (hashes[next_pos] != EMPTY_HASH && _get_probe_length(next_pos, hashes[next_pos], capacity, capacity_inv) != 0) { uint32_t kpos = hash_to_key[pos]; uint32_t kpos_next = hash_to_key[next_pos]; SWAP(key_to_hash[kpos], key_to_hash[kpos_next]); @@ -276,7 +279,7 @@ class HashSet { SWAP(hash_to_key[next_pos], hash_to_key[pos]); pos = next_pos; - next_pos = (pos + 1) % capacity; + next_pos = fastmod(pos + 1, capacity_inv, capacity); } hashes[pos] = EMPTY_HASH; @@ -443,6 +446,13 @@ class HashSet { capacity_index = MIN_CAPACITY_INDEX; } + HashSet(std::initializer_list p_init) { + reserve(p_init.size()); + for (const TKey &E : p_init) { + insert(E); + } + } + void reset() { clear(); diff --git a/include/godot_cpp/templates/hashfuncs.hpp b/include/godot_cpp/templates/hashfuncs.hpp index 3fcedb693..566b8c71a 100644 --- a/include/godot_cpp/templates/hashfuncs.hpp +++ b/include/godot_cpp/templates/hashfuncs.hpp @@ -66,10 +66,11 @@ namespace godot { static _FORCE_INLINE_ uint32_t hash_djb2(const char *p_cstr) { const unsigned char *chr = (const unsigned char *)p_cstr; uint32_t hash = 5381; - uint32_t c; + uint32_t c = *chr++; - while ((c = *chr++)) { + while (c) { hash = ((hash << 5) + hash) ^ c; /* hash * 33 ^ c */ + c = *chr++; } return hash; @@ -107,6 +108,16 @@ static _FORCE_INLINE_ uint32_t hash_one_uint64(const uint64_t p_int) { return uint32_t(v); } +static _FORCE_INLINE_ uint64_t hash64_murmur3_64(uint64_t key, uint64_t seed) { + key ^= seed; + key ^= key >> 33; + key *= 0xff51afd7ed558ccd; + key ^= key >> 33; + key *= 0xc4ceb9fe1a85ec53; + key ^= key >> 33; + return key; +} + #define HASH_MURMUR3_SEED 0x7F07C65 // Murmurhash3 32-bit version. // All MurmurHash versions are public domain software, and the author disclaims all copyright to their code. @@ -227,7 +238,7 @@ static _FORCE_INLINE_ uint32_t hash_murmur3_buffer(const void *key, int length, k1 = hash_rotl32(k1, 15); k1 *= c2; h1 ^= k1; - } + }; // Finalize with additional bit mixing. h1 ^= length; @@ -310,40 +321,41 @@ struct HashMapHasherDefault { static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); } static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); } - static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return hash_fmix32(p_wchar); } - static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return hash_fmix32(p_uchar); } - static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return hash_fmix32(p_uchar); } + static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return hash_fmix32(uint32_t(p_wchar)); } + static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return hash_fmix32(uint32_t(p_uchar)); } + static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return hash_fmix32(uint32_t(p_uchar)); } static _FORCE_INLINE_ uint32_t hash(const RID &p_rid) { return hash_one_uint64(p_rid.get_id()); } + static _FORCE_INLINE_ uint32_t hash(const CharString &p_char_string) { return hash_djb2(p_char_string.get_data()); } static _FORCE_INLINE_ uint32_t hash(const StringName &p_string_name) { return p_string_name.hash(); } static _FORCE_INLINE_ uint32_t hash(const NodePath &p_path) { return p_path.hash(); } static _FORCE_INLINE_ uint32_t hash(const ObjectID &p_id) { return hash_one_uint64(p_id); } static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); } - static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash_one_uint64(p_int); } + static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash_one_uint64(uint64_t(p_int)); } static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_murmur3_one_float(p_float); } static _FORCE_INLINE_ uint32_t hash(const double p_double) { return hash_murmur3_one_double(p_double); } static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return hash_fmix32(p_int); } - static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return hash_fmix32(p_int); } - static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return hash_fmix32(p_int); } - static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return hash_fmix32(p_int); } - static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return hash_fmix32(p_int); } - static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return hash_fmix32(p_int); } + static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return hash_fmix32(uint32_t(p_int)); } + static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return hash_fmix32(uint32_t(p_int)); } + static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return hash_fmix32(uint32_t(p_int)); } + static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return hash_fmix32(uint32_t(p_int)); } + static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return hash_fmix32(uint32_t(p_int)); } static _FORCE_INLINE_ uint32_t hash(const Vector2i &p_vec) { - uint32_t h = hash_murmur3_one_32(p_vec.x); - h = hash_murmur3_one_32(p_vec.y, h); + uint32_t h = hash_murmur3_one_32(uint32_t(p_vec.x)); + h = hash_murmur3_one_32(uint32_t(p_vec.y), h); return hash_fmix32(h); } static _FORCE_INLINE_ uint32_t hash(const Vector3i &p_vec) { - uint32_t h = hash_murmur3_one_32(p_vec.x); - h = hash_murmur3_one_32(p_vec.y, h); - h = hash_murmur3_one_32(p_vec.z, h); + uint32_t h = hash_murmur3_one_32(uint32_t(p_vec.x)); + h = hash_murmur3_one_32(uint32_t(p_vec.y), h); + h = hash_murmur3_one_32(uint32_t(p_vec.z), h); return hash_fmix32(h); } static _FORCE_INLINE_ uint32_t hash(const Vector4i &p_vec) { - uint32_t h = hash_murmur3_one_32(p_vec.x); - h = hash_murmur3_one_32(p_vec.y, h); - h = hash_murmur3_one_32(p_vec.z, h); - h = hash_murmur3_one_32(p_vec.w, h); + uint32_t h = hash_murmur3_one_32(uint32_t(p_vec.x)); + h = hash_murmur3_one_32(uint32_t(p_vec.y), h); + h = hash_murmur3_one_32(uint32_t(p_vec.z), h); + h = hash_murmur3_one_32(uint32_t(p_vec.w), h); return hash_fmix32(h); } static _FORCE_INLINE_ uint32_t hash(const Vector2 &p_vec) { @@ -365,10 +377,10 @@ struct HashMapHasherDefault { return hash_fmix32(h); } static _FORCE_INLINE_ uint32_t hash(const Rect2i &p_rect) { - uint32_t h = hash_murmur3_one_32(p_rect.position.x); - h = hash_murmur3_one_32(p_rect.position.y, h); - h = hash_murmur3_one_32(p_rect.size.x, h); - h = hash_murmur3_one_32(p_rect.size.y, h); + uint32_t h = hash_murmur3_one_32(uint32_t(p_rect.position.x)); + h = hash_murmur3_one_32(uint32_t(p_rect.position.y), h); + h = hash_murmur3_one_32(uint32_t(p_rect.size.x), h); + h = hash_murmur3_one_32(uint32_t(p_rect.size.y), h); return hash_fmix32(h); } static _FORCE_INLINE_ uint32_t hash(const Rect2 &p_rect) { @@ -389,6 +401,19 @@ struct HashMapHasherDefault { } }; +struct HashHasher { + static _FORCE_INLINE_ uint32_t hash(const int32_t hash) { return hash; } + static _FORCE_INLINE_ uint32_t hash(const uint32_t hash) { return hash; } + static _FORCE_INLINE_ uint64_t hash(const int64_t hash) { return hash; } + static _FORCE_INLINE_ uint64_t hash(const uint64_t hash) { return hash; } +}; + +// TODO: Fold this into HashMapHasherDefault once C++20 concepts are allowed +template +struct HashableHasher { + static _FORCE_INLINE_ uint32_t hash(const T &hashable) { return hashable.hash(); } +}; + template struct HashMapComparatorDefault { static bool compare(const T &p_lhs, const T &p_rhs) { @@ -410,6 +435,13 @@ struct HashMapComparatorDefault { } }; +template <> +struct HashMapComparatorDefault { + static bool compare(const Color &p_lhs, const Color &p_rhs) { + return ((p_lhs.r == p_rhs.r) || (Math::is_nan(p_lhs.r) && Math::is_nan(p_rhs.r))) && ((p_lhs.g == p_rhs.g) || (Math::is_nan(p_lhs.g) && Math::is_nan(p_rhs.g))) && ((p_lhs.b == p_rhs.b) || (Math::is_nan(p_lhs.b) && Math::is_nan(p_rhs.b))) && ((p_lhs.a == p_rhs.a) || (Math::is_nan(p_lhs.a) && Math::is_nan(p_rhs.a))); + } +}; + template <> struct HashMapComparatorDefault { static bool compare(const Vector2 &p_lhs, const Vector2 &p_rhs) { @@ -424,9 +456,90 @@ struct HashMapComparatorDefault { } }; +template <> +struct HashMapComparatorDefault { + static bool compare(const Vector4 &p_lhs, const Vector4 &p_rhs) { + return ((p_lhs.x == p_rhs.x) || (Math::is_nan(p_lhs.x) && Math::is_nan(p_rhs.x))) && ((p_lhs.y == p_rhs.y) || (Math::is_nan(p_lhs.y) && Math::is_nan(p_rhs.y))) && ((p_lhs.z == p_rhs.z) || (Math::is_nan(p_lhs.z) && Math::is_nan(p_rhs.z))) && ((p_lhs.w == p_rhs.w) || (Math::is_nan(p_lhs.w) && Math::is_nan(p_rhs.w))); + } +}; + +template <> +struct HashMapComparatorDefault { + static bool compare(const Rect2 &p_lhs, const Rect2 &p_rhs) { + return HashMapComparatorDefault().compare(p_lhs.position, p_rhs.position) && HashMapComparatorDefault().compare(p_lhs.size, p_rhs.size); + } +}; + +template <> +struct HashMapComparatorDefault { + static bool compare(const AABB &p_lhs, const AABB &p_rhs) { + return HashMapComparatorDefault().compare(p_lhs.position, p_rhs.position) && HashMapComparatorDefault().compare(p_lhs.size, p_rhs.size); + } +}; + +template <> +struct HashMapComparatorDefault { + static bool compare(const Plane &p_lhs, const Plane &p_rhs) { + return HashMapComparatorDefault().compare(p_lhs.normal, p_rhs.normal) && ((p_lhs.d == p_rhs.d) || (Math::is_nan(p_lhs.d) && Math::is_nan(p_rhs.d))); + } +}; + +template <> +struct HashMapComparatorDefault { + static bool compare(const Transform2D &p_lhs, const Transform2D &p_rhs) { + for (int i = 0; i < 3; ++i) { + if (!HashMapComparatorDefault().compare(p_lhs.columns[i], p_rhs.columns[i])) { + return false; + } + } + + return true; + } +}; + +template <> +struct HashMapComparatorDefault { + static bool compare(const Basis &p_lhs, const Basis &p_rhs) { + for (int i = 0; i < 3; ++i) { + if (!HashMapComparatorDefault().compare(p_lhs.rows[i], p_rhs.rows[i])) { + return false; + } + } + + return true; + } +}; + +template <> +struct HashMapComparatorDefault { + static bool compare(const Transform3D &p_lhs, const Transform3D &p_rhs) { + return HashMapComparatorDefault().compare(p_lhs.basis, p_rhs.basis) && HashMapComparatorDefault().compare(p_lhs.origin, p_rhs.origin); + } +}; + +template <> +struct HashMapComparatorDefault { + static bool compare(const Projection &p_lhs, const Projection &p_rhs) { + for (int i = 0; i < 4; ++i) { + if (!HashMapComparatorDefault().compare(p_lhs.columns[i], p_rhs.columns[i])) { + return false; + } + } + + return true; + } +}; + +template <> +struct HashMapComparatorDefault { + static bool compare(const Quaternion &p_lhs, const Quaternion &p_rhs) { + return ((p_lhs.x == p_rhs.x) || (Math::is_nan(p_lhs.x) && Math::is_nan(p_rhs.x))) && ((p_lhs.y == p_rhs.y) || (Math::is_nan(p_lhs.y) && Math::is_nan(p_rhs.y))) && ((p_lhs.z == p_rhs.z) || (Math::is_nan(p_lhs.z) && Math::is_nan(p_rhs.z))) && ((p_lhs.w == p_rhs.w) || (Math::is_nan(p_lhs.w) && Math::is_nan(p_rhs.w))); + } +}; + constexpr uint32_t HASH_TABLE_SIZE_MAX = 29; -const uint32_t hash_table_size_primes[HASH_TABLE_SIZE_MAX] = { +inline constexpr uint32_t hash_table_size_primes[HASH_TABLE_SIZE_MAX] = { 5, 13, 23, @@ -459,7 +572,7 @@ const uint32_t hash_table_size_primes[HASH_TABLE_SIZE_MAX] = { }; // Computed with elem_i = UINT64_C (0 x FFFFFFFF FFFFFFFF ) / d_i + 1, where d_i is the i-th element of the above array. -const uint64_t hash_table_size_primes_inv[HASH_TABLE_SIZE_MAX] = { +inline constexpr uint64_t hash_table_size_primes_inv[HASH_TABLE_SIZE_MAX] = { 3689348814741910324, 1418980313362273202, 802032351030850071, diff --git a/include/godot_cpp/templates/list.hpp b/include/godot_cpp/templates/list.hpp index bbc818c7d..9291f5e40 100644 --- a/include/godot_cpp/templates/list.hpp +++ b/include/godot_cpp/templates/list.hpp @@ -34,6 +34,8 @@ #include #include +#include + /** * Generic Templatized Linked List Implementation. * The implementation differs from the STL one because @@ -133,6 +135,8 @@ class List { data->erase(this); } + void transfer_to_back(List *p_dst_list); + _FORCE_INLINE_ Element() {} }; @@ -223,7 +227,7 @@ class List { Element *last = nullptr; int size_cache = 0; - bool erase(const Element *p_I) { + bool erase(Element *p_I) { ERR_FAIL_NULL_V(p_I, false); ERR_FAIL_COND_V(p_I->data != this, false); @@ -243,7 +247,7 @@ class List { p_I->next_ptr->prev_ptr = p_I->prev_ptr; } - memdelete_allocator(const_cast(p_I)); + memdelete_allocator(p_I); size_cache--; return true; @@ -429,7 +433,7 @@ class List { /** * erase an element in the list, by iterator pointing to it. Return true if it was found/erased. */ - bool erase(const Element *p_I) { + bool erase(Element *p_I) { if (_data && p_I) { bool ret = _data->erase(p_I); @@ -521,10 +525,14 @@ class List { it = it->next(); } } + void operator=(List &&p_list) { + if (unlikely(this == &p_list)) { + return; + } - // Index operator, kept for compatibility. - _FORCE_INLINE_ T &operator[](int p_index) { - return get(p_index); + clear(); + _data = p_list._data; + p_list._data = nullptr; } // Random access to elements, use with care, @@ -542,11 +550,6 @@ class List { return I->get(); } - // Index operator, kept for compatibility. - _FORCE_INLINE_ const T &operator[](int p_index) const { - return get(p_index); - } - // Random access to elements, use with care, // do not use for iteration. const T &get(int p_index) const { @@ -720,8 +723,8 @@ class List { template void sort_custom() { - // this version uses auxiliary memory for speed. - // if you don't want to use auxiliary memory, use the in_place version + //this version uses auxiliary memory for speed. + //if you don't want to use auxiliary memory, use the in_place version int s = size(); if (s < 2) { @@ -769,9 +772,19 @@ class List { it = it->next(); } } + List(List &&p_list) { + _data = p_list._data; + p_list._data = nullptr; + } List() {} + List(std::initializer_list p_init) { + for (const T &E : p_init) { + push_back(E); + } + } + ~List() { clear(); if (_data) { @@ -781,4 +794,41 @@ class List { } }; +template +void List::Element::transfer_to_back(List *p_dst_list) { + // Detach from current. + + if (data->first == this) { + data->first = data->first->next_ptr; + } + if (data->last == this) { + data->last = data->last->prev_ptr; + } + if (prev_ptr) { + prev_ptr->next_ptr = next_ptr; + } + if (next_ptr) { + next_ptr->prev_ptr = prev_ptr; + } + data->size_cache--; + + // Attach to the back of the new one. + + if (!p_dst_list->_data) { + p_dst_list->_data = memnew_allocator(_Data, A); + p_dst_list->_data->first = this; + p_dst_list->_data->last = nullptr; + p_dst_list->_data->size_cache = 0; + prev_ptr = nullptr; + } else { + p_dst_list->_data->last->next_ptr = this; + prev_ptr = p_dst_list->_data->last; + } + p_dst_list->_data->last = this; + next_ptr = nullptr; + + data = p_dst_list->_data; + p_dst_list->_data->size_cache++; +} + } // namespace godot diff --git a/include/godot_cpp/templates/local_vector.hpp b/include/godot_cpp/templates/local_vector.hpp index 7b684874a..0ef322fba 100644 --- a/include/godot_cpp/templates/local_vector.hpp +++ b/include/godot_cpp/templates/local_vector.hpp @@ -58,21 +58,18 @@ class LocalVector { return data; } + // Must take a copy instead of a reference (see GH-31736). _FORCE_INLINE_ void push_back(T p_elem) { if (unlikely(count == capacity)) { - if (capacity == 0) { - capacity = 1; - } else { - capacity <<= 1; - } + capacity = tight ? (capacity + 1) : MAX((U)1, capacity << 1); data = (T *)memrealloc(data, capacity * sizeof(T)); CRASH_COND_MSG(!data, "Out of memory"); } - if constexpr (!std::is_trivially_constructible::value && !force_trivial) { + if constexpr (!std::is_trivially_constructible_v && !force_trivial) { memnew_placement(&data[count++], T(p_elem)); } else { - data[count++] = p_elem; + data[count++] = std::move(p_elem); } } @@ -80,31 +77,49 @@ class LocalVector { ERR_FAIL_UNSIGNED_INDEX(p_index, count); count--; for (U i = p_index; i < count; i++) { - data[i] = data[i + 1]; + data[i] = std::move(data[i + 1]); } - if constexpr (!std::is_trivially_destructible::value && !force_trivial) { + if constexpr (!std::is_trivially_destructible_v && !force_trivial) { data[count].~T(); } } /// Removes the item copying the last value into the position of the one to - /// remove. It's generally faster than `remove`. + /// remove. It's generally faster than `remove_at`. void remove_at_unordered(U p_index) { ERR_FAIL_INDEX(p_index, count); count--; if (count > p_index) { - data[p_index] = data[count]; + data[p_index] = std::move(data[count]); } - if constexpr (!std::is_trivially_destructible::value && !force_trivial) { + if constexpr (!std::is_trivially_destructible_v && !force_trivial) { data[count].~T(); } } - void erase(const T &p_val) { + _FORCE_INLINE_ bool erase(const T &p_val) { int64_t idx = find(p_val); if (idx >= 0) { remove_at(idx); + return true; } + return false; + } + + U erase_multiple_unordered(const T &p_val) { + U from = 0; + U occurrences = 0; + while (true) { + int64_t idx = find(p_val, from); + + if (idx == -1) { + break; + } + remove_at_unordered(idx); + from = idx; + occurrences++; + } + return occurrences; } void invert() { @@ -136,7 +151,7 @@ class LocalVector { _FORCE_INLINE_ U size() const { return count; } void resize(U p_size) { if (p_size < count) { - if constexpr (!std::is_trivially_destructible::value && !force_trivial) { + if constexpr (!std::is_trivially_destructible_v && !force_trivial) { for (U i = p_size; i < count; i++) { data[i].~T(); } @@ -144,16 +159,11 @@ class LocalVector { count = p_size; } else if (p_size > count) { if (unlikely(p_size > capacity)) { - if (capacity == 0) { - capacity = 1; - } - while (capacity < p_size) { - capacity <<= 1; - } + capacity = tight ? p_size : nearest_power_of_2_templated(p_size); data = (T *)memrealloc(data, capacity * sizeof(T)); CRASH_COND_MSG(!data, "Out of memory"); } - if constexpr (!std::is_trivially_constructible::value && !force_trivial) { + if constexpr (!std::is_trivially_constructible_v && !force_trivial) { for (U i = count; i < p_size; i++) { memnew_placement(&data[i], T); } @@ -237,13 +247,13 @@ class LocalVector { void insert(U p_pos, T p_val) { ERR_FAIL_UNSIGNED_INDEX(p_pos, count + 1); if (p_pos == count) { - push_back(p_val); + push_back(std::move(p_val)); } else { resize(count + 1); for (U i = count - 1; i > p_pos; i--) { - data[i] = data[i - 1]; + data[i] = std::move(data[i - 1]); } - data[p_pos] = p_val; + data[p_pos] = std::move(p_val); } } @@ -287,9 +297,17 @@ class LocalVector { operator Vector() const { Vector ret; - ret.resize(size()); + ret.resize(count); T *w = ret.ptrw(); - memcpy(w, data, sizeof(T) * count); + if (w) { + if constexpr (std::is_trivially_copyable_v) { + memcpy(w, data, sizeof(T) * count); + } else { + for (U i = 0; i < count; i++) { + w[i] = data[i]; + } + } + } return ret; } @@ -297,7 +315,9 @@ class LocalVector { Vector ret; ret.resize(count * sizeof(T)); uint8_t *w = ret.ptrw(); - memcpy(w, data, sizeof(T) * count); + if (w) { + memcpy(w, data, sizeof(T) * count); + } return ret; } @@ -314,6 +334,16 @@ class LocalVector { data[i] = p_from.data[i]; } } + _FORCE_INLINE_ LocalVector(LocalVector &&p_from) { + data = p_from.data; + count = p_from.count; + capacity = p_from.capacity; + + p_from.data = nullptr; + p_from.count = 0; + p_from.capacity = 0; + } + inline void operator=(const LocalVector &p_from) { resize(p_from.size()); for (U i = 0; i < p_from.count; i++) { @@ -326,6 +356,26 @@ class LocalVector { data[i] = p_from[i]; } } + inline void operator=(LocalVector &&p_from) { + if (unlikely(this == &p_from)) { + return; + } + reset(); + + data = p_from.data; + count = p_from.count; + capacity = p_from.capacity; + + p_from.data = nullptr; + p_from.count = 0; + p_from.capacity = 0; + } + inline void operator=(Vector &&p_from) { + resize(p_from.size()); + for (U i = 0; i < count; i++) { + data[i] = std::move(p_from[i]); + } + } _FORCE_INLINE_ ~LocalVector() { if (data) { diff --git a/include/godot_cpp/templates/pair.hpp b/include/godot_cpp/templates/pair.hpp index 5c064c1cf..423a7099e 100644 --- a/include/godot_cpp/templates/pair.hpp +++ b/include/godot_cpp/templates/pair.hpp @@ -68,6 +68,15 @@ struct PairSort { } }; +template +struct PairHash { + static uint32_t hash(const Pair &P) { + uint64_t h1 = HashMapHasherDefault::hash(P.first); + uint64_t h2 = HashMapHasherDefault::hash(P.second); + return hash_one_uint64((h1 << 32) | h2); + } +}; + template struct KeyValue { const K key; diff --git a/include/godot_cpp/templates/rb_map.hpp b/include/godot_cpp/templates/rb_map.hpp index 0ddb19839..c0dc4bf33 100644 --- a/include/godot_cpp/templates/rb_map.hpp +++ b/include/godot_cpp/templates/rb_map.hpp @@ -34,6 +34,8 @@ #include #include +#include + namespace godot { // based on the very nice implementation of rb-trees by: @@ -97,6 +99,8 @@ class RBMap { typedef KeyValue ValueType; struct Iterator { + friend class RBMap; + _FORCE_INLINE_ KeyValue &operator*() const { return E->key_value(); } @@ -110,11 +114,16 @@ class RBMap { return *this; } - _FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; } - _FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; } + _FORCE_INLINE_ bool operator==(const Iterator &p_it) const { return E == p_it.E; } + _FORCE_INLINE_ bool operator!=(const Iterator &p_it) const { return E != p_it.E; } explicit operator bool() const { return E != nullptr; } + + Iterator &operator=(const Iterator &p_it) { + E = p_it.E; + return *this; + } Iterator(Element *p_E) { E = p_E; } Iterator() {} Iterator(const Iterator &p_it) { E = p_it.E; } @@ -137,11 +146,16 @@ class RBMap { return *this; } - _FORCE_INLINE_ bool operator==(const ConstIterator &b) const { return E == b.E; } - _FORCE_INLINE_ bool operator!=(const ConstIterator &b) const { return E != b.E; } + _FORCE_INLINE_ bool operator==(const ConstIterator &p_it) const { return E == p_it.E; } + _FORCE_INLINE_ bool operator!=(const ConstIterator &p_it) const { return E != p_it.E; } explicit operator bool() const { return E != nullptr; } + + ConstIterator &operator=(const ConstIterator &p_it) { + E = p_it.E; + return *this; + } ConstIterator(const Element *p_E) { E = p_E; } ConstIterator() {} ConstIterator(const ConstIterator &p_it) { E = p_it.E; } @@ -418,7 +432,7 @@ class RBMap { new_node->right = _data._nil; new_node->left = _data._nil; - // new_node->data=_data; + //new_node->data=_data; if (new_parent == _data._root || less(p_key, new_parent->_data.key)) { new_parent->left = new_node; @@ -752,6 +766,12 @@ class RBMap { _copy_from(p_map); } + RBMap(std::initializer_list> p_init) { + for (const KeyValue &E : p_init) { + insert(E.key, E.value); + } + } + _FORCE_INLINE_ RBMap() {} ~RBMap() { diff --git a/include/godot_cpp/templates/rb_set.hpp b/include/godot_cpp/templates/rb_set.hpp index f826896f7..612be9115 100644 --- a/include/godot_cpp/templates/rb_set.hpp +++ b/include/godot_cpp/templates/rb_set.hpp @@ -32,6 +32,8 @@ #include +#include + // based on the very nice implementation of rb-trees by: // https://web.archive.org/web/20120507164830/https://web.mit.edu/~emin/www/source_code/red_black_tree/index.html @@ -398,7 +400,7 @@ class RBSet { new_node->right = _data._nil; new_node->left = _data._nil; new_node->value = p_value; - // new_node->data=_data; + //new_node->data=_data; if (new_parent == _data._root || less(p_value, new_parent->value)) { new_parent->left = new_node; @@ -701,6 +703,12 @@ class RBSet { _copy_from(p_set); } + RBSet(std::initializer_list p_init) { + for (const T &E : p_init) { + insert(E); + } + } + _FORCE_INLINE_ RBSet() {} ~RBSet() { diff --git a/include/godot_cpp/templates/safe_refcount.hpp b/include/godot_cpp/templates/safe_refcount.hpp index e6c29689c..42cdb2444 100644 --- a/include/godot_cpp/templates/safe_refcount.hpp +++ b/include/godot_cpp/templates/safe_refcount.hpp @@ -51,7 +51,7 @@ namespace godot { #define SAFE_NUMERIC_TYPE_PUN_GUARANTEES(m_type) \ static_assert(sizeof(SafeNumeric) == sizeof(m_type)); \ static_assert(alignof(SafeNumeric) == alignof(m_type)); \ - static_assert(std::is_trivially_destructible>::value); + static_assert(std::is_trivially_destructible_v>); #define SAFE_FLAG_TYPE_PUN_GUARANTEES \ static_assert(sizeof(SafeFlag) == sizeof(bool)); \ static_assert(alignof(SafeFlag) == alignof(bool)); @@ -102,6 +102,17 @@ class SafeNumeric { return value.fetch_sub(p_value, std::memory_order_acq_rel) - p_value; } + _ALWAYS_INLINE_ T bit_or(T p_value) { + return value.fetch_or(p_value, std::memory_order_acq_rel); + } + _ALWAYS_INLINE_ T bit_and(T p_value) { + return value.fetch_and(p_value, std::memory_order_acq_rel); + } + + _ALWAYS_INLINE_ T bit_xor(T p_value) { + return value.fetch_xor(p_value, std::memory_order_acq_rel); + } + // Returns the original value instead of the new one _ALWAYS_INLINE_ T postsub(T p_value) { return value.fetch_sub(p_value, std::memory_order_acq_rel); @@ -113,7 +124,8 @@ class SafeNumeric { if (tmp >= p_value) { return tmp; // already greater, or equal } - if (value.compare_exchange_weak(tmp, p_value, std::memory_order_release)) { + + if (value.compare_exchange_weak(tmp, p_value, std::memory_order_acq_rel)) { return p_value; } } @@ -125,7 +137,7 @@ class SafeNumeric { if (c == 0) { return 0; } - if (value.compare_exchange_weak(c, c + 1, std::memory_order_release)) { + if (value.compare_exchange_weak(c, c + 1, std::memory_order_acq_rel)) { return c + 1; } } @@ -166,6 +178,16 @@ class SafeFlag { class SafeRefCount { SafeNumeric count; +#ifdef DEV_ENABLED + _ALWAYS_INLINE_ void _check_unref_safety() { + // This won't catch every misuse, but it's better than nothing. + CRASH_COND_MSG(count.get() == 0, + "Trying to unreference a SafeRefCount which is already zero is wrong and a symptom of it being misused.\n" + "Upon a SafeRefCount reaching zero any object whose lifetime is tied to it, as well as the ref count itself, must be destroyed.\n" + "Moreover, to guarantee that, no multiple threads should be racing to do the final unreferencing to zero."); + } +#endif + public: _ALWAYS_INLINE_ bool ref() { // true on success return count.conditional_increment() != 0; @@ -176,10 +198,16 @@ class SafeRefCount { } _ALWAYS_INLINE_ bool unref() { // true if must be disposed of +#ifdef DEV_ENABLED + _check_unref_safety(); +#endif return count.decrement() == 0; } _ALWAYS_INLINE_ uint32_t unrefval() { // 0 if must be disposed of +#ifdef DEV_ENABLED + _check_unref_safety(); +#endif return count.decrement(); } @@ -192,141 +220,6 @@ class SafeRefCount { } }; -#else - -template -class SafeNumeric { -protected: - T value; - -public: - _ALWAYS_INLINE_ void set(T p_value) { - value = p_value; - } - - _ALWAYS_INLINE_ T get() const { - return value; - } - - _ALWAYS_INLINE_ T increment() { - return ++value; - } - - _ALWAYS_INLINE_ T postincrement() { - return value++; - } - - _ALWAYS_INLINE_ T decrement() { - return --value; - } - - _ALWAYS_INLINE_ T postdecrement() { - return value--; - } - - _ALWAYS_INLINE_ T add(T p_value) { - return value += p_value; - } - - _ALWAYS_INLINE_ T postadd(T p_value) { - T old = value; - value += p_value; - return old; - } - - _ALWAYS_INLINE_ T sub(T p_value) { - return value -= p_value; - } - - _ALWAYS_INLINE_ T postsub(T p_value) { - T old = value; - value -= p_value; - return old; - } - - _ALWAYS_INLINE_ T exchange_if_greater(T p_value) { - if (value < p_value) { - value = p_value; - } - return value; - } - - _ALWAYS_INLINE_ T conditional_increment() { - if (value == 0) { - return 0; - } else { - return ++value; - } - } - - _ALWAYS_INLINE_ explicit SafeNumeric(T p_value = static_cast(0)) : - value(p_value) { - } -}; - -class SafeFlag { -protected: - bool flag; - -public: - _ALWAYS_INLINE_ bool is_set() const { - return flag; - } - - _ALWAYS_INLINE_ void set() { - flag = true; - } - - _ALWAYS_INLINE_ void clear() { - flag = false; - } - - _ALWAYS_INLINE_ void set_to(bool p_value) { - flag = p_value; - } - - _ALWAYS_INLINE_ explicit SafeFlag(bool p_value = false) : - flag(p_value) {} -}; - -class SafeRefCount { - uint32_t count = 0; - -public: - _ALWAYS_INLINE_ bool ref() { // true on success - if (count != 0) { - ++count; - return true; - } else { - return false; - } - } - - _ALWAYS_INLINE_ uint32_t refval() { // none-zero on success - if (count != 0) { - return ++count; - } else { - return 0; - } - } - - _ALWAYS_INLINE_ bool unref() { // true if must be disposed of - return --count == 0; - } - - _ALWAYS_INLINE_ uint32_t unrefval() { // 0 if must be disposed of - return --count; - } - - _ALWAYS_INLINE_ uint32_t get() const { - return count; - } - - _ALWAYS_INLINE_ void init(uint32_t p_value = 1) { - count = p_value; - } -}; - -#endif - } // namespace godot + +#endif // !defined(NO_THREADS) diff --git a/include/godot_cpp/templates/search_array.hpp b/include/godot_cpp/templates/search_array.hpp index aa3374e8f..27a5c9d07 100644 --- a/include/godot_cpp/templates/search_array.hpp +++ b/include/godot_cpp/templates/search_array.hpp @@ -39,12 +39,12 @@ class SearchArray { public: Comparator compare; - inline int bisect(const T *p_array, int p_len, const T &p_value, bool p_before) const { - int lo = 0; - int hi = p_len; + inline int64_t bisect(const T *p_array, int64_t p_len, const T &p_value, bool p_before) const { + int64_t lo = 0; + int64_t hi = p_len; if (p_before) { while (lo < hi) { - const int mid = (lo + hi) / 2; + const int64_t mid = (lo + hi) / 2; if (compare(p_array[mid], p_value)) { lo = mid + 1; } else { @@ -53,7 +53,7 @@ class SearchArray { } } else { while (lo < hi) { - const int mid = (lo + hi) / 2; + const int64_t mid = (lo + hi) / 2; if (compare(p_value, p_array[mid])) { hi = mid; } else { diff --git a/include/godot_cpp/templates/self_list.hpp b/include/godot_cpp/templates/self_list.hpp index cdd1f2586..4b4e3942d 100644 --- a/include/godot_cpp/templates/self_list.hpp +++ b/include/godot_cpp/templates/self_list.hpp @@ -100,11 +100,74 @@ class SelfList { p_elem->_root = nullptr; } + void clear() { + while (_first) { + remove(_first); + } + } + + void sort() { + sort_custom>(); + } + + template + void sort_custom() { + if (_first == _last) { + return; + } + + SelfList *from = _first; + SelfList *current = from; + SelfList *to = from; + + while (current) { + SelfList *next = current->_next; + + if (from != current) { + current->_prev = nullptr; + current->_next = from; + + SelfList *find = from; + C less; + while (find && less(*find->_self, *current->_self)) { + current->_prev = find; + current->_next = find->_next; + find = find->_next; + } + + if (current->_prev) { + current->_prev->_next = current; + } else { + from = current; + } + + if (current->_next) { + current->_next->_prev = current; + } else { + to = current; + } + } else { + current->_prev = nullptr; + current->_next = nullptr; + } + + current = next; + } + _first = from; + _last = to; + } + _FORCE_INLINE_ SelfList *first() { return _first; } _FORCE_INLINE_ const SelfList *first() const { return _first; } + // Forbid copying, which has broken behavior. + void operator=(const List &) = delete; + _FORCE_INLINE_ List() {} - _FORCE_INLINE_ ~List() { ERR_FAIL_COND(_first != nullptr); } + _FORCE_INLINE_ ~List() { + // A self list must be empty on destruction. + DEV_ASSERT(_first == nullptr); + } }; private: @@ -126,6 +189,9 @@ class SelfList { _FORCE_INLINE_ const SelfList *prev() const { return _prev; } _FORCE_INLINE_ T *self() const { return _self; } + // Forbid copying, which has broken behavior. + void operator=(const SelfList &) = delete; + _FORCE_INLINE_ SelfList(T *p_self) { _self = p_self; } diff --git a/include/godot_cpp/templates/sort_array.hpp b/include/godot_cpp/templates/sort_array.hpp index c2727dd94..fe1365858 100644 --- a/include/godot_cpp/templates/sort_array.hpp +++ b/include/godot_cpp/templates/sort_array.hpp @@ -78,8 +78,8 @@ class SortArray { } } - inline int bitlog(int n) const { - int k; + inline int64_t bitlog(int64_t n) const { + int64_t k; for (k = 0; n != 1; n >>= 1) { ++k; } @@ -88,8 +88,8 @@ class SortArray { /* Heap / Heapsort functions */ - inline void push_heap(int p_first, int p_hole_idx, int p_top_index, T p_value, T *p_array) const { - int parent = (p_hole_idx - 1) / 2; + inline void push_heap(int64_t p_first, int64_t p_hole_idx, int64_t p_top_index, T p_value, T *p_array) const { + int64_t parent = (p_hole_idx - 1) / 2; while (p_hole_idx > p_top_index && compare(p_array[p_first + parent], p_value)) { p_array[p_first + p_hole_idx] = p_array[p_first + parent]; p_hole_idx = parent; @@ -98,17 +98,17 @@ class SortArray { p_array[p_first + p_hole_idx] = p_value; } - inline void pop_heap(int p_first, int p_last, int p_result, T p_value, T *p_array) const { + inline void pop_heap(int64_t p_first, int64_t p_last, int64_t p_result, T p_value, T *p_array) const { p_array[p_result] = p_array[p_first]; adjust_heap(p_first, 0, p_last - p_first, p_value, p_array); } - inline void pop_heap(int p_first, int p_last, T *p_array) const { + inline void pop_heap(int64_t p_first, int64_t p_last, T *p_array) const { pop_heap(p_first, p_last - 1, p_last - 1, p_array[p_last - 1], p_array); } - inline void adjust_heap(int p_first, int p_hole_idx, int p_len, T p_value, T *p_array) const { - int top_index = p_hole_idx; - int second_child = 2 * p_hole_idx + 2; + inline void adjust_heap(int64_t p_first, int64_t p_hole_idx, int64_t p_len, T p_value, T *p_array) const { + int64_t top_index = p_hole_idx; + int64_t second_child = 2 * p_hole_idx + 2; while (second_child < p_len) { if (compare(p_array[p_first + second_child], p_array[p_first + (second_child - 1)])) { @@ -127,18 +127,18 @@ class SortArray { push_heap(p_first, p_hole_idx, top_index, p_value, p_array); } - inline void sort_heap(int p_first, int p_last, T *p_array) const { + inline void sort_heap(int64_t p_first, int64_t p_last, T *p_array) const { while (p_last - p_first > 1) { pop_heap(p_first, p_last--, p_array); } } - inline void make_heap(int p_first, int p_last, T *p_array) const { + inline void make_heap(int64_t p_first, int64_t p_last, T *p_array) const { if (p_last - p_first < 2) { return; } - int len = p_last - p_first; - int parent = (len - 2) / 2; + int64_t len = p_last - p_first; + int64_t parent = (len - 2) / 2; while (true) { adjust_heap(p_first, parent, len, p_array[p_first + parent], p_array); @@ -149,9 +149,9 @@ class SortArray { } } - inline void partial_sort(int p_first, int p_last, int p_middle, T *p_array) const { + inline void partial_sort(int64_t p_first, int64_t p_last, int64_t p_middle, T *p_array) const { make_heap(p_first, p_middle, p_array); - for (int i = p_middle; i < p_last; i++) { + for (int64_t i = p_middle; i < p_last; i++) { if (compare(p_array[i], p_array[p_first])) { pop_heap(p_first, p_middle, i, p_array[i], p_array); } @@ -159,29 +159,29 @@ class SortArray { sort_heap(p_first, p_middle, p_array); } - inline void partial_select(int p_first, int p_last, int p_middle, T *p_array) const { + inline void partial_select(int64_t p_first, int64_t p_last, int64_t p_middle, T *p_array) const { make_heap(p_first, p_middle, p_array); - for (int i = p_middle; i < p_last; i++) { + for (int64_t i = p_middle; i < p_last; i++) { if (compare(p_array[i], p_array[p_first])) { pop_heap(p_first, p_middle, i, p_array[i], p_array); } } } - inline int partitioner(int p_first, int p_last, T p_pivot, T *p_array) const { - const int unmodified_first = p_first; - const int unmodified_last = p_last; + inline int64_t partitioner(int64_t p_first, int64_t p_last, T p_pivot, T *p_array) const { + const int64_t unmodified_first = p_first; + const int64_t unmodified_last = p_last; while (true) { while (compare(p_array[p_first], p_pivot)) { - if (Validate) { + if constexpr (Validate) { ERR_BAD_COMPARE(p_first == unmodified_last - 1); } p_first++; } p_last--; while (compare(p_pivot, p_array[p_last])) { - if (Validate) { + if constexpr (Validate) { ERR_BAD_COMPARE(p_last == unmodified_first); } p_last--; @@ -196,7 +196,7 @@ class SortArray { } } - inline void introsort(int p_first, int p_last, T *p_array, int p_max_depth) const { + inline void introsort(int64_t p_first, int64_t p_last, T *p_array, int64_t p_max_depth) const { while (p_last - p_first > INTROSORT_THRESHOLD) { if (p_max_depth == 0) { partial_sort(p_first, p_last, p_last, p_array); @@ -205,7 +205,7 @@ class SortArray { p_max_depth--; - int cut = partitioner( + int64_t cut = partitioner( p_first, p_last, median_of_3( @@ -219,7 +219,7 @@ class SortArray { } } - inline void introselect(int p_first, int p_nth, int p_last, T *p_array, int p_max_depth) const { + inline void introselect(int64_t p_first, int64_t p_nth, int64_t p_last, T *p_array, int64_t p_max_depth) const { while (p_last - p_first > 3) { if (p_max_depth == 0) { partial_select(p_first, p_nth + 1, p_last, p_array); @@ -229,7 +229,7 @@ class SortArray { p_max_depth--; - int cut = partitioner( + int64_t cut = partitioner( p_first, p_last, median_of_3( @@ -248,10 +248,10 @@ class SortArray { insertion_sort(p_first, p_last, p_array); } - inline void unguarded_linear_insert(int p_last, T p_value, T *p_array) const { - int next = p_last - 1; + inline void unguarded_linear_insert(int64_t p_last, T p_value, T *p_array) const { + int64_t next = p_last - 1; while (compare(p_value, p_array[next])) { - if (Validate) { + if constexpr (Validate) { ERR_BAD_COMPARE(next == 0); } p_array[p_last] = p_array[next]; @@ -261,10 +261,10 @@ class SortArray { p_array[p_last] = p_value; } - inline void linear_insert(int p_first, int p_last, T *p_array) const { + inline void linear_insert(int64_t p_first, int64_t p_last, T *p_array) const { T val = p_array[p_last]; if (compare(val, p_array[p_first])) { - for (int i = p_last; i > p_first; i--) { + for (int64_t i = p_last; i > p_first; i--) { p_array[i] = p_array[i - 1]; } @@ -274,22 +274,22 @@ class SortArray { } } - inline void insertion_sort(int p_first, int p_last, T *p_array) const { + inline void insertion_sort(int64_t p_first, int64_t p_last, T *p_array) const { if (p_first == p_last) { return; } - for (int i = p_first + 1; i != p_last; i++) { + for (int64_t i = p_first + 1; i != p_last; i++) { linear_insert(p_first, i, p_array); } } - inline void unguarded_insertion_sort(int p_first, int p_last, T *p_array) const { - for (int i = p_first; i != p_last; i++) { + inline void unguarded_insertion_sort(int64_t p_first, int64_t p_last, T *p_array) const { + for (int64_t i = p_first; i != p_last; i++) { unguarded_linear_insert(i, p_array[i], p_array); } } - inline void final_insertion_sort(int p_first, int p_last, T *p_array) const { + inline void final_insertion_sort(int64_t p_first, int64_t p_last, T *p_array) const { if (p_last - p_first > INTROSORT_THRESHOLD) { insertion_sort(p_first, p_first + INTROSORT_THRESHOLD, p_array); unguarded_insertion_sort(p_first + INTROSORT_THRESHOLD, p_last, p_array); @@ -298,18 +298,18 @@ class SortArray { } } - inline void sort_range(int p_first, int p_last, T *p_array) const { + inline void sort_range(int64_t p_first, int64_t p_last, T *p_array) const { if (p_first != p_last) { introsort(p_first, p_last, p_array, bitlog(p_last - p_first) * 2); final_insertion_sort(p_first, p_last, p_array); } } - inline void sort(T *p_array, int p_len) const { + inline void sort(T *p_array, int64_t p_len) const { sort_range(0, p_len, p_array); } - inline void nth_element(int p_first, int p_last, int p_nth, T *p_array) const { + inline void nth_element(int64_t p_first, int64_t p_last, int64_t p_nth, T *p_array) const { if (p_first == p_last || p_nth == p_last) { return; } diff --git a/include/godot_cpp/templates/vector.hpp b/include/godot_cpp/templates/vector.hpp index 50593f30a..51eb825d3 100644 --- a/include/godot_cpp/templates/vector.hpp +++ b/include/godot_cpp/templates/vector.hpp @@ -68,6 +68,7 @@ class Vector { CowData _cowdata; public: + // Must take a copy instead of a reference (see GH-31736). bool push_back(T p_elem); _FORCE_INLINE_ bool append(const T &p_elem) { return push_back(p_elem); } //alias void fill(T p_elem); @@ -96,11 +97,13 @@ class Vector { Error resize(Size p_size) { return _cowdata.resize(p_size); } Error resize_zeroed(Size p_size) { return _cowdata.template resize(p_size); } _FORCE_INLINE_ const T &operator[](Size p_index) const { return _cowdata.get(p_index); } + // Must take a copy instead of a reference (see GH-31736). Error insert(Size p_pos, T p_val) { return _cowdata.insert(p_pos, p_val); } Size find(const T &p_val, Size p_from = 0) const { return _cowdata.find(p_val, p_from); } Size rfind(const T &p_val, Size p_from = -1) const { return _cowdata.rfind(p_val, p_from); } Size count(const T &p_val) const { return _cowdata.count(p_val); } + // Must take a copy instead of a reference (see GH-31736). void append_array(Vector p_other); _FORCE_INLINE_ bool has(const T &p_val) const { return find(p_val) != -1; } @@ -145,17 +148,19 @@ class Vector { insert(i, p_val); } - inline void operator=(const Vector &p_from) { - _cowdata._ref(p_from._cowdata); - } + void operator=(const Vector &p_from) { _cowdata._ref(p_from._cowdata); } + void operator=(Vector &&p_from) { _cowdata = std::move(p_from._cowdata); } Vector to_byte_array() const { Vector ret; if (is_empty()) { return ret; } - ret.resize(size() * sizeof(T)); - memcpy(ret.ptrw(), ptr(), sizeof(T) * size()); + size_t alloc_size = size() * sizeof(T); + ret.resize(alloc_size); + if (alloc_size) { + memcpy(ret.ptrw(), ptr(), alloc_size); + } return ret; } @@ -278,16 +283,11 @@ class Vector { } _FORCE_INLINE_ Vector() {} - _FORCE_INLINE_ Vector(std::initializer_list p_init) { - Error err = _cowdata.resize(p_init.size()); - ERR_FAIL_COND(err); - - Size i = 0; - for (const T &element : p_init) { - _cowdata.set(i++, element); - } - } + _FORCE_INLINE_ Vector(std::initializer_list p_init) : + _cowdata(p_init) {} _FORCE_INLINE_ Vector(const Vector &p_from) { _cowdata._ref(p_from._cowdata); } + _FORCE_INLINE_ Vector(Vector &&p_from) : + _cowdata(std::move(p_from._cowdata)) {} _FORCE_INLINE_ ~Vector() {} }; diff --git a/include/godot_cpp/templates/vmap.hpp b/include/godot_cpp/templates/vmap.hpp index b6fa3c039..ea043d9fc 100644 --- a/include/godot_cpp/templates/vmap.hpp +++ b/include/godot_cpp/templates/vmap.hpp @@ -72,16 +72,16 @@ class VMap { middle = (low + high) / 2; if (p_val < a[middle].key) { - high = middle - 1; // search low end of array + high = middle - 1; //search low end of array } else if (a[middle].key < p_val) { - low = middle + 1; // search high end of array + low = middle + 1; //search high end of array } else { r_exact = true; return middle; } } - // return the position where this would be inserted + //return the position where this would be inserted if (a[middle].key < p_val) { middle++; } @@ -102,9 +102,9 @@ class VMap { middle = (low + high) / 2; if (p_val < a[middle].key) { - high = middle - 1; // search low end of array + high = middle - 1; //search low end of array } else if (a[middle].key < p_val) { - low = middle + 1; // search high end of array + low = middle + 1; //search high end of array } else { return middle; } @@ -142,6 +142,9 @@ class VMap { } int find_nearest(const T &p_val) const { + if (_cowdata.is_empty()) { + return -1; + } bool exact; return _find(p_val, exact); } @@ -191,6 +194,8 @@ class VMap { } _FORCE_INLINE_ VMap() {} + _FORCE_INLINE_ VMap(std::initializer_list p_init) : + _cowdata(p_init) {} _FORCE_INLINE_ VMap(const VMap &p_from) { _cowdata._ref(p_from._cowdata); } inline void operator=(const VMap &p_from) { diff --git a/include/godot_cpp/templates/vset.hpp b/include/godot_cpp/templates/vset.hpp index 42167403b..13d6e996b 100644 --- a/include/godot_cpp/templates/vset.hpp +++ b/include/godot_cpp/templates/vset.hpp @@ -59,16 +59,16 @@ class VSet { middle = (low + high) / 2; if (p_val < a[middle]) { - high = middle - 1; // search low end of array + high = middle - 1; //search low end of array } else if (a[middle] < p_val) { - low = middle + 1; // search high end of array + low = middle + 1; //search high end of array } else { r_exact = true; return middle; } } - // return the position where this would be inserted + //return the position where this would be inserted if (a[middle] < p_val) { middle++; } @@ -89,9 +89,9 @@ class VSet { middle = (low + high) / 2; if (p_val < a[middle]) { - high = middle - 1; // search low end of array + high = middle - 1; //search low end of array } else if (a[middle] < p_val) { - low = middle + 1; // search high end of array + low = middle + 1; //search high end of array } else { return middle; } @@ -137,6 +137,10 @@ class VSet { inline const T &operator[](int p_index) const { return _data[p_index]; } + + _FORCE_INLINE_ VSet() {} + _FORCE_INLINE_ VSet(std::initializer_list p_init) : + _data(p_init) {} }; } // namespace godot From 6917c1ea17e9e9179c46cd042b4c8ba80094e40f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pa=CC=84vels=20Nadtoc=CC=8Cajevs?= <7645683+bruvzg@users.noreply.github.com> Date: Fri, 28 Mar 2025 08:45:43 +0200 Subject: [PATCH 07/41] [macOS] Remove unnecessary Cocoa reference. (cherry picked from commit d239da32219dc2c9b9958cebef49256fa2ff4d20) --- cmake/macos.cmake | 12 ------------ tools/macos.py | 8 -------- 2 files changed, 20 deletions(-) diff --git a/cmake/macos.cmake b/cmake/macos.cmake index 7f8038210..33db862d7 100644 --- a/cmake/macos.cmake +++ b/cmake/macos.cmake @@ -17,14 +17,6 @@ https://cmake.org/cmake/help/latest/variable/CMAKE_OSX_ARCHITECTURES.html # Find Requirements if(APPLE) set(CMAKE_OSX_SYSROOT $ENV{SDKROOT}) - find_library( - COCOA_LIBRARY - REQUIRED - NAMES Cocoa - PATHS ${CMAKE_OSX_SYSROOT}/System/Library - PATH_SUFFIXES Frameworks - NO_DEFAULT_PATH - ) endif(APPLE) #[=============================[ MacOS Options ]=============================] @@ -45,9 +37,5 @@ endfunction() function(macos_generate) target_compile_definitions(godot-cpp PUBLIC MACOS_ENABLED UNIX_ENABLED) - target_link_options(godot-cpp PUBLIC -Wl,-undefined,dynamic_lookup) - - target_link_libraries(godot-cpp INTERFACE ${COCOA_LIBRARY}) - common_compiler_flags() endfunction() diff --git a/tools/macos.py b/tools/macos.py index f88e47ff1..541249cb4 100644 --- a/tools/macos.py +++ b/tools/macos.py @@ -63,14 +63,6 @@ def generate(env): env.Append(CCFLAGS=["-isysroot", env["macos_sdk_path"]]) env.Append(LINKFLAGS=["-isysroot", env["macos_sdk_path"]]) - env.Append( - LINKFLAGS=[ - "-framework", - "Cocoa", - "-Wl,-undefined,dynamic_lookup", - ] - ) - env.Append(CPPDEFINES=["MACOS_ENABLED", "UNIX_ENABLED"]) # Refer to https://github.com/godotengine/godot/blob/master/platform/macos/detect.py From 940fdea07f1777b0d4355bf2c311e00b2f968edc Mon Sep 17 00:00:00 2001 From: David Snopek Date: Fri, 28 Mar 2025 07:41:25 -0500 Subject: [PATCH 08/41] Fix stack smashing when Godot methods return `char32_t`, `char16_t` or `wchar_t` (cherry picked from commit 035add9d4f4289724a2b5049c5edc5383038d105) --- include/godot_cpp/core/engine_ptrcall.hpp | 8 ++++---- include/godot_cpp/core/method_ptrcall.hpp | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/include/godot_cpp/core/engine_ptrcall.hpp b/include/godot_cpp/core/engine_ptrcall.hpp index c8c80041a..3e4db0621 100644 --- a/include/godot_cpp/core/engine_ptrcall.hpp +++ b/include/godot_cpp/core/engine_ptrcall.hpp @@ -55,10 +55,10 @@ O *_call_native_mb_ret_obj(const GDExtensionMethodBindPtr mb, void *instance, co template R _call_native_mb_ret(const GDExtensionMethodBindPtr mb, void *instance, const Args &...args) { - R ret; + typename PtrToArg::EncodeT ret; std::array mb_args = { { (GDExtensionConstTypePtr)args... } }; internal::gdextension_interface_object_method_bind_ptrcall(mb, instance, mb_args.data(), &ret); - return ret; + return static_cast(ret); } template @@ -69,10 +69,10 @@ void _call_native_mb_no_ret(const GDExtensionMethodBindPtr mb, void *instance, c template R _call_utility_ret(GDExtensionPtrUtilityFunction func, const Args &...args) { - R ret; + typename PtrToArg::EncodeT ret; std::array mb_args = { { (GDExtensionConstTypePtr)args... } }; func(&ret, mb_args.data(), mb_args.size()); - return ret; + return static_cast(ret); } template diff --git a/include/godot_cpp/core/method_ptrcall.hpp b/include/godot_cpp/core/method_ptrcall.hpp index 8c84dbc75..820e59e9b 100644 --- a/include/godot_cpp/core/method_ptrcall.hpp +++ b/include/godot_cpp/core/method_ptrcall.hpp @@ -121,6 +121,9 @@ MAKE_PTRARGCONV(uint16_t, int64_t); MAKE_PTRARGCONV(int16_t, int64_t); MAKE_PTRARGCONV(uint32_t, int64_t); MAKE_PTRARGCONV(int32_t, int64_t); +MAKE_PTRARGCONV(char16_t, int64_t); +MAKE_PTRARGCONV(char32_t, int64_t); +MAKE_PTRARGCONV(wchar_t, int64_t); MAKE_PTRARG(int64_t); MAKE_PTRARG(uint64_t); // Float types From 37febead2b5aa3d749fcb526954dacd98dbf3417 Mon Sep 17 00:00:00 2001 From: Tom Date: Fri, 28 Mar 2025 20:04:15 +0000 Subject: [PATCH 09/41] Add method_ptrcall header include to type_info to fix compiler errors (cherry picked from commit 7ffaecce8c0a4da2fd69ae98b3d34af8c7e5624f) --- include/godot_cpp/core/type_info.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/godot_cpp/core/type_info.hpp b/include/godot_cpp/core/type_info.hpp index 59ad87e4b..e584aab31 100644 --- a/include/godot_cpp/core/type_info.hpp +++ b/include/godot_cpp/core/type_info.hpp @@ -30,6 +30,7 @@ #pragma once +#include #include #include #include From e299bc623dfb45f76b45c847b57db616f8c58b24 Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Fri, 14 Mar 2025 02:46:23 -0700 Subject: [PATCH 10/41] Add missing Projection constructor with 16 real_t values (cherry picked from commit aa03c32b3e84e8342a6aecd9abc12a30b9b47c50) --- include/godot_cpp/variant/projection.hpp | 1 + src/variant/projection.cpp | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/include/godot_cpp/variant/projection.hpp b/include/godot_cpp/variant/projection.hpp index e2283e6a6..42eb41662 100644 --- a/include/godot_cpp/variant/projection.hpp +++ b/include/godot_cpp/variant/projection.hpp @@ -153,6 +153,7 @@ struct [[nodiscard]] Projection { Projection(); Projection(const Vector4 &p_x, const Vector4 &p_y, const Vector4 &p_z, const Vector4 &p_w); + Projection(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_xw, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_yw, real_t p_zx, real_t p_zy, real_t p_zz, real_t p_zw, real_t p_wx, real_t p_wy, real_t p_wz, real_t p_ww); Projection(const Transform3D &p_transform); ~Projection(); }; diff --git a/src/variant/projection.cpp b/src/variant/projection.cpp index e983cd204..d8e35d441 100644 --- a/src/variant/projection.cpp +++ b/src/variant/projection.cpp @@ -1037,6 +1037,13 @@ Projection::Projection(const Vector4 &p_x, const Vector4 &p_y, const Vector4 &p_ columns[3] = p_w; } +Projection::Projection(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_xw, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_yw, real_t p_zx, real_t p_zy, real_t p_zz, real_t p_zw, real_t p_wx, real_t p_wy, real_t p_wz, real_t p_ww) { + columns[0] = Vector4(p_xx, p_xy, p_xz, p_xw); + columns[1] = Vector4(p_yx, p_yy, p_yz, p_yw); + columns[2] = Vector4(p_zx, p_zy, p_zz, p_zw); + columns[3] = Vector4(p_wx, p_wy, p_wz, p_ww); +} + Projection::Projection(const Transform3D &p_transform) { const Transform3D &tr = p_transform; real_t *m = &columns[0][0]; From 863f94de7732a945d6f4f45fa02e0f1b3a827761 Mon Sep 17 00:00:00 2001 From: unvermuthet <40361609+unvermuthet@users.noreply.github.com> Date: Tue, 18 Mar 2025 18:44:28 +0100 Subject: [PATCH 11/41] Implement `use_static_cpp` flag for Linux (cherry picked from commit b0f41909e0c9deddb7f0829fa3f3d1062b81ee94) --- cmake/linux.cmake | 14 ++++++++++++++ tools/linux.py | 5 +++++ 2 files changed, 19 insertions(+) diff --git a/cmake/linux.cmake b/cmake/linux.cmake index 89289d754..f01d75da9 100644 --- a/cmake/linux.cmake +++ b/cmake/linux.cmake @@ -14,11 +14,25 @@ function(linux_options) Not implemented as compiler selection is managed by CMake. Look to doc/cmake.rst for examples. ]] + option(GODOTCPP_USE_STATIC_CPP "Link libgcc and libstdc++ statically for better portability" ON) endfunction() #[===========================[ Target Generation ]===========================] function(linux_generate) + set(STATIC_CPP "$") + target_compile_definitions(godot-cpp PUBLIC LINUX_ENABLED UNIX_ENABLED) + # gersemi: off + target_link_options( + godot-cpp + PUBLIC + $<${STATIC_CPP}: + -static-libgcc + -static-libstdc++ + > + ) + # gersemi: on + common_compiler_flags() endfunction() diff --git a/tools/linux.py b/tools/linux.py index 9e85d8803..ae8019877 100644 --- a/tools/linux.py +++ b/tools/linux.py @@ -5,6 +5,7 @@ def options(opts): opts.Add(BoolVariable("use_llvm", "Use the LLVM compiler - only effective when targeting Linux", False)) + opts.Add(BoolVariable("use_static_cpp", "Link libgcc and libstdc++ statically for better portability", True)) def exists(env): @@ -37,6 +38,10 @@ def generate(env): env.Append(CCFLAGS=["-march=rv64gc"]) env.Append(LINKFLAGS=["-march=rv64gc"]) + # Link statically for portability + if env["use_static_cpp"]: + env.Append(LINKFLAGS=["-static-libgcc", "-static-libstdc++"]) + env.Append(CPPDEFINES=["LINUX_ENABLED", "UNIX_ENABLED"]) # Refer to https://github.com/godotengine/godot/blob/master/platform/linuxbsd/detect.py From c435258dde33c85d5d6d1404bab81c57e7105602 Mon Sep 17 00:00:00 2001 From: Tom Date: Sat, 22 Feb 2025 14:58:39 +0000 Subject: [PATCH 12/41] Made the Array's ptr and ptrw methods private (cherry picked from commit a2c37f8a160d04f1f5c6c11308fffce88f30ee3f) --- binding_generator.py | 46 ++++++++++++++++++++++++ include/godot_cpp/variant/variant.hpp | 51 +++++++++++++++++++++++++++ src/variant/packed_arrays.cpp | 8 +++++ 3 files changed, 105 insertions(+) diff --git a/binding_generator.py b/binding_generator.py index 9697687fb..b8256076f 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -642,6 +642,11 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl result.append("") result.append(f"\t{class_name}(const Variant *p_variant);") + if class_name == "Array": + result.append("") + result.append("\tconst Variant *ptr() const;") + result.append("\tVariant *ptrw();") + result.append("") result.append("public:") @@ -907,6 +912,47 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl result.append("\tVariant &operator[](int64_t p_index);") result.append("\tvoid set_typed(uint32_t p_type, const StringName &p_class_name, const Variant &p_script);") result.append("\tvoid _ref(const Array &p_from) const;") + result.append(""" + struct Iterator { + _FORCE_INLINE_ Variant &operator*() const; + _FORCE_INLINE_ Variant *operator->() const; + _FORCE_INLINE_ Iterator &operator++(); + _FORCE_INLINE_ Iterator &operator--(); + + _FORCE_INLINE_ bool operator==(const Iterator &b) const { return elem_ptr == b.elem_ptr; } + _FORCE_INLINE_ bool operator!=(const Iterator &b) const { return elem_ptr != b.elem_ptr; } + + Iterator(Variant *p_ptr) { elem_ptr = p_ptr; } + Iterator() {} + Iterator(const Iterator &p_it) { elem_ptr = p_it.elem_ptr; } + + private: + Variant *elem_ptr = nullptr; + }; + + struct ConstIterator { + _FORCE_INLINE_ const Variant &operator*() const; + _FORCE_INLINE_ const Variant *operator->() const; + _FORCE_INLINE_ ConstIterator &operator++(); + _FORCE_INLINE_ ConstIterator &operator--(); + + _FORCE_INLINE_ bool operator==(const ConstIterator &b) const { return elem_ptr == b.elem_ptr; } + _FORCE_INLINE_ bool operator!=(const ConstIterator &b) const { return elem_ptr != b.elem_ptr; } + + ConstIterator(const Variant *p_ptr) { elem_ptr = p_ptr; } + ConstIterator() {} + ConstIterator(const ConstIterator &p_it) { elem_ptr = p_it.elem_ptr; } + + private: + const Variant *elem_ptr = nullptr; + }; + + _FORCE_INLINE_ Iterator begin(); + _FORCE_INLINE_ Iterator end(); + + _FORCE_INLINE_ ConstIterator begin() const; + _FORCE_INLINE_ ConstIterator end() const; + """) if class_name == "Dictionary": result.append("\tconst Variant &operator[](const Variant &p_key) const;") diff --git a/include/godot_cpp/variant/variant.hpp b/include/godot_cpp/variant/variant.hpp index 0e4cda253..683f480ff 100644 --- a/include/godot_cpp/variant/variant.hpp +++ b/include/godot_cpp/variant/variant.hpp @@ -32,6 +32,7 @@ #include +#include #include #include @@ -357,6 +358,56 @@ String vformat(const String &p_text, const VarArgs... p_args) { return p_text % args_array; } +Variant &Array::Iterator::operator*() const { + return *elem_ptr; +} + +Variant *Array::Iterator::operator->() const { + return elem_ptr; +} + +Array::Iterator &Array::Iterator::operator++() { + elem_ptr++; + return *this; +} + +Array::Iterator &Array::Iterator::operator--() { + elem_ptr--; + return *this; +} + +const Variant &Array::ConstIterator::operator*() const { + return *elem_ptr; +} + +const Variant *Array::ConstIterator::operator->() const { + return elem_ptr; +} + +Array::ConstIterator &Array::ConstIterator::operator++() { + elem_ptr++; + return *this; +} + +Array::ConstIterator &Array::ConstIterator::operator--() { + elem_ptr--; + return *this; +} + +Array::Iterator Array::begin() { + return Array::Iterator(ptrw()); +} +Array::Iterator Array::end() { + return Array::Iterator(ptrw() + size()); +} + +Array::ConstIterator Array::begin() const { + return Array::ConstIterator(ptr()); +} +Array::ConstIterator Array::end() const { + return Array::ConstIterator(ptr() + size()); +} + #include #ifdef REAL_T_IS_DOUBLE diff --git a/src/variant/packed_arrays.cpp b/src/variant/packed_arrays.cpp index 8fe8a7338..4206b886d 100644 --- a/src/variant/packed_arrays.cpp +++ b/src/variant/packed_arrays.cpp @@ -236,6 +236,14 @@ void Array::_ref(const Array &p_from) const { internal::gdextension_interface_array_ref((GDExtensionTypePtr *)this, (GDExtensionConstTypePtr *)&p_from); } +const Variant *Array::ptr() const { + return (const Variant *)internal::gdextension_interface_array_operator_index_const((GDExtensionTypePtr *)this, 0); +} + +Variant *Array::ptrw() { + return (Variant *)internal::gdextension_interface_array_operator_index((GDExtensionTypePtr *)this, 0); +} + const Variant &Dictionary::operator[](const Variant &p_key) const { const Variant *var = (const Variant *)internal::gdextension_interface_dictionary_operator_index_const((GDExtensionTypePtr *)this, (GDExtensionVariantPtr)&p_key); return *var; From 6e6a1ea45134b7d1372f5c7bcd40ce4bb63475b0 Mon Sep 17 00:00:00 2001 From: Tom Date: Wed, 2 Apr 2025 19:58:05 +0100 Subject: [PATCH 13/41] . (cherry picked from commit 946a69385967986307871f88b304965839aae3a2) --- binding_generator.py | 3 ++- include/godot_cpp/variant/typed_array.hpp | 5 +++++ include/godot_cpp/variant/variant.hpp | 9 +++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/binding_generator.py b/binding_generator.py index b8256076f..c5b535c9a 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -541,7 +541,7 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl result.append("#include ") result.append("") - if is_packed_array(class_name): + if is_packed_array(class_name) or class_name == "Array": result.append("#include ") result.append("#include ") result.append("") @@ -953,6 +953,7 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl _FORCE_INLINE_ ConstIterator begin() const; _FORCE_INLINE_ ConstIterator end() const; """) + result.append("\t_FORCE_INLINE_ Array(std::initializer_list p_init);") if class_name == "Dictionary": result.append("\tconst Variant &operator[](const Variant &p_key) const;") diff --git a/include/godot_cpp/variant/typed_array.hpp b/include/godot_cpp/variant/typed_array.hpp index 9b735c599..69afdaaea 100644 --- a/include/godot_cpp/variant/typed_array.hpp +++ b/include/godot_cpp/variant/typed_array.hpp @@ -53,6 +53,8 @@ class TypedArray : public Array { assign(p_array); } } + _FORCE_INLINE_ TypedArray(std::initializer_list p_init) : + TypedArray(Array(p_init)) {} _FORCE_INLINE_ TypedArray() { set_typed(Variant::OBJECT, T::get_class_static(), Variant()); } @@ -68,6 +70,9 @@ class TypedArray : public Array { ERR_FAIL_COND_MSG(!is_same_typed(p_array), "Cannot assign an array with a different element type."); \ _ref(p_array); \ } \ + _FORCE_INLINE_ TypedArray(std::initializer_list p_init) : \ + Array(Array(p_init), m_variant_type, StringName(), Variant()) { \ + } \ _FORCE_INLINE_ TypedArray(const Variant &p_variant) : \ TypedArray(Array(p_variant)) { \ } \ diff --git a/include/godot_cpp/variant/variant.hpp b/include/godot_cpp/variant/variant.hpp index 683f480ff..6a0264a3a 100644 --- a/include/godot_cpp/variant/variant.hpp +++ b/include/godot_cpp/variant/variant.hpp @@ -408,6 +408,15 @@ Array::ConstIterator Array::end() const { return Array::ConstIterator(ptr() + size()); } +Array::Array(std::initializer_list p_init) { + ERR_FAIL_COND(resize(p_init.size()) != 0); + + size_t i = 0; + for (const Variant &element : p_init) { + set(i++, element); + } +} + #include #ifdef REAL_T_IS_DOUBLE From 3963054a14fb1c1baba59a3e60eedf3c13b3352f Mon Sep 17 00:00:00 2001 From: Samuel Nicholas Date: Tue, 11 Mar 2025 12:37:11 +1030 Subject: [PATCH 14/41] CMake: Update CI - Duplicated the ci.yml into ci-scons.yml and ci-cmake.yml - Replaced some manual shell commands to detect changes with tj-actions/changed-files@v45 - Conditionally run the CI depending on what files change. - Add ios toolchain from leetal/ios-cmake - Added a cmake-minimum of 3.10 to silence errors from ios toolchain (cherry picked from commit b6c0251296377fcb449752f64ec4e2eceaae40c4) --- .github/actions/setup-godot-cpp/action.yml | 8 + .github/workflows/ci-cmake.yml | 195 ++++ .github/workflows/{ci.yml => ci-scons.yml} | 42 +- .github/workflows/runner.yml | 56 +- .github/workflows/static_checks.yml | 14 +- CMakeLists.txt | 2 +- cmake/godotcpp.cmake | 2 +- cmake/ios.toolchain.cmake | 1147 ++++++++++++++++++++ 8 files changed, 1408 insertions(+), 58 deletions(-) create mode 100644 .github/workflows/ci-cmake.yml rename .github/workflows/{ci.yml => ci-scons.yml} (83%) create mode 100644 cmake/ios.toolchain.cmake diff --git a/.github/actions/setup-godot-cpp/action.yml b/.github/actions/setup-godot-cpp/action.yml index 287fb2382..008a6b4f0 100644 --- a/.github/actions/setup-godot-cpp/action.yml +++ b/.github/actions/setup-godot-cpp/action.yml @@ -22,10 +22,13 @@ inputs: ndk-version: default: r23c description: Android NDK version. + buildtool: + description: scons or cmake scons-version: default: 4.4.0 description: SCons version. + runs: using: composite steps: @@ -55,8 +58,13 @@ runs: version: ${{ inputs.mingw-version }} - name: Setup SCons + if: ${{ inputs.buildtool == 'scons' }} shell: bash run: | python -c "import sys; print(sys.version)" python -m pip install scons==${{ inputs.scons-version }} scons --version + + - name: Install Ninja + if: ${{ inputs.buildtool == 'cmake' }} + uses: ashutoshvarma/setup-ninja@master diff --git a/.github/workflows/ci-cmake.yml b/.github/workflows/ci-cmake.yml new file mode 100644 index 000000000..706c87b9a --- /dev/null +++ b/.github/workflows/ci-cmake.yml @@ -0,0 +1,195 @@ +name: Continuous integration +on: + workflow_call: + +env: + # Only used for the cache key. Increment version to force clean build. + GODOT_BASE_BRANCH: master + # Used to select the version of Godot to run the tests with. + GODOT_TEST_VERSION: master + # Use UTF-8 on Linux. + LANG: en_US.UTF-8 + LC_ALL: en_US.UTF-8 + +concurrency: + group: ci-cmake-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build-cmake: + name: ${{ matrix.name }} + runs-on: ${{ matrix.os }} + env: + EM_VERSION: 3.1.39 + config-flags: + -DCMAKE_C_COMPILER_LAUNCHER=sccache + -DCMAKE_CXX_COMPILER_LAUNCHER=sccache + -DGODOTCPP_ENABLE_TESTING=ON + -DGODOTCPP_BUILD_PROFILE="test/build_profile.json" + SCCACHE_GHA_ENABLED: "true" + + strategy: + fail-fast: false + matrix: + include: + - name: 🐧 Linux (GCC, Makefiles) + os: ubuntu-22.04 + platform: linux + config-flags: -DCMAKE_BUILD_TYPE=Release + artifact-name: godot-cpp-linux-glibc2.27-x86_64-release.cmake + artifact-path: cmake-build/bin/libgodot-cpp.linux.template_release.x86_64.a + run-tests: true + + - name: 🐧 Linux (GCC, Makefiles, Double Precision) + os: ubuntu-22.04 + platform: linux + config-flags: -DCMAKE_BUILD_TYPE=Release -DGODOTCPP_PRECISION=double + artifact-name: godot-cpp-linux-glibc2.27-x86_64-double-release.cmake + artifact-path: cmake-build/bin/libgodot-cpp.linux.template_release.double.x86_64.a + flags: precision=double + run-tests: false + + - name: 🏁 Windows (x86_64, MSVC) + os: windows-2019 + platform: windows + compiler: msvc + build-flags: --config Release + artifact-name: godot-cpp-windows-msvc2019-x86_64-release.cmake + artifact-path: cmake-build/bin/libgodot-cpp.windows.template_release.x86_64.lib + run-tests: false + + - name: 🏁 Windows (x86_64, MinGW, Ninja) + os: windows-2019 + platform: windows + compiler: mingw + config-flags: + -GNinja -DCMAKE_BUILD_TYPE=Release + -DCMAKE_CXX_COMPILER=cc -DCMAKE_CXX_COMPILER=c++ + artifact-name: godot-cpp-linux-mingw-x86_64-release.cmake + artifact-path: cmake-build/bin/libgodot-cpp.windows.template_release.x86_64.a + run-tests: false + + - name: 🍎 macOS (universal, Makefiles) + os: macos-latest + platform: macos + config-flags: -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" + artifact-name: godot-cpp-macos-universal-release.cmake + artifact-path: cmake-build/bin/libgodot-cpp.macos.template_release.universal.a + run-tests: false + + - name: 🤖 Android (arm64, Ninja) + os: ubuntu-22.04 + platform: android + config-flags: + -G Ninja -DCMAKE_BUILD_TYPE=Release + --toolchain ${ANDROID_HOME}/ndk/23.2.8568313/build/cmake/android.toolchain.cmake + -DANDROID_PLATFORM=21 -DANDROID_ABI=arm64-v8a + artifact-name: godot-cpp-android-arm64-release.cmake + artifact-path: cmake-build/bin/libgodot-cpp.android.template_release.arm64.a + flags: arch=arm64 + run-tests: false + + - name: 🍏 iOS (arm64, XCode) + os: macos-latest + platform: ios + config-flags: + -G Xcode + --toolchain cmake/ios.toolchain.cmake + -DPLATFORM=OS64 + build-flags: --config Release + artifact-name: godot-cpp-ios-arm64-release.cmake + artifact-path: cmake-build/bin/libgodot-cpp.ios.template_release.arm64.a + flags: arch=arm64 + run-tests: false + + - name: 🌐 Web (wasm32, Ninja) + os: ubuntu-22.04 + platform: web + config-flags: + -G Ninja -DCMAKE_BUILD_TYPE=Release + --toolchain ${EMSDK}/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake + artifact-name: godot-cpp-web-wasm32-release.cmake + artifact-path: cmake-build/bin/libgodot-cpp.web.template_release.wasm32.a + run-tests: false + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Run sccache-cache + uses: mozilla-actions/sccache-action@v0.0.7 + + - name: Setup godot-cpp + uses: ./.github/actions/setup-godot-cpp + with: + platform: ${{ matrix.platform }} + windows-compiler: ${{ matrix.compiler }} + buildtool: cmake + + - name: Configure godot-cpp-test with template_debug + run: > + cmake --log-level=VERBOSE -S . -B cmake-build ${{ env.config-flags }} ${{ matrix.config-flags }} + + - name: Build godot-cpp-test (template_debug) + run: > + cmake --build cmake-build --verbose --target godot-cpp-test ${{ matrix.build-flags }} + + - name: Configure godot-cpp-test with template_release + run: > + cmake --fresh --log-level=VERBOSE -S . -B cmake-build + -DGODOTCPP_TARGET=template_release ${{ env.config-flags }} ${{ matrix.config-flags }} + + - name: Build godot-cpp-test (template_release) + run: > + cmake --build cmake-build --verbose --target godot-cpp-test ${{ matrix.build-flags }} + + - name: Run sccache stat for check + shell: bash + run: ${SCCACHE_PATH} --show-stats + + - name: Download latest Godot artifacts + uses: dsnopek/action-download-artifact@1322f74e2dac9feed2ee76a32d9ae1ca3b4cf4e9 + if: matrix.run-tests && env.GODOT_TEST_VERSION == 'master' + with: + repo: godotengine/godot + branch: master + event: push + workflow: linux_builds.yml + workflow_conclusion: success + name: linux-editor-mono + search_artifacts: true + check_artifacts: true + ensure_latest: true + path: godot-artifacts + + - name: Prepare Godot artifacts for testing + if: matrix.run-tests && env.GODOT_TEST_VERSION == 'master' + run: | + chmod +x ./godot-artifacts/godot.linuxbsd.editor.x86_64.mono + echo "GODOT=$(pwd)/godot-artifacts/godot.linuxbsd.editor.x86_64.mono" >> $GITHUB_ENV + + - name: Download requested Godot version for testing + if: matrix.run-tests && env.GODOT_TEST_VERSION != 'master' + run: | + wget "https://github.com/godotengine/godot-builds/releases/download/${GODOT_TEST_VERSION}/Godot_v${GODOT_TEST_VERSION}_linux.x86_64.zip" -O Godot.zip + unzip -a Godot.zip + chmod +x "Godot_v${GODOT_TEST_VERSION}_linux.x86_64" + echo "GODOT=$(pwd)/Godot_v${GODOT_TEST_VERSION}_linux.x86_64" >> $GITHUB_ENV + + - name: Run tests + if: matrix.run-tests + run: | + $GODOT --headless --version + cd test + # Need to run the editor so .godot is generated... but it crashes! Ignore that :-) + (cd project && (timeout 30 $GODOT --import --headless >/dev/null 2>&1 || true)) + ./run-tests.sh + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.artifact-name }} + path: ${{ matrix.artifact-path }} + if-no-files-found: error diff --git a/.github/workflows/ci.yml b/.github/workflows/ci-scons.yml similarity index 83% rename from .github/workflows/ci.yml rename to .github/workflows/ci-scons.yml index 5782b310f..b951c29c0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci-scons.yml @@ -12,11 +12,11 @@ env: LC_ALL: en_US.UTF-8 concurrency: - group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }} + group: ci-scons-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }} cancel-in-progress: true jobs: - build: + build-scons: name: ${{ matrix.name }} runs-on: ${{ matrix.os }} strategy: @@ -113,6 +113,7 @@ jobs: with: platform: ${{ matrix.platform }} windows-compiler: ${{ contains(matrix.flags, 'use_mingw=yes') && 'mingw' || 'msvc' }} + buildtool: scons - name: Generate godot-cpp sources only run: | @@ -183,40 +184,3 @@ jobs: name: ${{ matrix.artifact-name }} path: ${{ matrix.artifact-path }} if-no-files-found: error - - linux-cmake-ninja: - name: 🐧 Build (Linux, GCC, CMake Ninja) - runs-on: ubuntu-22.04 - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Install dependencies - run: | - sudo apt-get update -qq - sudo apt-get install -qqq build-essential pkg-config cmake ninja-build - - - name: Build test GDExtension library - run: | - mkdir cmake-build - cd cmake-build - cmake ../ -DGODOTCPP_ENABLE_TESTING=YES -DGODOTCPP_TARGET=template_release - cmake --build . --verbose -j $(nproc) --target godot-cpp-test --config Release - - windows-msvc-cmake: - name: 🏁 Build (Windows, MSVC, CMake) - runs-on: windows-2019 - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Build test GDExtension library - run: | - mkdir cmake-build - cd cmake-build - cmake ../ -DGODOTCPP_ENABLE_TESTING=YES -DGODOTCPP_TARGET=template_release - cmake --build . --verbose --target godot-cpp-test --config Release diff --git a/.github/workflows/runner.yml b/.github/workflows/runner.yml index a2e4f91b8..d056236ab 100644 --- a/.github/workflows/runner.yml +++ b/.github/workflows/runner.yml @@ -9,13 +9,57 @@ jobs: # First stage: Only static checks, fast and prevent expensive builds from running. static-checks: - if: '!vars.DISABLE_GODOT_CI' name: 📊 Static Checks + if: '!vars.DISABLE_GODOT_CI' uses: ./.github/workflows/static_checks.yml - # Second stage: Run all the builds and some of the tests. - - ci: - name: 🛠️ Continuous Integration + # Second stage: Review code changes + changes: + name: Analyze Changes needs: static-checks - uses: ./.github/workflows/ci.yml + runs-on: ubuntu-latest + outputs: + sources: ${{ steps.filter.outputs.sources_any_changed }} + scons: ${{ steps.filter.outputs.scons_any_changed }} + cmake: ${{ steps.filter.outputs.cmake_any_changed }} + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - uses: tj-actions/changed-files@v45 + id: filter + with: + files_yaml: | + sources: + - '.github/workflows/*.yml' + - '**/*.py' + - '**/*.cpp' + - '**/*.h' + - 'test/build_profile.json' + - 'gdextension/extension_api.json' + scons: + - '**/SConstruct' + - '**/SCsub' + - '**/*.py' + cmake: + - '**/CMakeLists.txt' + - '**/*.cmake' + - name: echo sources changed + run: | + echo sources ${{ steps.filter.outputs.sources_any_modified }} + echo scons ${{ steps.filter.outputs.scons_any_modified }} + echo cmake ${{ steps.filter.outputs.cmake_any_modified }} + + # Third stage: Run all the builds and some of the tests. + + ci-scons: + name: 🛠️ SCons CI + needs: changes + if: ${{ needs.changes.outputs.scons == 'true' || needs.changes.outputs.sources == 'true' }} + uses: ./.github/workflows/ci-scons.yml + + ci-cmake: + name: 🛠️ CMake CI + needs: changes + if: ${{ needs.changes.outputs.cmake == 'true' || needs.changes.outputs.sources == 'true' }} + uses: ./.github/workflows/ci-cmake.yml diff --git a/.github/workflows/static_checks.yml b/.github/workflows/static_checks.yml index a3d813226..868e80129 100644 --- a/.github/workflows/static_checks.yml +++ b/.github/workflows/static_checks.yml @@ -17,21 +17,13 @@ jobs: fetch-depth: 2 - name: Get changed files - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - if [ "${{ github.event_name }}" == "pull_request" ]; then - files=$(git diff-tree --no-commit-id --name-only -r HEAD^1..HEAD 2> /dev/null || true) - elif [ "${{ github.event_name }}" == "push" -a "${{ github.event.forced }}" == "false" -a "${{ github.event.created }}" == "false" ]; then - files=$(git diff-tree --no-commit-id --name-only -r ${{ github.event.before }}..${{ github.event.after }} 2> /dev/null || true) - fi - files=$(echo "$files" | grep -v 'thirdparty' | xargs -I {} sh -c 'echo "\"./{}\""' | tr '\n' ' ') - echo "CHANGED_FILES=$files" >> $GITHUB_ENV + id: changed-files + uses: tj-actions/changed-files@v45 - name: Style checks via pre-commit uses: pre-commit/action@v3.0.1 with: - extra_args: --verbose --hook-stage manual --files ${{ env.CHANGED_FILES }} + extra_args: --verbose --hook-stage manual --files ${{ steps.changed-files.outputs.all_changed_files }} - name: Check generated files consistency run: diff --git a/CMakeLists.txt b/CMakeLists.txt index 32dce3ec7..4c2be6d8c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.17) +cmake_minimum_required(VERSION 3.10...3.17) #[=======================================================================[.rst: diff --git a/cmake/godotcpp.cmake b/cmake/godotcpp.cmake index 8ae938bf9..b93280543 100644 --- a/cmake/godotcpp.cmake +++ b/cmake/godotcpp.cmake @@ -276,7 +276,7 @@ function(godotcpp_generate) string( CONCAT SYSTEM_NAME - "$<$:android.${ANDROID_ABI}>" + "$<$:android>" "$<$:ios>" "$<$:linux>" "$<$:macos>" diff --git a/cmake/ios.toolchain.cmake b/cmake/ios.toolchain.cmake new file mode 100644 index 000000000..d82518162 --- /dev/null +++ b/cmake/ios.toolchain.cmake @@ -0,0 +1,1147 @@ +# gersemi: off +# This file is part of the ios-cmake project. It was retrieved from +# https://github.com/leetal/ios-cmake.git, which is a fork of +# https://github.com/gerstrong/ios-cmake.git, which is a fork of +# https://github.com/cristeab/ios-cmake.git, which is a fork of +# https://code.google.com/p/ios-cmake/. Which in turn is based off of +# the Platform/Darwin.cmake and Platform/UnixPaths.cmake files which +# are included with CMake 2.8.4 +# +# The ios-cmake project is licensed under the new BSD license. +# +# Copyright (c) 2014, Bogdan Cristea and LTE Engineering Software, +# Kitware, Inc., Insight Software Consortium. All rights reserved. +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# This file is based on the Platform/Darwin.cmake and +# Platform/UnixPaths.cmake files which are included with CMake 2.8.4 +# It has been altered for iOS development. +# +# Updated by Alex Stewart (alexs.mac@gmail.com) +# +# ***************************************************************************** +# Now maintained by Alexander Widerberg (widerbergaren [at] gmail.com) +# under the BSD-3-Clause license +# https://github.com/leetal/ios-cmake +# ***************************************************************************** +# +# INFORMATION / HELP +# +############################################################################### +# OPTIONS # +############################################################################### +# +# PLATFORM: (default "OS64") +# OS = Build for iPhoneOS. +# OS64 = Build for arm64 iphoneOS. +# OS64COMBINED = Build for arm64 x86_64 iphoneOS + iphoneOS Simulator. Combined into FAT STATIC lib (only supported on 3.14+ of CMake with "-G Xcode" argument in combination with the "cmake --install" CMake build step) +# SIMULATOR = Build for x86 i386 iphoneOS Simulator. +# SIMULATOR64 = Build for x86_64 iphoneOS Simulator. +# SIMULATORARM64 = Build for arm64 iphoneOS Simulator. +# SIMULATOR64COMBINED = Build for arm64 x86_64 iphoneOS Simulator. Combined into FAT STATIC lib (supported on 3.14+ of CMakewith "-G Xcode" argument ONLY) +# TVOS = Build for arm64 tvOS. +# TVOSCOMBINED = Build for arm64 x86_64 tvOS + tvOS Simulator. Combined into FAT STATIC lib (only supported on 3.14+ of CMake with "-G Xcode" argument in combination with the "cmake --install" CMake build step) +# SIMULATOR_TVOS = Build for x86_64 tvOS Simulator. +# SIMULATORARM64_TVOS = Build for arm64 tvOS Simulator. +# VISIONOSCOMBINED = Build for arm64 visionOS + visionOS Simulator. Combined into FAT STATIC lib (only supported on 3.14+ of CMake with "-G Xcode" argument in combination with the "cmake --install" CMake build step) +# VISIONOS = Build for arm64 visionOS. +# SIMULATOR_VISIONOS = Build for arm64 visionOS Simulator. +# WATCHOS = Build for armv7k arm64_32 for watchOS. +# WATCHOSCOMBINED = Build for armv7k arm64_32 x86_64 watchOS + watchOS Simulator. Combined into FAT STATIC lib (only supported on 3.14+ of CMake with "-G Xcode" argument in combination with the "cmake --install" CMake build step) +# SIMULATOR_WATCHOS = Build for x86_64 for watchOS Simulator. +# SIMULATORARM64_WATCHOS = Build for arm64 for watchOS Simulator. +# MAC = Build for x86_64 macOS. +# MAC_ARM64 = Build for Apple Silicon macOS. +# MAC_UNIVERSAL = Combined build for x86_64 and Apple Silicon on macOS. +# MAC_CATALYST = Build for x86_64 macOS with Catalyst support (iOS toolchain on macOS). +# Note: The build argument "MACOSX_DEPLOYMENT_TARGET" can be used to control min-version of macOS +# MAC_CATALYST_ARM64 = Build for Apple Silicon macOS with Catalyst support (iOS toolchain on macOS). +# Note: The build argument "MACOSX_DEPLOYMENT_TARGET" can be used to control min-version of macOS +# MAC_CATALYST_UNIVERSAL = Combined build for x86_64 and Apple Silicon on Catalyst. +# +# CMAKE_OSX_SYSROOT: Path to the SDK to use. By default this is +# automatically determined from PLATFORM and xcodebuild, but +# can also be manually specified (although this should not be required). +# +# CMAKE_DEVELOPER_ROOT: Path to the Developer directory for the platform +# being compiled for. By default, this is automatically determined from +# CMAKE_OSX_SYSROOT, but can also be manually specified (although this should +# not be required). +# +# DEPLOYMENT_TARGET: Minimum SDK version to target. Default 6.0 on watchOS, 13.0 on tvOS+iOS/iPadOS, 11.0 on macOS, 1.0 on visionOS +# +# NAMED_LANGUAGE_SUPPORT: +# ON (default) = Will require "enable_language(OBJC) and/or enable_language(OBJCXX)" for full OBJC|OBJCXX support +# OFF = Will embed the OBJC and OBJCXX flags into the CMAKE_C_FLAGS and CMAKE_CXX_FLAGS (legacy behavior, CMake version < 3.16) +# +# ENABLE_BITCODE: (ON|OFF) Enables or disables bitcode support. Default OFF +# +# ENABLE_ARC: (ON|OFF) Enables or disables ARC support. Default ON (ARC enabled by default) +# +# ENABLE_VISIBILITY: (ON|OFF) Enables or disables symbol visibility support. Default OFF (visibility hidden by default) +# +# ENABLE_STRICT_TRY_COMPILE: (ON|OFF) Enables or disables strict try_compile() on all Check* directives (will run linker +# to actually check if linking is possible). Default OFF (will set CMAKE_TRY_COMPILE_TARGET_TYPE to STATIC_LIBRARY) +# +# ARCHS: (armv7 armv7s armv7k arm64 arm64_32 i386 x86_64) If specified, will override the default architectures for the given PLATFORM +# OS = armv7 armv7s arm64 (if applicable) +# OS64 = arm64 (if applicable) +# SIMULATOR = i386 +# SIMULATOR64 = x86_64 +# SIMULATORARM64 = arm64 +# TVOS = arm64 +# SIMULATOR_TVOS = x86_64 (i386 has since long been deprecated) +# SIMULATORARM64_TVOS = arm64 +# WATCHOS = armv7k arm64_32 (if applicable) +# SIMULATOR_WATCHOS = x86_64 (i386 has since long been deprecated) +# SIMULATORARM64_WATCHOS = arm64 +# MAC = x86_64 +# MAC_ARM64 = arm64 +# MAC_UNIVERSAL = x86_64 arm64 +# MAC_CATALYST = x86_64 +# MAC_CATALYST_ARM64 = arm64 +# MAC_CATALYST_UNIVERSAL = x86_64 arm64 +# +# NOTE: When manually specifying ARCHS, put a semi-colon between the entries. E.g., -DARCHS="armv7;arm64" +# +############################################################################### +# END OPTIONS # +############################################################################### +# +# This toolchain defines the following properties (available via get_property()) for use externally: +# +# PLATFORM: The currently targeted platform. +# XCODE_VERSION: Version number (not including Build version) of Xcode detected. +# SDK_VERSION: Version of SDK being used. +# OSX_ARCHITECTURES: Architectures being compiled for (generated from PLATFORM). +# APPLE_TARGET_TRIPLE: Used by autoconf build systems. NOTE: If "ARCHS" is overridden, this will *NOT* be set! +# +# This toolchain defines the following macros for use externally: +# +# set_xcode_property (TARGET XCODE_PROPERTY XCODE_VALUE XCODE_VARIANT) +# A convenience macro for setting xcode specific properties on targets. +# Available variants are: All, Release, RelWithDebInfo, Debug, MinSizeRel +# example: set_xcode_property (myioslib IPHONEOS_DEPLOYMENT_TARGET "3.1" "all"). +# +# find_host_package (PROGRAM ARGS) +# A macro used to find executable programs on the host system, not within the +# environment. Thanks to the android-cmake project for providing the +# command. +# + +cmake_minimum_required(VERSION 3.8.0) + +# CMake invokes the toolchain file twice during the first build, but only once during subsequent rebuilds. +# NOTE: To improve single-library build-times, provide the flag "OS_SINGLE_BUILD" as a build argument. +if(DEFINED OS_SINGLE_BUILD AND DEFINED ENV{_IOS_TOOLCHAIN_HAS_RUN}) + return() +endif() +set(ENV{_IOS_TOOLCHAIN_HAS_RUN} true) + +# List of supported platform values +list(APPEND _supported_platforms + "OS" "OS64" "OS64COMBINED" "SIMULATOR" "SIMULATOR64" "SIMULATORARM64" "SIMULATOR64COMBINED" + "TVOS" "TVOSCOMBINED" "SIMULATOR_TVOS" "SIMULATORARM64_TVOS" + "WATCHOS" "WATCHOSCOMBINED" "SIMULATOR_WATCHOS" "SIMULATORARM64_WATCHOS" + "MAC" "MAC_ARM64" "MAC_UNIVERSAL" + "VISIONOS" "SIMULATOR_VISIONOS" "VISIONOSCOMBINED" + "MAC_CATALYST" "MAC_CATALYST_ARM64" "MAC_CATALYST_UNIVERSAL") + +# Cache what generator is used +set(USED_CMAKE_GENERATOR "${CMAKE_GENERATOR}") + +# Check if using a CMake version capable of building combined FAT builds (simulator and target slices combined in one static lib) +if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.14") + set(MODERN_CMAKE YES) +endif() + +# Get the Xcode version being used. +# Problem: CMake runs toolchain files multiple times, but can't read cache variables on some runs. +# Workaround: On the first run (in which cache variables are always accessible), set an intermediary environment variable. +# +# NOTE: This pattern is used in many places in this toolchain to speed up checks of all sorts +if(DEFINED XCODE_VERSION_INT) + # Environment variables are always preserved. + set(ENV{_XCODE_VERSION_INT} "${XCODE_VERSION_INT}") +elseif(DEFINED ENV{_XCODE_VERSION_INT}) + set(XCODE_VERSION_INT "$ENV{_XCODE_VERSION_INT}") +elseif(NOT DEFINED XCODE_VERSION_INT) + find_program(XCODEBUILD_EXECUTABLE xcodebuild) + if(NOT XCODEBUILD_EXECUTABLE) + message(FATAL_ERROR "xcodebuild not found. Please install either the standalone commandline tools or Xcode.") + endif() + execute_process(COMMAND ${XCODEBUILD_EXECUTABLE} -version + OUTPUT_VARIABLE XCODE_VERSION_INT + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REGEX MATCH "Xcode [0-9\\.]+" XCODE_VERSION_INT "${XCODE_VERSION_INT}") + string(REGEX REPLACE "Xcode ([0-9\\.]+)" "\\1" XCODE_VERSION_INT "${XCODE_VERSION_INT}") + set(XCODE_VERSION_INT "${XCODE_VERSION_INT}" CACHE INTERNAL "") +endif() + +# Assuming that xcode 12.0 is installed you most probably have ios sdk 14.0 or later installed (tested on Big Sur) +# if you don't set a deployment target it will be set the way you only get 64-bit builds +#if(NOT DEFINED DEPLOYMENT_TARGET AND XCODE_VERSION_INT VERSION_GREATER 12.0) +# Temporarily fix the arm64 issues in CMake install-combined by excluding arm64 for simulator builds (needed for Apple Silicon...) +# set(CMAKE_XCODE_ATTRIBUTE_EXCLUDED_ARCHS[sdk=iphonesimulator*] "arm64") +#endif() + +# Check if the platform variable is set +if(DEFINED PLATFORM) + # Environment variables are always preserved. + set(ENV{_PLATFORM} "${PLATFORM}") +elseif(DEFINED ENV{_PLATFORM}) + set(PLATFORM "$ENV{_PLATFORM}") +elseif(NOT DEFINED PLATFORM) + message(FATAL_ERROR "PLATFORM argument not set. Bailing configure since I don't know what target you want to build for!") +endif () + +if(PLATFORM MATCHES ".*COMBINED" AND NOT CMAKE_GENERATOR MATCHES "Xcode") + message(FATAL_ERROR "The combined builds support requires Xcode to be used as a generator via '-G Xcode' command-line argument in CMake") +endif() + +# Safeguard that the platform value is set and is one of the supported values +list(FIND _supported_platforms ${PLATFORM} contains_PLATFORM) +if("${contains_PLATFORM}" EQUAL "-1") + string(REPLACE ";" "\n * " _supported_platforms_formatted "${_supported_platforms}") + message(FATAL_ERROR " Invalid PLATFORM specified! Current value: ${PLATFORM}.\n" + " Supported PLATFORM values: \n * ${_supported_platforms_formatted}") +endif() + +# Check if Apple Silicon is supported +if(PLATFORM MATCHES "^(MAC_ARM64)$|^(MAC_CATALYST_ARM64)$|^(MAC_UNIVERSAL)$|^(MAC_CATALYST_UNIVERSAL)$" AND ${CMAKE_VERSION} VERSION_LESS "3.19.5") + message(FATAL_ERROR "Apple Silicon builds requires a minimum of CMake 3.19.5") +endif() + +# Touch the toolchain variable to suppress the "unused variable" warning. +# This happens if CMake is invoked with the same command line the second time. +if(CMAKE_TOOLCHAIN_FILE) +endif() + +# Fix for PThread library not in path +set(CMAKE_THREAD_LIBS_INIT "-lpthread") +set(CMAKE_HAVE_THREADS_LIBRARY 1) +set(CMAKE_USE_WIN32_THREADS_INIT 0) +set(CMAKE_USE_PTHREADS_INIT 1) + +# Specify named language support defaults. +if(NOT DEFINED NAMED_LANGUAGE_SUPPORT AND ${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.16") + set(NAMED_LANGUAGE_SUPPORT ON) + message(STATUS "[DEFAULTS] Using explicit named language support! E.g., enable_language(CXX) is needed in the project files.") +elseif(NOT DEFINED NAMED_LANGUAGE_SUPPORT AND ${CMAKE_VERSION} VERSION_LESS "3.16") + set(NAMED_LANGUAGE_SUPPORT OFF) + message(STATUS "[DEFAULTS] Disabling explicit named language support. Falling back to legacy behavior.") +elseif(DEFINED NAMED_LANGUAGE_SUPPORT AND ${CMAKE_VERSION} VERSION_LESS "3.16") + message(FATAL_ERROR "CMake named language support for OBJC and OBJCXX was added in CMake 3.16.") +endif() +set(NAMED_LANGUAGE_SUPPORT_INT ${NAMED_LANGUAGE_SUPPORT} CACHE BOOL + "Whether or not to enable explicit named language support" FORCE) + +# Specify the minimum version of the deployment target. +if(NOT DEFINED DEPLOYMENT_TARGET) + if (PLATFORM MATCHES "WATCHOS") + # Unless specified, SDK version 4.0 is used by default as minimum target version (watchOS). + set(DEPLOYMENT_TARGET "6.0") + elseif(PLATFORM STREQUAL "MAC") + # Unless specified, SDK version 10.13 (High Sierra) is used by default as the minimum target version (macos). + set(DEPLOYMENT_TARGET "11.0") + elseif(PLATFORM STREQUAL "VISIONOS" OR PLATFORM STREQUAL "SIMULATOR_VISIONOS" OR PLATFORM STREQUAL "VISIONOSCOMBINED") + # Unless specified, SDK version 1.0 is used by default as minimum target version (visionOS). + set(DEPLOYMENT_TARGET "1.0") + elseif(PLATFORM STREQUAL "MAC_ARM64") + # Unless specified, SDK version 11.0 (Big Sur) is used by default as the minimum target version (macOS on arm). + set(DEPLOYMENT_TARGET "11.0") + elseif(PLATFORM STREQUAL "MAC_UNIVERSAL") + # Unless specified, SDK version 11.0 (Big Sur) is used by default as minimum target version for universal builds. + set(DEPLOYMENT_TARGET "11.0") + elseif(PLATFORM STREQUAL "MAC_CATALYST" OR PLATFORM STREQUAL "MAC_CATALYST_ARM64" OR PLATFORM STREQUAL "MAC_CATALYST_UNIVERSAL") + # Unless specified, SDK version 13.0 is used by default as the minimum target version (mac catalyst minimum requirement). + set(DEPLOYMENT_TARGET "13.1") + else() + # Unless specified, SDK version 11.0 is used by default as the minimum target version (iOS, tvOS). + set(DEPLOYMENT_TARGET "13.0") + endif() + message(STATUS "[DEFAULTS] Using the default min-version since DEPLOYMENT_TARGET not provided!") +elseif(DEFINED DEPLOYMENT_TARGET AND PLATFORM MATCHES "^MAC_CATALYST" AND ${DEPLOYMENT_TARGET} VERSION_LESS "13.1") + message(FATAL_ERROR "Mac Catalyst builds requires a minimum deployment target of 13.1!") +endif() + +# Store the DEPLOYMENT_TARGET in the cache +set(DEPLOYMENT_TARGET "${DEPLOYMENT_TARGET}" CACHE INTERNAL "") + +# Handle the case where we are targeting iOS and a version above 10.3.4 (32-bit support dropped officially) +if(PLATFORM STREQUAL "OS" AND DEPLOYMENT_TARGET VERSION_GREATER_EQUAL 10.3.4) + set(PLATFORM "OS64") + message(STATUS "Targeting minimum SDK version ${DEPLOYMENT_TARGET}. Dropping 32-bit support.") +elseif(PLATFORM STREQUAL "SIMULATOR" AND DEPLOYMENT_TARGET VERSION_GREATER_EQUAL 10.3.4) + set(PLATFORM "SIMULATOR64") + message(STATUS "Targeting minimum SDK version ${DEPLOYMENT_TARGET}. Dropping 32-bit support.") +endif() + +set(PLATFORM_INT "${PLATFORM}") + +if(DEFINED ARCHS) + string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") +endif() + +# Determine the platform name and architectures for use in xcodebuild commands +# from the specified PLATFORM_INT name. +if(PLATFORM_INT STREQUAL "OS") + set(SDK_NAME iphoneos) + if(NOT ARCHS) + set(ARCHS armv7 armv7s arm64) + set(APPLE_TARGET_TRIPLE_INT arm-apple-ios${DEPLOYMENT_TARGET}) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}) + endif() +elseif(PLATFORM_INT STREQUAL "OS64") + set(SDK_NAME iphoneos) + if(NOT ARCHS) + if (XCODE_VERSION_INT VERSION_GREATER 10.0) + set(ARCHS arm64) # FIXME: Add arm64e when Apple has fixed the integration issues with it, libarclite_iphoneos.a is currently missing bitcode markers for example + else() + set(ARCHS arm64) + endif() + set(APPLE_TARGET_TRIPLE_INT arm64-apple-ios${DEPLOYMENT_TARGET}) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}) + endif() +elseif(PLATFORM_INT STREQUAL "OS64COMBINED") + set(SDK_NAME iphoneos) + if(MODERN_CMAKE) + if(NOT ARCHS) + if (XCODE_VERSION_INT VERSION_GREATER 12.0) + set(ARCHS arm64 x86_64) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64 arm64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64 arm64") + else() + set(ARCHS arm64 x86_64) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64") + endif() + set(APPLE_TARGET_TRIPLE_INT arm64-x86_64-apple-ios${DEPLOYMENT_TARGET}) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}) + endif() + else() + message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the OS64COMBINED setting work") + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATOR64COMBINED") + set(SDK_NAME iphonesimulator) + if(MODERN_CMAKE) + if(NOT ARCHS) + if (XCODE_VERSION_INT VERSION_GREATER 12.0) + set(ARCHS arm64 x86_64) # FIXME: Add arm64e when Apple have fixed the integration issues with it, libarclite_iphoneos.a is currently missing bitcode markers for example + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64 arm64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64 arm64") + else() + set(ARCHS arm64 x86_64) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64") + endif() + set(APPLE_TARGET_TRIPLE_INT aarch64-x86_64-apple-ios${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator) + endif() + else() + message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the SIMULATOR64COMBINED setting work") + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATOR") + set(SDK_NAME iphonesimulator) + if(NOT ARCHS) + set(ARCHS i386) + set(APPLE_TARGET_TRIPLE_INT i386-apple-ios${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator) + endif() + message(DEPRECATION "SIMULATOR IS DEPRECATED. Consider using SIMULATOR64 instead.") +elseif(PLATFORM_INT STREQUAL "SIMULATOR64") + set(SDK_NAME iphonesimulator) + if(NOT ARCHS) + set(ARCHS x86_64) + set(APPLE_TARGET_TRIPLE_INT x86_64-apple-ios${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator) + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATORARM64") + set(SDK_NAME iphonesimulator) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-ios${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator) + endif() +elseif(PLATFORM_INT STREQUAL "TVOS") + set(SDK_NAME appletvos) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-tvos${DEPLOYMENT_TARGET}) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET}) + endif() +elseif (PLATFORM_INT STREQUAL "TVOSCOMBINED") + set(SDK_NAME appletvos) + if(MODERN_CMAKE) + if(NOT ARCHS) + set(ARCHS arm64 x86_64) + set(APPLE_TARGET_TRIPLE_INT arm64-x86_64-apple-tvos${DEPLOYMENT_TARGET}) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=appletvos*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=appletvsimulator*] "x86_64 arm64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=appletvos*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=appletvsimulator*] "x86_64 arm64") + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET}) + endif() + else() + message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the TVOSCOMBINED setting work") + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATOR_TVOS") + set(SDK_NAME appletvsimulator) + if(NOT ARCHS) + set(ARCHS x86_64) + set(APPLE_TARGET_TRIPLE_INT x86_64-apple-tvos${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET}-simulator) + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATORARM64_TVOS") + set(SDK_NAME appletvsimulator) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-tvos${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET}-simulator) + endif() +elseif(PLATFORM_INT STREQUAL "WATCHOS") + set(SDK_NAME watchos) + if(NOT ARCHS) + if (XCODE_VERSION_INT VERSION_GREATER 10.0) + set(ARCHS armv7k arm64_32) + set(APPLE_TARGET_TRIPLE_INT arm64_32-apple-watchos${DEPLOYMENT_TARGET}) + else() + set(ARCHS armv7k) + set(APPLE_TARGET_TRIPLE_INT arm-apple-watchos${DEPLOYMENT_TARGET}) + endif() + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET}) + endif() +elseif(PLATFORM_INT STREQUAL "WATCHOSCOMBINED") + set(SDK_NAME watchos) + if(MODERN_CMAKE) + if(NOT ARCHS) + if (XCODE_VERSION_INT VERSION_GREATER 10.0) + set(ARCHS armv7k arm64_32 i386) + set(APPLE_TARGET_TRIPLE_INT arm64_32-i386-apple-watchos${DEPLOYMENT_TARGET}) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchos*] "armv7k arm64_32") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchsimulator*] "i386") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchos*] "armv7k arm64_32") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchsimulator*] "i386") + else() + set(ARCHS armv7k i386) + set(APPLE_TARGET_TRIPLE_INT arm-i386-apple-watchos${DEPLOYMENT_TARGET}) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchos*] "armv7k") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchsimulator*] "i386") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchos*] "armv7k") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchsimulator*] "i386") + endif() + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET}) + endif() + else() + message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the WATCHOSCOMBINED setting work") + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATOR_WATCHOS") + set(SDK_NAME watchsimulator) + if(NOT ARCHS) + set(ARCHS i386) + set(APPLE_TARGET_TRIPLE_INT i386-apple-watchos${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET}-simulator) + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATORARM64_WATCHOS") + set(SDK_NAME watchsimulator) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-watchos${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET}-simulator) + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATOR_VISIONOS") + set(SDK_NAME xrsimulator) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-xros${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-xros${DEPLOYMENT_TARGET}-simulator) + endif() +elseif(PLATFORM_INT STREQUAL "VISIONOS") + set(SDK_NAME xros) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-xros${DEPLOYMENT_TARGET}) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-xros${DEPLOYMENT_TARGET}) + endif() +elseif(PLATFORM_INT STREQUAL "VISIONOSCOMBINED") + set(SDK_NAME xros) + if(MODERN_CMAKE) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-xros${DEPLOYMENT_TARGET}) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=xros*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=xrsimulator*] "arm64") + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-xros${DEPLOYMENT_TARGET}) + endif() + else() + message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the VISIONOSCOMBINED setting work") + endif() +elseif(PLATFORM_INT STREQUAL "MAC" OR PLATFORM_INT STREQUAL "MAC_CATALYST") + set(SDK_NAME macosx) + if(NOT ARCHS) + set(ARCHS x86_64) + endif() + string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") + if(PLATFORM_INT STREQUAL "MAC") + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-macosx${DEPLOYMENT_TARGET}) + elseif(PLATFORM_INT STREQUAL "MAC_CATALYST") + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-macabi) + endif() +elseif(PLATFORM_INT MATCHES "^(MAC_ARM64)$|^(MAC_CATALYST_ARM64)$") + set(SDK_NAME macosx) + if(NOT ARCHS) + set(ARCHS arm64) + endif() + string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") + if(PLATFORM_INT STREQUAL "MAC_ARM64") + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-macosx${DEPLOYMENT_TARGET}) + elseif(PLATFORM_INT STREQUAL "MAC_CATALYST_ARM64") + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-macabi) + endif() +elseif(PLATFORM_INT STREQUAL "MAC_UNIVERSAL") + set(SDK_NAME macosx) + if(NOT ARCHS) + set(ARCHS "x86_64;arm64") + endif() + string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-macosx${DEPLOYMENT_TARGET}) +elseif(PLATFORM_INT STREQUAL "MAC_CATALYST_UNIVERSAL") + set(SDK_NAME macosx) + if(NOT ARCHS) + set(ARCHS "x86_64;arm64") + endif() + string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-macabi) +else() + message(FATAL_ERROR "Invalid PLATFORM: ${PLATFORM_INT}") +endif() + +string(REPLACE ";" " " ARCHS_SPACED "${ARCHS}") + +if(MODERN_CMAKE AND PLATFORM_INT MATCHES ".*COMBINED" AND NOT CMAKE_GENERATOR MATCHES "Xcode") + message(FATAL_ERROR "The COMBINED options only work with Xcode generator, -G Xcode") +endif() + +if(CMAKE_GENERATOR MATCHES "Xcode" AND PLATFORM_INT MATCHES "^MAC_CATALYST") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") + set(CMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS "macosx") + set(CMAKE_XCODE_ATTRIBUTE_SUPPORTS_MACCATALYST "YES") + if(NOT DEFINED MACOSX_DEPLOYMENT_TARGET) + set(CMAKE_XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET "10.15") + else() + set(CMAKE_XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET "${MACOSX_DEPLOYMENT_TARGET}") + endif() +elseif(CMAKE_GENERATOR MATCHES "Xcode") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") + set(CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "${DEPLOYMENT_TARGET}") + if(NOT PLATFORM_INT MATCHES ".*COMBINED") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=${SDK_NAME}*] "${ARCHS_SPACED}") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=${SDK_NAME}*] "${ARCHS_SPACED}") + endif() +endif() + +# If the user did not specify the SDK root to use, then query xcodebuild for it. +if(DEFINED CMAKE_OSX_SYSROOT_INT) + # Environment variables are always preserved. + set(ENV{_CMAKE_OSX_SYSROOT_INT} "${CMAKE_OSX_SYSROOT_INT}") +elseif(DEFINED ENV{_CMAKE_OSX_SYSROOT_INT}) + set(CMAKE_OSX_SYSROOT_INT "$ENV{_CMAKE_OSX_SYSROOT_INT}") +elseif(NOT DEFINED CMAKE_OSX_SYSROOT_INT) + execute_process(COMMAND ${XCODEBUILD_EXECUTABLE} -version -sdk ${SDK_NAME} Path + OUTPUT_VARIABLE CMAKE_OSX_SYSROOT_INT + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() + +if (NOT DEFINED CMAKE_OSX_SYSROOT_INT AND NOT DEFINED CMAKE_OSX_SYSROOT) + message(SEND_ERROR "Please make sure that Xcode is installed and that the toolchain" + "is pointing to the correct path. Please run:" + "sudo xcode-select -s /Applications/Xcode.app/Contents/Developer" + "and see if that fixes the problem for you.") + message(FATAL_ERROR "Invalid CMAKE_OSX_SYSROOT: ${CMAKE_OSX_SYSROOT} " + "does not exist.") +elseif(DEFINED CMAKE_OSX_SYSROOT_INT) + set(CMAKE_OSX_SYSROOT_INT "${CMAKE_OSX_SYSROOT_INT}" CACHE INTERNAL "") + # Specify the location or name of the platform SDK to be used in CMAKE_OSX_SYSROOT. + set(CMAKE_OSX_SYSROOT "${CMAKE_OSX_SYSROOT_INT}" CACHE INTERNAL "") +endif() + +# Use bitcode or not +if(NOT DEFINED ENABLE_BITCODE) + message(STATUS "[DEFAULTS] Disabling bitcode support by default. ENABLE_BITCODE not provided for override!") + set(ENABLE_BITCODE OFF) +endif() +set(ENABLE_BITCODE_INT ${ENABLE_BITCODE} CACHE BOOL + "Whether or not to enable bitcode" FORCE) +# Use ARC or not +if(NOT DEFINED ENABLE_ARC) + # Unless specified, enable ARC support by default + set(ENABLE_ARC ON) + message(STATUS "[DEFAULTS] Enabling ARC support by default. ENABLE_ARC not provided!") +endif() +set(ENABLE_ARC_INT ${ENABLE_ARC} CACHE BOOL "Whether or not to enable ARC" FORCE) +# Use hidden visibility or not +if(NOT DEFINED ENABLE_VISIBILITY) + # Unless specified, disable symbols visibility by default + set(ENABLE_VISIBILITY OFF) + message(STATUS "[DEFAULTS] Hiding symbols visibility by default. ENABLE_VISIBILITY not provided!") +endif() +set(ENABLE_VISIBILITY_INT ${ENABLE_VISIBILITY} CACHE BOOL "Whether or not to hide symbols from the dynamic linker (-fvisibility=hidden)" FORCE) +# Set strict compiler checks or not +if(NOT DEFINED ENABLE_STRICT_TRY_COMPILE) + # Unless specified, disable strict try_compile() + set(ENABLE_STRICT_TRY_COMPILE OFF) + message(STATUS "[DEFAULTS] Using NON-strict compiler checks by default. ENABLE_STRICT_TRY_COMPILE not provided!") +endif() +set(ENABLE_STRICT_TRY_COMPILE_INT ${ENABLE_STRICT_TRY_COMPILE} CACHE BOOL + "Whether or not to use strict compiler checks" FORCE) + +# Get the SDK version information. +if(DEFINED SDK_VERSION) + # Environment variables are always preserved. + set(ENV{_SDK_VERSION} "${SDK_VERSION}") +elseif(DEFINED ENV{_SDK_VERSION}) + set(SDK_VERSION "$ENV{_SDK_VERSION}") +elseif(NOT DEFINED SDK_VERSION) + execute_process(COMMAND ${XCODEBUILD_EXECUTABLE} -sdk ${CMAKE_OSX_SYSROOT_INT} -version SDKVersion + OUTPUT_VARIABLE SDK_VERSION + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() + +# Find the Developer root for the specific iOS platform being compiled for +# from CMAKE_OSX_SYSROOT. Should be ../../ from SDK specified in +# CMAKE_OSX_SYSROOT. There does not appear to be a direct way to obtain +# this information from xcrun or xcodebuild. +if (NOT DEFINED CMAKE_DEVELOPER_ROOT AND NOT CMAKE_GENERATOR MATCHES "Xcode") + get_filename_component(PLATFORM_SDK_DIR ${CMAKE_OSX_SYSROOT_INT} PATH) + get_filename_component(CMAKE_DEVELOPER_ROOT ${PLATFORM_SDK_DIR} PATH) + if (NOT EXISTS "${CMAKE_DEVELOPER_ROOT}") + message(FATAL_ERROR "Invalid CMAKE_DEVELOPER_ROOT: ${CMAKE_DEVELOPER_ROOT} does not exist.") + endif() +endif() + +# Find the C & C++ compilers for the specified SDK. +if(DEFINED CMAKE_C_COMPILER) + # Environment variables are always preserved. + set(ENV{_CMAKE_C_COMPILER} "${CMAKE_C_COMPILER}") +elseif(DEFINED ENV{_CMAKE_C_COMPILER}) + set(CMAKE_C_COMPILER "$ENV{_CMAKE_C_COMPILER}") + set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) +elseif(NOT DEFINED CMAKE_C_COMPILER) + execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find clang + OUTPUT_VARIABLE CMAKE_C_COMPILER + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) +endif() +if(DEFINED CMAKE_CXX_COMPILER) + # Environment variables are always preserved. + set(ENV{_CMAKE_CXX_COMPILER} "${CMAKE_CXX_COMPILER}") +elseif(DEFINED ENV{_CMAKE_CXX_COMPILER}) + set(CMAKE_CXX_COMPILER "$ENV{_CMAKE_CXX_COMPILER}") +elseif(NOT DEFINED CMAKE_CXX_COMPILER) + execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find clang++ + OUTPUT_VARIABLE CMAKE_CXX_COMPILER + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() +# Find (Apple's) libtool. +if(DEFINED BUILD_LIBTOOL) + # Environment variables are always preserved. + set(ENV{_BUILD_LIBTOOL} "${BUILD_LIBTOOL}") +elseif(DEFINED ENV{_BUILD_LIBTOOL}) + set(BUILD_LIBTOOL "$ENV{_BUILD_LIBTOOL}") +elseif(NOT DEFINED BUILD_LIBTOOL) + execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find libtool + OUTPUT_VARIABLE BUILD_LIBTOOL + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() +# Find the toolchain's provided install_name_tool if none is found on the host +if(DEFINED CMAKE_INSTALL_NAME_TOOL) + # Environment variables are always preserved. + set(ENV{_CMAKE_INSTALL_NAME_TOOL} "${CMAKE_INSTALL_NAME_TOOL}") +elseif(DEFINED ENV{_CMAKE_INSTALL_NAME_TOOL}) + set(CMAKE_INSTALL_NAME_TOOL "$ENV{_CMAKE_INSTALL_NAME_TOOL}") +elseif(NOT DEFINED CMAKE_INSTALL_NAME_TOOL) + execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find install_name_tool + OUTPUT_VARIABLE CMAKE_INSTALL_NAME_TOOL_INT + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + set(CMAKE_INSTALL_NAME_TOOL ${CMAKE_INSTALL_NAME_TOOL_INT} CACHE INTERNAL "") +endif() + +# Configure libtool to be used instead of ar + ranlib to build static libraries. +# This is required on Xcode 7+, but should also work on previous versions of +# Xcode. +get_property(languages GLOBAL PROPERTY ENABLED_LANGUAGES) +foreach(lang ${languages}) + set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "${BUILD_LIBTOOL} -static -o " CACHE INTERNAL "") +endforeach() + +# CMake 3.14+ support building for iOS, watchOS, and tvOS out of the box. +if(MODERN_CMAKE) + if(SDK_NAME MATCHES "iphone") + set(CMAKE_SYSTEM_NAME iOS) + elseif(SDK_NAME MATCHES "xros") + set(CMAKE_SYSTEM_NAME visionOS) + elseif(SDK_NAME MATCHES "xrsimulator") + set(CMAKE_SYSTEM_NAME visionOS) + elseif(SDK_NAME MATCHES "macosx") + set(CMAKE_SYSTEM_NAME Darwin) + elseif(SDK_NAME MATCHES "appletv") + set(CMAKE_SYSTEM_NAME tvOS) + elseif(SDK_NAME MATCHES "watch") + set(CMAKE_SYSTEM_NAME watchOS) + endif() + # Provide flags for a combined FAT library build on newer CMake versions + if(PLATFORM_INT MATCHES ".*COMBINED") + set(CMAKE_IOS_INSTALL_COMBINED YES) + if(CMAKE_GENERATOR MATCHES "Xcode") + # Set the SDKROOT Xcode properties to a Xcode-friendly value (the SDK_NAME, E.g, iphoneos) + # This way, Xcode will automatically switch between the simulator and device SDK when building. + set(CMAKE_XCODE_ATTRIBUTE_SDKROOT "${SDK_NAME}") + # Force to not build just one ARCH, but all! + set(CMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH "NO") + endif() + endif() +elseif(NOT DEFINED CMAKE_SYSTEM_NAME AND ${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.10") + # Legacy code path prior to CMake 3.14 or fallback if no CMAKE_SYSTEM_NAME specified + set(CMAKE_SYSTEM_NAME iOS) +elseif(NOT DEFINED CMAKE_SYSTEM_NAME) + # Legacy code path before CMake 3.14 or fallback if no CMAKE_SYSTEM_NAME specified + set(CMAKE_SYSTEM_NAME Darwin) +endif() +# Standard settings. +set(CMAKE_SYSTEM_VERSION ${SDK_VERSION} CACHE INTERNAL "") +set(UNIX ON CACHE BOOL "") +set(APPLE ON CACHE BOOL "") +if(PLATFORM STREQUAL "MAC" OR PLATFORM STREQUAL "MAC_ARM64" OR PLATFORM STREQUAL "MAC_UNIVERSAL") + set(IOS OFF CACHE BOOL "") + set(MACOS ON CACHE BOOL "") +elseif(PLATFORM STREQUAL "MAC_CATALYST" OR PLATFORM STREQUAL "MAC_CATALYST_ARM64" OR PLATFORM STREQUAL "MAC_CATALYST_UNIVERSAL") + set(IOS ON CACHE BOOL "") + set(MACOS ON CACHE BOOL "") +elseif(PLATFORM STREQUAL "VISIONOS" OR PLATFORM STREQUAL "SIMULATOR_VISIONOS" OR PLATFORM STREQUAL "VISIONOSCOMBINED") + set(IOS OFF CACHE BOOL "") + set(VISIONOS ON CACHE BOOL "") +else() + set(IOS ON CACHE BOOL "") +endif() +# Set the architectures for which to build. +set(CMAKE_OSX_ARCHITECTURES ${ARCHS} CACHE INTERNAL "") +# Change the type of target generated for try_compile() so it'll work when cross-compiling, weak compiler checks +if(NOT ENABLE_STRICT_TRY_COMPILE_INT) + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) +endif() +# All iOS/Darwin specific settings - some may be redundant. +if (NOT DEFINED CMAKE_MACOSX_BUNDLE) + set(CMAKE_MACOSX_BUNDLE YES) +endif() +set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO") +set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO") +set(CMAKE_SHARED_LIBRARY_PREFIX "lib") +set(CMAKE_SHARED_LIBRARY_SUFFIX ".dylib") +set(CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES ".tbd" ".so") +set(CMAKE_SHARED_MODULE_PREFIX "lib") +set(CMAKE_SHARED_MODULE_SUFFIX ".so") +set(CMAKE_C_COMPILER_ABI ELF) +set(CMAKE_CXX_COMPILER_ABI ELF) +set(CMAKE_C_HAS_ISYSROOT 1) +set(CMAKE_CXX_HAS_ISYSROOT 1) +set(CMAKE_MODULE_EXISTS 1) +set(CMAKE_DL_LIBS "") +set(CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ") +set(CMAKE_C_OSX_CURRENT_VERSION_FLAG "-current_version ") +set(CMAKE_CXX_OSX_COMPATIBILITY_VERSION_FLAG "${CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG}") +set(CMAKE_CXX_OSX_CURRENT_VERSION_FLAG "${CMAKE_C_OSX_CURRENT_VERSION_FLAG}") + +if(ARCHS MATCHES "((^|;|, )(arm64|arm64e|x86_64))+") + set(CMAKE_C_SIZEOF_DATA_PTR 8) + set(CMAKE_CXX_SIZEOF_DATA_PTR 8) + if(ARCHS MATCHES "((^|;|, )(arm64|arm64e))+") + set(CMAKE_SYSTEM_PROCESSOR "aarch64") + else() + set(CMAKE_SYSTEM_PROCESSOR "x86_64") + endif() +else() + set(CMAKE_C_SIZEOF_DATA_PTR 4) + set(CMAKE_CXX_SIZEOF_DATA_PTR 4) + set(CMAKE_SYSTEM_PROCESSOR "arm") +endif() + +# Note that only Xcode 7+ supports the newer more specific: +# -m${SDK_NAME}-version-min flags, older versions of Xcode use: +# -m(ios/ios-simulator)-version-min instead. +if(${CMAKE_VERSION} VERSION_LESS "3.11") + if(PLATFORM_INT STREQUAL "OS" OR PLATFORM_INT STREQUAL "OS64") + if(XCODE_VERSION_INT VERSION_LESS 7.0) + set(SDK_NAME_VERSION_FLAGS + "-mios-version-min=${DEPLOYMENT_TARGET}") + else() + # Xcode 7.0+ uses flags we can build directly from SDK_NAME. + set(SDK_NAME_VERSION_FLAGS + "-m${SDK_NAME}-version-min=${DEPLOYMENT_TARGET}") + endif() + elseif(PLATFORM_INT STREQUAL "TVOS") + set(SDK_NAME_VERSION_FLAGS + "-mtvos-version-min=${DEPLOYMENT_TARGET}") + elseif(PLATFORM_INT STREQUAL "SIMULATOR_TVOS") + set(SDK_NAME_VERSION_FLAGS + "-mtvos-simulator-version-min=${DEPLOYMENT_TARGET}") +elseif(PLATFORM_INT STREQUAL "SIMULATORARM64_TVOS") + set(SDK_NAME_VERSION_FLAGS + "-mtvos-simulator-version-min=${DEPLOYMENT_TARGET}") + elseif(PLATFORM_INT STREQUAL "WATCHOS") + set(SDK_NAME_VERSION_FLAGS + "-mwatchos-version-min=${DEPLOYMENT_TARGET}") + elseif(PLATFORM_INT STREQUAL "SIMULATOR_WATCHOS") + set(SDK_NAME_VERSION_FLAGS + "-mwatchos-simulator-version-min=${DEPLOYMENT_TARGET}") + elseif(PLATFORM_INT STREQUAL "SIMULATORARM64_WATCHOS") + set(SDK_NAME_VERSION_FLAGS + "-mwatchos-simulator-version-min=${DEPLOYMENT_TARGET}") + elseif(PLATFORM_INT STREQUAL "MAC") + set(SDK_NAME_VERSION_FLAGS + "-mmacosx-version-min=${DEPLOYMENT_TARGET}") + else() + # SIMULATOR or SIMULATOR64 both use -mios-simulator-version-min. + set(SDK_NAME_VERSION_FLAGS + "-mios-simulator-version-min=${DEPLOYMENT_TARGET}") + endif() +elseif(NOT PLATFORM_INT MATCHES "^MAC_CATALYST") + # Newer versions of CMake sets the version min flags correctly, skip this for Mac Catalyst targets + set(CMAKE_OSX_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET} CACHE INTERNAL "Minimum OS X deployment version") +endif() + +if(DEFINED APPLE_TARGET_TRIPLE_INT) + set(APPLE_TARGET_TRIPLE ${APPLE_TARGET_TRIPLE_INT} CACHE INTERNAL "") + set(CMAKE_C_COMPILER_TARGET ${APPLE_TARGET_TRIPLE}) + set(CMAKE_CXX_COMPILER_TARGET ${APPLE_TARGET_TRIPLE}) + set(CMAKE_ASM_COMPILER_TARGET ${APPLE_TARGET_TRIPLE}) +endif() + +if(PLATFORM_INT MATCHES "^MAC_CATALYST") + set(C_TARGET_FLAGS "-isystem ${CMAKE_OSX_SYSROOT_INT}/System/iOSSupport/usr/include -iframework ${CMAKE_OSX_SYSROOT_INT}/System/iOSSupport/System/Library/Frameworks") +endif() + +if(ENABLE_BITCODE_INT) + set(BITCODE "-fembed-bitcode") + set(CMAKE_XCODE_ATTRIBUTE_BITCODE_GENERATION_MODE "bitcode") + set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "YES") +else() + set(BITCODE "") + set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "NO") +endif() + +if(ENABLE_ARC_INT) + set(FOBJC_ARC "-fobjc-arc") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "YES") +else() + set(FOBJC_ARC "-fno-objc-arc") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "NO") +endif() + +if(NAMED_LANGUAGE_SUPPORT_INT) + set(OBJC_VARS "-fobjc-abi-version=2 -DOBJC_OLD_DISPATCH_PROTOTYPES=0") + set(OBJC_LEGACY_VARS "") +else() + set(OBJC_VARS "") + set(OBJC_LEGACY_VARS "-fobjc-abi-version=2 -DOBJC_OLD_DISPATCH_PROTOTYPES=0") +endif() + +if(NOT ENABLE_VISIBILITY_INT) + foreach(lang ${languages}) + set(CMAKE_${lang}_VISIBILITY_PRESET "hidden" CACHE INTERNAL "") + endforeach() + set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN "YES") + set(VISIBILITY "-fvisibility=hidden -fvisibility-inlines-hidden") +else() + foreach(lang ${languages}) + set(CMAKE_${lang}_VISIBILITY_PRESET "default" CACHE INTERNAL "") + endforeach() + set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN "NO") + set(VISIBILITY "-fvisibility=default") +endif() + +if(DEFINED APPLE_TARGET_TRIPLE) + set(APPLE_TARGET_TRIPLE_FLAG "-target ${APPLE_TARGET_TRIPLE}") +endif() + +#Check if Xcode generator is used since that will handle these flags automagically +if(CMAKE_GENERATOR MATCHES "Xcode") + message(STATUS "Not setting any manual command-line buildflags, since Xcode is selected as the generator. Modifying the Xcode build-settings directly instead.") +else() + set(CMAKE_C_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${OBJC_LEGACY_VARS} ${BITCODE} ${VISIBILITY} ${CMAKE_C_FLAGS}" CACHE INTERNAL + "Flags used by the compiler during all C build types.") + set(CMAKE_C_FLAGS_DEBUG "-O0 -g ${CMAKE_C_FLAGS_DEBUG}") + set(CMAKE_C_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_C_FLAGS_MINSIZEREL}") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_C_FLAGS_RELWITHDEBINFO}") + set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_C_FLAGS_RELEASE}") + set(CMAKE_CXX_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${OBJC_LEGACY_VARS} ${BITCODE} ${VISIBILITY} ${CMAKE_CXX_FLAGS}" CACHE INTERNAL + "Flags used by the compiler during all CXX build types.") + set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g ${CMAKE_CXX_FLAGS_DEBUG}") + set(CMAKE_CXX_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_CXX_FLAGS_MINSIZEREL}") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") + set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_CXX_FLAGS_RELEASE}") + if(NAMED_LANGUAGE_SUPPORT_INT) + set(CMAKE_OBJC_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} ${FOBJC_ARC} ${OBJC_VARS} ${CMAKE_OBJC_FLAGS}" CACHE INTERNAL + "Flags used by the compiler during all OBJC build types.") + set(CMAKE_OBJC_FLAGS_DEBUG "-O0 -g ${CMAKE_OBJC_FLAGS_DEBUG}") + set(CMAKE_OBJC_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_OBJC_FLAGS_MINSIZEREL}") + set(CMAKE_OBJC_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_OBJC_FLAGS_RELWITHDEBINFO}") + set(CMAKE_OBJC_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_OBJC_FLAGS_RELEASE}") + set(CMAKE_OBJCXX_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} ${FOBJC_ARC} ${OBJC_VARS} ${CMAKE_OBJCXX_FLAGS}" CACHE INTERNAL + "Flags used by the compiler during all OBJCXX build types.") + set(CMAKE_OBJCXX_FLAGS_DEBUG "-O0 -g ${CMAKE_OBJCXX_FLAGS_DEBUG}") + set(CMAKE_OBJCXX_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_OBJCXX_FLAGS_MINSIZEREL}") + set(CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO}") + set(CMAKE_OBJCXX_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_OBJCXX_FLAGS_RELEASE}") + endif() + set(CMAKE_C_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}" CACHE INTERNAL + "Flags used by the compiler for all C link types.") + set(CMAKE_CXX_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}" CACHE INTERNAL + "Flags used by the compiler for all CXX link types.") + if(NAMED_LANGUAGE_SUPPORT_INT) + set(CMAKE_OBJC_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_OBJC_LINK_FLAGS}" CACHE INTERNAL + "Flags used by the compiler for all OBJC link types.") + set(CMAKE_OBJCXX_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_OBJCXX_LINK_FLAGS}" CACHE INTERNAL + "Flags used by the compiler for all OBJCXX link types.") + endif() + set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp -arch ${CMAKE_OSX_ARCHITECTURES} ${APPLE_TARGET_TRIPLE_FLAG}" CACHE INTERNAL + "Flags used by the compiler for all ASM build types.") +endif() + +## Print status messages to inform of the current state +message(STATUS "Configuring ${SDK_NAME} build for platform: ${PLATFORM_INT}, architecture(s): ${ARCHS}") +message(STATUS "Using SDK: ${CMAKE_OSX_SYSROOT_INT}") +message(STATUS "Using C compiler: ${CMAKE_C_COMPILER}") +message(STATUS "Using CXX compiler: ${CMAKE_CXX_COMPILER}") +message(STATUS "Using libtool: ${BUILD_LIBTOOL}") +message(STATUS "Using install name tool: ${CMAKE_INSTALL_NAME_TOOL}") +if(DEFINED APPLE_TARGET_TRIPLE) + message(STATUS "Autoconf target triple: ${APPLE_TARGET_TRIPLE}") +endif() +message(STATUS "Using minimum deployment version: ${DEPLOYMENT_TARGET}" + " (SDK version: ${SDK_VERSION})") +if(MODERN_CMAKE) + message(STATUS "Merging integrated CMake 3.14+ iOS,tvOS,watchOS,macOS toolchain(s) with this toolchain!") + if(PLATFORM_INT MATCHES ".*COMBINED") + message(STATUS "Will combine built (static) artifacts into FAT lib...") + endif() +endif() +if(CMAKE_GENERATOR MATCHES "Xcode") + message(STATUS "Using Xcode version: ${XCODE_VERSION_INT}") +endif() +message(STATUS "CMake version: ${CMAKE_VERSION}") +if(DEFINED SDK_NAME_VERSION_FLAGS) + message(STATUS "Using version flags: ${SDK_NAME_VERSION_FLAGS}") +endif() +message(STATUS "Using a data_ptr size of: ${CMAKE_CXX_SIZEOF_DATA_PTR}") +if(ENABLE_BITCODE_INT) + message(STATUS "Bitcode: Enabled") +else() + message(STATUS "Bitcode: Disabled") +endif() + +if(ENABLE_ARC_INT) + message(STATUS "ARC: Enabled") +else() + message(STATUS "ARC: Disabled") +endif() + +if(ENABLE_VISIBILITY_INT) + message(STATUS "Hiding symbols: Disabled") +else() + message(STATUS "Hiding symbols: Enabled") +endif() + +# Set global properties +set_property(GLOBAL PROPERTY PLATFORM "${PLATFORM}") +set_property(GLOBAL PROPERTY APPLE_TARGET_TRIPLE "${APPLE_TARGET_TRIPLE_INT}") +set_property(GLOBAL PROPERTY SDK_VERSION "${SDK_VERSION}") +set_property(GLOBAL PROPERTY XCODE_VERSION "${XCODE_VERSION_INT}") +set_property(GLOBAL PROPERTY OSX_ARCHITECTURES "${CMAKE_OSX_ARCHITECTURES}") + +# Export configurable variables for the try_compile() command. +set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES + PLATFORM + XCODE_VERSION_INT + SDK_VERSION + NAMED_LANGUAGE_SUPPORT + DEPLOYMENT_TARGET + CMAKE_DEVELOPER_ROOT + CMAKE_OSX_SYSROOT_INT + ENABLE_BITCODE + ENABLE_ARC + CMAKE_ASM_COMPILER + CMAKE_C_COMPILER + CMAKE_C_COMPILER_TARGET + CMAKE_CXX_COMPILER + CMAKE_CXX_COMPILER_TARGET + BUILD_LIBTOOL + CMAKE_INSTALL_NAME_TOOL + CMAKE_C_FLAGS + CMAKE_C_DEBUG + CMAKE_C_MINSIZEREL + CMAKE_C_RELWITHDEBINFO + CMAKE_C_RELEASE + CMAKE_CXX_FLAGS + CMAKE_CXX_FLAGS_DEBUG + CMAKE_CXX_FLAGS_MINSIZEREL + CMAKE_CXX_FLAGS_RELWITHDEBINFO + CMAKE_CXX_FLAGS_RELEASE + CMAKE_C_LINK_FLAGS + CMAKE_CXX_LINK_FLAGS + CMAKE_ASM_FLAGS +) + +if(NAMED_LANGUAGE_SUPPORT_INT) + list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES + CMAKE_OBJC_FLAGS + CMAKE_OBJC_DEBUG + CMAKE_OBJC_MINSIZEREL + CMAKE_OBJC_RELWITHDEBINFO + CMAKE_OBJC_RELEASE + CMAKE_OBJCXX_FLAGS + CMAKE_OBJCXX_DEBUG + CMAKE_OBJCXX_MINSIZEREL + CMAKE_OBJCXX_RELWITHDEBINFO + CMAKE_OBJCXX_RELEASE + CMAKE_OBJC_LINK_FLAGS + CMAKE_OBJCXX_LINK_FLAGS + ) +endif() + +set(CMAKE_PLATFORM_HAS_INSTALLNAME 1) +set(CMAKE_SHARED_LINKER_FLAGS "-rpath @executable_path/Frameworks -rpath @loader_path/Frameworks") +set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-dynamiclib -Wl,-headerpad_max_install_names") +set(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-bundle -Wl,-headerpad_max_install_names") +set(CMAKE_SHARED_MODULE_LOADER_C_FLAG "-Wl,-bundle_loader,") +set(CMAKE_SHARED_MODULE_LOADER_CXX_FLAG "-Wl,-bundle_loader,") +set(CMAKE_FIND_LIBRARY_SUFFIXES ".tbd" ".dylib" ".so" ".a") +set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-install_name") + +# Set the find root to the SDK developer roots. +# Note: CMAKE_FIND_ROOT_PATH is only useful when cross-compiling. Thus, do not set on macOS builds. +if(NOT PLATFORM_INT MATCHES "^MAC.*$") + list(APPEND CMAKE_FIND_ROOT_PATH "${CMAKE_OSX_SYSROOT_INT}" CACHE INTERNAL "") + set(CMAKE_IGNORE_PATH "/System/Library/Frameworks;/usr/local/lib;/opt/homebrew" CACHE INTERNAL "") +endif() + +# Default to searching for frameworks first. +IF(NOT DEFINED CMAKE_FIND_FRAMEWORK) + set(CMAKE_FIND_FRAMEWORK FIRST) +ENDIF(NOT DEFINED CMAKE_FIND_FRAMEWORK) + +# Set up the default search directories for frameworks. +if(PLATFORM_INT MATCHES "^MAC_CATALYST") + set(CMAKE_FRAMEWORK_PATH + ${CMAKE_DEVELOPER_ROOT}/Library/PrivateFrameworks + ${CMAKE_OSX_SYSROOT_INT}/System/Library/Frameworks + ${CMAKE_OSX_SYSROOT_INT}/System/iOSSupport/System/Library/Frameworks + ${CMAKE_FRAMEWORK_PATH} CACHE INTERNAL "") +else() + set(CMAKE_FRAMEWORK_PATH + ${CMAKE_DEVELOPER_ROOT}/Library/PrivateFrameworks + ${CMAKE_OSX_SYSROOT_INT}/System/Library/Frameworks + ${CMAKE_FRAMEWORK_PATH} CACHE INTERNAL "") +endif() + +# By default, search both the specified iOS SDK and the remainder of the host filesystem. +if(NOT CMAKE_FIND_ROOT_PATH_MODE_PROGRAM) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH CACHE INTERNAL "") +endif() +if(NOT CMAKE_FIND_ROOT_PATH_MODE_LIBRARY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH CACHE INTERNAL "") +endif() +if(NOT CMAKE_FIND_ROOT_PATH_MODE_INCLUDE) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH CACHE INTERNAL "") +endif() +if(NOT CMAKE_FIND_ROOT_PATH_MODE_PACKAGE) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH CACHE INTERNAL "") +endif() + +# +# Some helper-macros below to simplify and beautify the CMakeFile +# + +# This little macro lets you set any Xcode specific property. +macro(set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE XCODE_RELVERSION) + set(XCODE_RELVERSION_I "${XCODE_RELVERSION}") + if(XCODE_RELVERSION_I STREQUAL "All") + set_property(TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} "${XCODE_VALUE}") + else() + set_property(TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY}[variant=${XCODE_RELVERSION_I}] "${XCODE_VALUE}") + endif() +endmacro(set_xcode_property) + +# This macro lets you find executable programs on the host system. +macro(find_host_package) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE NEVER) + set(_TOOLCHAIN_IOS ${IOS}) + set(IOS OFF) + find_package(${ARGN}) + set(IOS ${_TOOLCHAIN_IOS}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH) +endmacro(find_host_package) +# gersemi: on From 466a7431123ac20ce2bfe474d64d0a85c50d3c43 Mon Sep 17 00:00:00 2001 From: Tom Date: Mon, 24 Mar 2025 19:42:04 +0000 Subject: [PATCH 15/41] Added initialiser list support to TypedDictionary (cherry picked from commit 335b4900618f7cabbe5c18bcb13274b1a98faf60) --- include/godot_cpp/classes/ref.hpp | 4 + include/godot_cpp/templates/pair.hpp | 2 + .../godot_cpp/variant/typed_dictionary.hpp | 117 +++++++++++------- 3 files changed, 79 insertions(+), 44 deletions(-) diff --git a/include/godot_cpp/classes/ref.hpp b/include/godot_cpp/classes/ref.hpp index 8a5a9aa9f..541c5ce31 100644 --- a/include/godot_cpp/classes/ref.hpp +++ b/include/godot_cpp/classes/ref.hpp @@ -70,6 +70,10 @@ class Ref { } public: + static _FORCE_INLINE_ String get_class_static() { + return T::get_class_static(); + } + _FORCE_INLINE_ bool operator==(const T *p_ptr) const { return reference == p_ptr; } diff --git a/include/godot_cpp/templates/pair.hpp b/include/godot_cpp/templates/pair.hpp index 423a7099e..15c7c3567 100644 --- a/include/godot_cpp/templates/pair.hpp +++ b/include/godot_cpp/templates/pair.hpp @@ -30,6 +30,8 @@ #pragma once +#include + namespace godot { template diff --git a/include/godot_cpp/variant/typed_dictionary.hpp b/include/godot_cpp/variant/typed_dictionary.hpp index ff78c5164..122655a47 100644 --- a/include/godot_cpp/variant/typed_dictionary.hpp +++ b/include/godot_cpp/variant/typed_dictionary.hpp @@ -31,6 +31,7 @@ #pragma once #include +#include #include #include @@ -57,54 +58,75 @@ class TypedDictionary : public Dictionary { _FORCE_INLINE_ TypedDictionary() { set_typed(Variant::OBJECT, K::get_class_static(), Variant(), Variant::OBJECT, V::get_class_static(), Variant()); } + _FORCE_INLINE_ TypedDictionary(std::initializer_list> p_init) : + Dictionary() { + set_typed(Variant::OBJECT, K::get_class_static(), Variant(), Variant::OBJECT, V::get_class_static(), Variant()); + for (const KeyValue &E : p_init) { + operator[](E.key) = E.value; + } + } }; //specialization for the rest of variant types -#define MAKE_TYPED_DICTIONARY_WITH_OBJECT(m_type, m_variant_type) \ - template \ - class TypedDictionary : public Dictionary { \ - public: \ - _FORCE_INLINE_ void operator=(const Dictionary &p_dictionary) { \ - ERR_FAIL_COND_MSG(!is_same_typed(p_dictionary), "Cannot assign an dictionary with a different element type."); \ - Dictionary::operator=(p_dictionary); \ - } \ - _FORCE_INLINE_ TypedDictionary(const Variant &p_variant) : \ - TypedDictionary(Dictionary(p_variant)) { \ - } \ - _FORCE_INLINE_ TypedDictionary(const Dictionary &p_dictionary) { \ - set_typed(Variant::OBJECT, T::get_class_static(), Variant(), m_variant_type, StringName(), Variant()); \ - if (is_same_typed(p_dictionary)) { \ - Dictionary::operator=(p_dictionary); \ - } else { \ - assign(p_dictionary); \ - } \ - } \ - _FORCE_INLINE_ TypedDictionary() { \ - set_typed(Variant::OBJECT, T::get_class_static(), Variant(), m_variant_type, StringName(), Variant()); \ - } \ - }; \ - template \ - class TypedDictionary : public Dictionary { \ - public: \ - _FORCE_INLINE_ void operator=(const Dictionary &p_dictionary) { \ - ERR_FAIL_COND_MSG(!is_same_typed(p_dictionary), "Cannot assign an dictionary with a different element type."); \ - Dictionary::operator=(p_dictionary); \ - } \ - _FORCE_INLINE_ TypedDictionary(const Variant &p_variant) : \ - TypedDictionary(Dictionary(p_variant)) { \ - } \ - _FORCE_INLINE_ TypedDictionary(const Dictionary &p_dictionary) { \ - set_typed(m_variant_type, StringName(), Variant(), Variant::OBJECT, T::get_class_static(), Variant()); \ - if (is_same_typed(p_dictionary)) { \ - Dictionary::operator=(p_dictionary); \ - } else { \ - assign(p_dictionary); \ - } \ - } \ - _FORCE_INLINE_ TypedDictionary() { \ - set_typed(m_variant_type, StringName(), Variant(), Variant::OBJECT, T::get_class_static(), Variant()); \ - } \ +#define MAKE_TYPED_DICTIONARY_WITH_OBJECT(m_type, m_variant_type) \ + template \ + class TypedDictionary : public Dictionary { \ + public: \ + _FORCE_INLINE_ void operator=(const Dictionary &p_dictionary) { \ + ERR_FAIL_COND_MSG(!is_same_typed(p_dictionary), "Cannot assign an dictionary with a different element type."); \ + Dictionary::operator=(p_dictionary); \ + } \ + _FORCE_INLINE_ TypedDictionary(const Variant &p_variant) : \ + TypedDictionary(Dictionary(p_variant)) { \ + } \ + _FORCE_INLINE_ TypedDictionary(const Dictionary &p_dictionary) { \ + set_typed(Variant::OBJECT, T::get_class_static(), Variant(), m_variant_type, StringName(), Variant()); \ + if (is_same_typed(p_dictionary)) { \ + Dictionary::operator=(p_dictionary); \ + } else { \ + assign(p_dictionary); \ + } \ + } \ + _FORCE_INLINE_ TypedDictionary() { \ + set_typed(Variant::OBJECT, T::get_class_static(), Variant(), m_variant_type, StringName(), Variant()); \ + } \ + _FORCE_INLINE_ TypedDictionary(std::initializer_list> p_init) : \ + Dictionary() { \ + set_typed(Variant::OBJECT, T::get_class_static(), Variant(), m_variant_type, StringName(), Variant()); \ + for (const KeyValue &E : p_init) { \ + operator[](E.key) = E.value; \ + } \ + } \ + }; \ + template \ + class TypedDictionary : public Dictionary { \ + public: \ + _FORCE_INLINE_ void operator=(const Dictionary &p_dictionary) { \ + ERR_FAIL_COND_MSG(!is_same_typed(p_dictionary), "Cannot assign an dictionary with a different element type."); \ + Dictionary::operator=(p_dictionary); \ + } \ + _FORCE_INLINE_ TypedDictionary(const Variant &p_variant) : \ + TypedDictionary(Dictionary(p_variant)) { \ + } \ + _FORCE_INLINE_ TypedDictionary(const Dictionary &p_dictionary) { \ + set_typed(m_variant_type, StringName(), Variant(), Variant::OBJECT, T::get_class_static(), Variant()); \ + if (is_same_typed(p_dictionary)) { \ + Dictionary::operator=(p_dictionary); \ + } else { \ + assign(p_dictionary); \ + } \ + } \ + _FORCE_INLINE_ TypedDictionary() { \ + set_typed(m_variant_type, StringName(), Variant(), Variant::OBJECT, T::get_class_static(), Variant()); \ + } \ + _FORCE_INLINE_ TypedDictionary(std::initializer_list> p_init) : \ + Dictionary() { \ + set_typed(m_variant_type, StringName(), Variant(), Variant::OBJECT, std::remove_pointer::type::get_class_static(), Variant()); \ + for (const KeyValue &E : p_init) { \ + operator[](E.key) = E.value; \ + } \ + } \ }; #define MAKE_TYPED_DICTIONARY_EXPANDED(m_type_key, m_variant_type_key, m_type_value, m_variant_type_value) \ @@ -129,6 +151,13 @@ class TypedDictionary : public Dictionary { _FORCE_INLINE_ TypedDictionary() { \ set_typed(m_variant_type_key, StringName(), Variant(), m_variant_type_value, StringName(), Variant()); \ } \ + _FORCE_INLINE_ TypedDictionary(std::initializer_list> p_init) : \ + Dictionary() { \ + set_typed(m_variant_type_key, StringName(), Variant(), m_variant_type_value, StringName(), Variant()); \ + for (const KeyValue &E : p_init) { \ + operator[](E.key) = E.value; \ + } \ + } \ }; #define MAKE_TYPED_DICTIONARY_NIL(m_type, m_variant_type) \ From 483499c14c289495e4473a6188531bd3ec1b14ba Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Thu, 3 Apr 2025 16:40:19 +0200 Subject: [PATCH 16/41] Update test project to Godot 4.4 (cherry picked from commit 552a74c96e8258328d862c7b77890a247567a6bc) --- test/project/example.gd.uid | 1 + test/project/example.gdextension.uid | 1 + test/project/main.gd.uid | 1 + test/project/main.tscn | 4 ++-- test/project/project.godot | 2 +- test/project/test_base.gd.uid | 1 + 6 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 test/project/example.gd.uid create mode 100644 test/project/example.gdextension.uid create mode 100644 test/project/main.gd.uid create mode 100644 test/project/test_base.gd.uid diff --git a/test/project/example.gd.uid b/test/project/example.gd.uid new file mode 100644 index 000000000..b1c36967a --- /dev/null +++ b/test/project/example.gd.uid @@ -0,0 +1 @@ +uid://1htvqeulgew6 diff --git a/test/project/example.gdextension.uid b/test/project/example.gdextension.uid new file mode 100644 index 000000000..fa1a310e2 --- /dev/null +++ b/test/project/example.gdextension.uid @@ -0,0 +1 @@ +uid://dhm7q8lygqyol diff --git a/test/project/main.gd.uid b/test/project/main.gd.uid new file mode 100644 index 000000000..1266fc06f --- /dev/null +++ b/test/project/main.gd.uid @@ -0,0 +1 @@ +uid://bujp6xsb8pfqk diff --git a/test/project/main.tscn b/test/project/main.tscn index e786025a6..89988fd3b 100644 --- a/test/project/main.tscn +++ b/test/project/main.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=3 format=3 uid="uid://dmx2xuigcpvt4"] -[ext_resource type="Script" path="res://main.gd" id="1_qesh5"] -[ext_resource type="Script" path="res://example.gd" id="2_jju25"] +[ext_resource type="Script" uid="uid://bujp6xsb8pfqk" path="res://main.gd" id="1_qesh5"] +[ext_resource type="Script" uid="uid://1htvqeulgew6" path="res://example.gd" id="2_jju25"] [node name="Node" type="Node"] script = ExtResource("1_qesh5") diff --git a/test/project/project.godot b/test/project/project.godot index df3dd70f7..9b711dd65 100644 --- a/test/project/project.godot +++ b/test/project/project.godot @@ -12,7 +12,7 @@ config_version=5 config/name="GDExtension Test Project" run/main_scene="res://main.tscn" -config/features=PackedStringArray("4.3") +config/features=PackedStringArray("4.4") config/icon="res://icon.png" [native_extensions] diff --git a/test/project/test_base.gd.uid b/test/project/test_base.gd.uid new file mode 100644 index 000000000..15057856a --- /dev/null +++ b/test/project/test_base.gd.uid @@ -0,0 +1 @@ +uid://dwbwwljpx3cp From 2b4512414bcda16eef459530ee83de07f174d63b Mon Sep 17 00:00:00 2001 From: Samuel Nicholas Date: Mon, 7 Apr 2025 08:10:16 +0930 Subject: [PATCH 17/41] Fix compatibility break for CI (cherry picked from commit 38e517b98b537303a153bdefba2c3f750ce289ea) --- .github/actions/setup-godot-cpp/action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/setup-godot-cpp/action.yml b/.github/actions/setup-godot-cpp/action.yml index 008a6b4f0..1be9293c4 100644 --- a/.github/actions/setup-godot-cpp/action.yml +++ b/.github/actions/setup-godot-cpp/action.yml @@ -23,6 +23,7 @@ inputs: default: r23c description: Android NDK version. buildtool: + default: scons description: scons or cmake scons-version: default: 4.4.0 From bdeb1987f614d5b7f7378c8a1866521056a8dca1 Mon Sep 17 00:00:00 2001 From: Marc Gilleron Date: Mon, 14 Apr 2025 23:46:47 +0200 Subject: [PATCH 18/41] Use Math::abs to avoid ambiguity with integer abs (cherry picked from commit 7e6c9c937026f8894b4009ae953e3f8c20e6f570) --- include/godot_cpp/variant/quaternion.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/godot_cpp/variant/quaternion.hpp b/include/godot_cpp/variant/quaternion.hpp index c93fe57e8..d0efa0867 100644 --- a/include/godot_cpp/variant/quaternion.hpp +++ b/include/godot_cpp/variant/quaternion.hpp @@ -149,7 +149,7 @@ struct [[nodiscard]] Quaternion { Vector3 n0 = p_v0.normalized(); Vector3 n1 = p_v1.normalized(); real_t d = n0.dot(n1); - if (abs(d) > ALMOST_ONE) { + if (Math::abs(d) > ALMOST_ONE) { if (d >= 0) { return; // Vectors are same. } From b139e2fb76d7e7d60029d81882200d24acee37b2 Mon Sep 17 00:00:00 2001 From: Tom Date: Thu, 3 Apr 2025 00:45:56 +0100 Subject: [PATCH 19/41] Synced defs.hpp with godot's typedefs.h (cherry picked from commit d634a5f8c49414cea86efa0d8cb25095064d292c) --- include/godot_cpp/core/binder_common.hpp | 1 + include/godot_cpp/core/defs.hpp | 255 +++++++++++++++++++++-- include/godot_cpp/core/math.compat.inc | 51 +++++ include/godot_cpp/core/math.hpp | 180 +--------------- include/godot_cpp/core/math_defs.hpp | 72 +++++++ include/godot_cpp/core/memory.hpp | 6 - include/godot_cpp/variant/plane.hpp | 2 +- include/godot_cpp/variant/vector3.hpp | 2 +- src/variant/plane.cpp | 2 +- tools/godotcpp.py | 2 - 10 files changed, 362 insertions(+), 211 deletions(-) create mode 100644 include/godot_cpp/core/math.compat.inc create mode 100644 include/godot_cpp/core/math_defs.hpp diff --git a/include/godot_cpp/core/binder_common.hpp b/include/godot_cpp/core/binder_common.hpp index 6a8777350..ba99aa38a 100644 --- a/include/godot_cpp/core/binder_common.hpp +++ b/include/godot_cpp/core/binder_common.hpp @@ -32,6 +32,7 @@ #include +#include #include #include diff --git a/include/godot_cpp/core/defs.hpp b/include/godot_cpp/core/defs.hpp index c5115aa9a..9395f2013 100644 --- a/include/godot_cpp/core/defs.hpp +++ b/include/godot_cpp/core/defs.hpp @@ -32,7 +32,7 @@ #include #include -#include +#include namespace godot { @@ -64,15 +64,33 @@ namespace godot { #endif #endif -// Should always inline, except in debug builds because it makes debugging harder. +// Should always inline, except in dev builds because it makes debugging harder, +// or `size_enabled` builds where inlining is actively avoided. #ifndef _FORCE_INLINE_ -#ifdef DISABLE_FORCED_INLINE +#if defined(DEV_ENABLED) || defined(SIZE_EXTRA) #define _FORCE_INLINE_ inline #else #define _FORCE_INLINE_ _ALWAYS_INLINE_ #endif #endif +// Should never inline. +#ifndef _NO_INLINE_ +#if defined(__GNUC__) +#define _NO_INLINE_ __attribute__((noinline)) +#elif defined(_MSC_VER) +#define _NO_INLINE_ __declspec(noinline) +#else +#define _NO_INLINE_ +#endif +#endif + +// In some cases [[nodiscard]] will get false positives, +// we can prevent the warning in specific cases by preceding the call with a cast. +#ifndef _ALLOW_DISCARD_ +#define _ALLOW_DISCARD_ (void) +#endif + // Windows badly defines a lot of stuff we'll never use. Undefine it. #ifdef _WIN32 #undef min // override standard definition @@ -80,14 +98,182 @@ namespace godot { #undef ERROR // override (really stupid) wingdi.h standard definition #undef DELETE // override (another really stupid) winnt.h standard definition #undef MessageBox // override winuser.h standard definition -#undef MIN // override standard definition -#undef MAX // override standard definition -#undef CLAMP // override standard definition #undef Error #undef OK #undef CONNECT_DEFERRED // override from Windows SDK, clashes with Object enum +#undef MemoryBarrier +#undef MONO_FONT +#endif + +// Make room for our constexpr's below by overriding potential system-specific macros. +#undef SIGN +#undef MIN +#undef MAX +#undef CLAMP + +template +constexpr const T SIGN(const T m_v) { + return m_v > 0 ? +1.0f : (m_v < 0 ? -1.0f : 0.0f); +} + +template +constexpr auto MIN(const T m_a, const T2 m_b) { + return m_a < m_b ? m_a : m_b; +} + +template +constexpr auto MAX(const T m_a, const T2 m_b) { + return m_a > m_b ? m_a : m_b; +} + +template +constexpr auto CLAMP(const T m_a, const T2 m_min, const T3 m_max) { + return m_a < m_min ? m_min : (m_a > m_max ? m_max : m_a); +} + +// Generic swap template. +#ifndef SWAP +#define SWAP(m_x, m_y) std::swap((m_x), (m_y)) +#endif // SWAP + +/* Functions to handle powers of 2 and shifting. */ + +// Returns `true` if a positive integer is a power of 2, `false` otherwise. +template +inline bool is_power_of_2(const T x) { + return x && ((x & (x - 1)) == 0); +} + +// Function to find the next power of 2 to an integer. +static _FORCE_INLINE_ unsigned int next_power_of_2(unsigned int x) { + if (x == 0) { + return 0; + } + + --x; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + + return ++x; +} + +// Function to find the previous power of 2 to an integer. +static _FORCE_INLINE_ unsigned int previous_power_of_2(unsigned int x) { + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + return x - (x >> 1); +} + +// Function to find the closest power of 2 to an integer. +static _FORCE_INLINE_ unsigned int closest_power_of_2(unsigned int x) { + unsigned int nx = next_power_of_2(x); + unsigned int px = previous_power_of_2(x); + return (nx - x) > (x - px) ? px : nx; +} + +// Get a shift value from a power of 2. +static inline int get_shift_from_power_of_2(unsigned int p_bits) { + for (unsigned int i = 0; i < 32; i++) { + if (p_bits == (unsigned int)(1 << i)) { + return i; + } + } + + return -1; +} + +template +static _FORCE_INLINE_ T nearest_power_of_2_templated(T x) { + --x; + + // The number of operations on x is the base two logarithm + // of the number of bits in the type. Add three to account + // for sizeof(T) being in bytes. + size_t num = get_shift_from_power_of_2(sizeof(T)) + 3; + + // If the compiler is smart, it unrolls this loop. + // If it's dumb, this is a bit slow. + for (size_t i = 0; i < num; i++) { + x |= x >> (1 << i); + } + + return ++x; +} + +// Function to find the nearest (bigger) power of 2 to an integer. +static inline unsigned int nearest_shift(unsigned int p_number) { + for (int i = 30; i >= 0; i--) { + if (p_number & (1 << i)) { + return i + 1; + } + } + + return 0; +} + +// constexpr function to find the floored log2 of a number +template +constexpr T floor_log2(T x) { + return x < 2 ? x : 1 + floor_log2(x >> 1); +} + +// Get the number of bits needed to represent the number. +// IE, if you pass in 8, you will get 4. +// If you want to know how many bits are needed to store 8 values however, pass in (8 - 1). +template +constexpr T get_num_bits(T x) { + return floor_log2(x); +} + +// Swap 16, 32 and 64 bits value for endianness. +#if defined(__GNUC__) +#define BSWAP16(x) __builtin_bswap16(x) +#define BSWAP32(x) __builtin_bswap32(x) +#define BSWAP64(x) __builtin_bswap64(x) +#elif defined(_MSC_VER) +#define BSWAP16(x) _byteswap_ushort(x) +#define BSWAP32(x) _byteswap_ulong(x) +#define BSWAP64(x) _byteswap_uint64(x) +#else +static inline uint16_t BSWAP16(uint16_t x) { + return (x >> 8) | (x << 8); +} + +static inline uint32_t BSWAP32(uint32_t x) { + return ((x << 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x >> 24)); +} + +static inline uint64_t BSWAP64(uint64_t x) { + x = (x & 0x00000000FFFFFFFF) << 32 | (x & 0xFFFFFFFF00000000) >> 32; + x = (x & 0x0000FFFF0000FFFF) << 16 | (x & 0xFFFF0000FFFF0000) >> 16; + x = (x & 0x00FF00FF00FF00FF) << 8 | (x & 0xFF00FF00FF00FF00) >> 8; + return x; +} #endif +// Generic comparator used in Map, List, etc. +template +struct Comparator { + _ALWAYS_INLINE_ bool operator()(const T &p_a, const T &p_b) const { return (p_a < p_b); } +}; + +// Global lock macro, relies on the static Mutex::_global_mutex. +void _global_lock(); +void _global_unlock(); + +struct _GlobalLock { + _GlobalLock() { _global_lock(); } + ~_GlobalLock() { _global_unlock(); } +}; + +#define GLOBAL_LOCK_FUNCTION _GlobalLock _global_lock_; + #if defined(__GNUC__) #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) @@ -96,22 +282,17 @@ namespace godot { #define unlikely(x) x #endif -#ifdef REAL_T_IS_DOUBLE -typedef double real_t; +#if defined(__GNUC__) +#define _PRINTF_FORMAT_ATTRIBUTE_2_0 __attribute__((format(printf, 2, 0))) +#define _PRINTF_FORMAT_ATTRIBUTE_2_3 __attribute__((format(printf, 2, 3))) #else -typedef float real_t; +#define _PRINTF_FORMAT_ATTRIBUTE_2_0 +#define _PRINTF_FORMAT_ATTRIBUTE_2_3 #endif -// Generic swap template. -#ifndef SWAP -#define SWAP(m_x, m_y) __swap_tmpl((m_x), (m_y)) -template -inline void __swap_tmpl(T &x, T &y) { - T aux = x; - x = y; - y = aux; -} -#endif // SWAP +// This is needed due to a strange OpenGL API that expects a pointer +// type for an argument that is actually an offset. +#define CAST_INT_TO_UCHAR_PTR(ptr) ((uint8_t *)(uintptr_t)(ptr)) // Home-made index sequence trick, so it can be used everywhere without the costly include of std::tuple. // https://stackoverflow.com/questions/15014096/c-index-of-type-during-variadic-template-expansion @@ -124,8 +305,36 @@ struct BuildIndexSequence : BuildIndexSequence {}; template struct BuildIndexSequence<0, Is...> : IndexSequence {}; -} //namespace godot +// Limit the depth of recursive algorithms when dealing with Array/Dictionary +#define MAX_RECURSION 100 + +#ifdef DEBUG_ENABLED +#define DEBUG_METHODS_ENABLED +#endif + +// Macro GD_IS_DEFINED() allows to check if a macro is defined. It needs to be defined to anything (say 1) to work. +#define __GDARG_PLACEHOLDER_1 false, +#define __gd_take_second_arg(__ignored, val, ...) val +#define ____gd_is_defined(arg1_or_junk) __gd_take_second_arg(arg1_or_junk true, false) +#define ___gd_is_defined(val) ____gd_is_defined(__GDARG_PLACEHOLDER_##val) +#define GD_IS_DEFINED(x) ___gd_is_defined(x) -// To maintain compatibility an alias is defined outside the namespace. -// Consider it deprecated. -using real_t = godot::real_t; +// Whether the default value of a type is just all-0 bytes. +// This can most commonly be exploited by using memset for these types instead of loop-construct. +// Trivially constructible types are also zero-constructible. +template +struct is_zero_constructible : std::is_trivially_constructible {}; + +template +struct is_zero_constructible : is_zero_constructible {}; + +template +struct is_zero_constructible : is_zero_constructible {}; + +template +struct is_zero_constructible : is_zero_constructible {}; + +template +inline constexpr bool is_zero_constructible_v = is_zero_constructible::value; + +} //namespace godot diff --git a/include/godot_cpp/core/math.compat.inc b/include/godot_cpp/core/math.compat.inc new file mode 100644 index 000000000..deaab87c3 --- /dev/null +++ b/include/godot_cpp/core/math.compat.inc @@ -0,0 +1,51 @@ +/**************************************************************************/ +/* math.compat.inc */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + + +#ifndef DISABLE_DEPRECATED + +namespace godot { + +#undef ABS + +// Generic ABS function, for math uses please use Math::abs. +template +[[deprecated("Use Math::abs instead")]] +constexpr T ABS(T m_v) { + return m_v < 0 ? -m_v : m_v; +} + +} + +// To maintain compatibility an alias is defined outside the namespace. +// Consider it deprecated. +using real_t = godot::real_t; + +#endif diff --git a/include/godot_cpp/core/math.hpp b/include/godot_cpp/core/math.hpp index 44cc30145..f7ebc0c0e 100644 --- a/include/godot_cpp/core/math.hpp +++ b/include/godot_cpp/core/math.hpp @@ -31,6 +31,7 @@ #pragma once #include +#include #include @@ -38,185 +39,8 @@ namespace godot { -#define Math_SQRT12 0.7071067811865475244008443621048490 -#define Math_SQRT2 1.4142135623730950488016887242 -#define Math_LN2 0.6931471805599453094172321215 -#define Math_PI 3.1415926535897932384626433833 -#define Math_TAU 6.2831853071795864769252867666 -#define Math_E 2.7182818284590452353602874714 -#define Math_INF INFINITY -#define Math_NAN NAN - -// Make room for our constexpr's below by overriding potential system-specific macros. -#undef ABS -#undef SIGN -#undef MIN -#undef MAX -#undef CLAMP - -// Generic ABS function, for math uses please use Math::abs. -template -constexpr T ABS(T m_v) { - return m_v < 0 ? -m_v : m_v; -} - -template -constexpr const T SIGN(const T m_v) { - return m_v == 0 ? 0.0f : (m_v < 0 ? -1.0f : +1.0f); -} - -template -constexpr auto MIN(const T m_a, const T2 m_b) { - return m_a < m_b ? m_a : m_b; -} - -template -constexpr auto MAX(const T m_a, const T2 m_b) { - return m_a > m_b ? m_a : m_b; -} - -template -constexpr auto CLAMP(const T m_a, const T2 m_min, const T3 m_max) { - return m_a < m_min ? m_min : (m_a > m_max ? m_max : m_a); -} - -// Generic swap template. -#ifndef SWAP -#define SWAP(m_x, m_y) __swap_tmpl((m_x), (m_y)) -template -inline void __swap_tmpl(T &x, T &y) { - T aux = x; - x = y; - y = aux; -} -#endif // SWAP - -/* Functions to handle powers of 2 and shifting. */ - -// Function to find the next power of 2 to an integer. -static _FORCE_INLINE_ unsigned int next_power_of_2(unsigned int x) { - if (x == 0) { - return 0; - } - - --x; - x |= x >> 1; - x |= x >> 2; - x |= x >> 4; - x |= x >> 8; - x |= x >> 16; - - return ++x; -} - -// Function to find the previous power of 2 to an integer. -static _FORCE_INLINE_ unsigned int previous_power_of_2(unsigned int x) { - x |= x >> 1; - x |= x >> 2; - x |= x >> 4; - x |= x >> 8; - x |= x >> 16; - return x - (x >> 1); -} - -// Function to find the closest power of 2 to an integer. -static _FORCE_INLINE_ unsigned int closest_power_of_2(unsigned int x) { - unsigned int nx = next_power_of_2(x); - unsigned int px = previous_power_of_2(x); - return (nx - x) > (x - px) ? px : nx; -} - -// Get a shift value from a power of 2. -static inline int get_shift_from_power_of_2(unsigned int p_bits) { - for (unsigned int i = 0; i < 32; i++) { - if (p_bits == (unsigned int)(1 << i)) { - return i; - } - } - - return -1; -} - -template -static _FORCE_INLINE_ T nearest_power_of_2_templated(T x) { - --x; - - // The number of operations on x is the base two logarithm - // of the number of bits in the type. Add three to account - // for sizeof(T) being in bytes. - size_t num = get_shift_from_power_of_2(sizeof(T)) + 3; - - // If the compiler is smart, it unrolls this loop. - // If it's dumb, this is a bit slow. - for (size_t i = 0; i < num; i++) { - x |= x >> (1 << i); - } - - return ++x; -} - -// Function to find the nearest (bigger) power of 2 to an integer. -static inline unsigned int nearest_shift(unsigned int p_number) { - for (int i = 30; i >= 0; i--) { - if (p_number & (1 << i)) { - return i + 1; - } - } - - return 0; -} - -// constexpr function to find the floored log2 of a number -template -constexpr T floor_log2(T x) { - return x < 2 ? x : 1 + floor_log2(x >> 1); -} - -// Get the number of bits needed to represent the number. -// IE, if you pass in 8, you will get 4. -// If you want to know how many bits are needed to store 8 values however, pass in (8 - 1). -template -constexpr T get_num_bits(T x) { - return floor_log2(x); -} - -// Swap 16, 32 and 64 bits value for endianness. -#if defined(__GNUC__) -#define BSWAP16(x) __builtin_bswap16(x) -#define BSWAP32(x) __builtin_bswap32(x) -#define BSWAP64(x) __builtin_bswap64(x) -#else -static inline uint16_t BSWAP16(uint16_t x) { - return (x >> 8) | (x << 8); -} - -static inline uint32_t BSWAP32(uint32_t x) { - return ((x << 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x >> 24)); -} - -static inline uint64_t BSWAP64(uint64_t x) { - x = (x & 0x00000000FFFFFFFF) << 32 | (x & 0xFFFFFFFF00000000) >> 32; - x = (x & 0x0000FFFF0000FFFF) << 16 | (x & 0xFFFF0000FFFF0000) >> 16; - x = (x & 0x00FF00FF00FF00FF) << 8 | (x & 0xFF00FF00FF00FF00) >> 8; - return x; -} -#endif - namespace Math { -// This epsilon should match the one used by Godot for consistency. -// Using `f` when `real_t` is float. -#define CMP_EPSILON 0.00001f -#define CMP_EPSILON2 (CMP_EPSILON * CMP_EPSILON) - -// This epsilon is for values related to a unit size (scalar or vector len). -#ifdef PRECISE_MATH_CHECKS -#define UNIT_EPSILON 0.00001 -#else -// Tolerate some more floating point error normally. -#define UNIT_EPSILON 0.001 -#endif - // Functions reproduced as in Godot's source code `math_funcs.h`. // Some are overloads to automatically support changing real_t into either double or float in the way Godot does. @@ -834,3 +658,5 @@ inline float snap_scalar_separation(float p_offset, float p_step, float p_target } // namespace Math } // namespace godot + +#include "math.compat.inc" diff --git a/include/godot_cpp/core/math_defs.hpp b/include/godot_cpp/core/math_defs.hpp new file mode 100644 index 000000000..73d861489 --- /dev/null +++ b/include/godot_cpp/core/math_defs.hpp @@ -0,0 +1,72 @@ +/**************************************************************************/ +/* math_defs.hpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#pragma once + +namespace godot { + +#define CMP_EPSILON 0.00001 +#define CMP_EPSILON2 (CMP_EPSILON * CMP_EPSILON) + +#define CMP_NORMALIZE_TOLERANCE 0.000001 +#define CMP_POINT_IN_PLANE_EPSILON 0.00001 + +#define Math_SQRT12 0.7071067811865475244008443621048490 +#define Math_SQRT2 1.4142135623730950488016887242 +#define Math_LN2 0.6931471805599453094172321215 +#define Math_TAU 6.2831853071795864769252867666 +#define Math_PI 3.1415926535897932384626433833 +#define Math_E 2.7182818284590452353602874714 + +#ifdef DEBUG_ENABLED +#define MATH_CHECKS +#endif + +//this epsilon is for values related to a unit size (scalar or vector len) +#ifdef PRECISE_MATH_CHECKS +#define UNIT_EPSILON 0.00001 +#else +//tolerate some more floating point error normally +#define UNIT_EPSILON 0.001 +#endif + +#define USEC_TO_SEC(m_usec) ((m_usec) / 1000000.0) + +/** + * The "Real" type is an abstract type used for real numbers, such as 1.5, + * in contrast to integer numbers. Precision can be controlled with the + * presence or absence of the REAL_T_IS_DOUBLE define. + */ +#ifdef REAL_T_IS_DOUBLE +typedef double real_t; +#else +typedef float real_t; +#endif +} // namespace godot diff --git a/include/godot_cpp/core/memory.hpp b/include/godot_cpp/core/memory.hpp index 4905ba897..917ccdede 100644 --- a/include/godot_cpp/core/memory.hpp +++ b/include/godot_cpp/core/memory.hpp @@ -101,12 +101,6 @@ _ALWAYS_INLINE_ T *_post_initialize(T *p_obj) { #define memnew_allocator(m_class, m_allocator) (::godot::_pre_initialize>(), ::godot::_post_initialize(new ("", m_allocator::alloc) m_class)) #define memnew_placement(m_placement, m_class) (::godot::_pre_initialize>(), ::godot::_post_initialize(new ("", m_placement, sizeof(m_class), "") m_class)) -// Generic comparator used in Map, List, etc. -template -struct Comparator { - _ALWAYS_INLINE_ bool operator()(const T &p_a, const T &p_b) const { return (p_a < p_b); } -}; - template void memdelete(T *p_class, typename std::enable_if>::type * = nullptr) { if constexpr (!std::is_trivially_destructible_v) { diff --git a/include/godot_cpp/variant/plane.hpp b/include/godot_cpp/variant/plane.hpp index 97ae7c81d..c7572045b 100644 --- a/include/godot_cpp/variant/plane.hpp +++ b/include/godot_cpp/variant/plane.hpp @@ -102,7 +102,7 @@ real_t Plane::distance_to(const Vector3 &p_point) const { bool Plane::has_point(const Vector3 &p_point, real_t p_tolerance) const { real_t dist = normal.dot(p_point) - d; - dist = ABS(dist); + dist = Math::abs(dist); return (dist <= p_tolerance); } diff --git a/include/godot_cpp/variant/vector3.hpp b/include/godot_cpp/variant/vector3.hpp index 796daeca7..034e6ca29 100644 --- a/include/godot_cpp/variant/vector3.hpp +++ b/include/godot_cpp/variant/vector3.hpp @@ -32,10 +32,10 @@ #include #include +#include namespace godot { -class String; struct Basis; struct Vector2; struct Vector3i; diff --git a/src/variant/plane.cpp b/src/variant/plane.cpp index 05aadcaa9..9b72c7af2 100644 --- a/src/variant/plane.cpp +++ b/src/variant/plane.cpp @@ -60,7 +60,7 @@ Vector3 Plane::get_any_perpendicular_normal() const { static const Vector3 p2 = Vector3(0, 1, 0); Vector3 p; - if (ABS(normal.dot(p1)) > 0.99f) { // if too similar to p1 + if (Math::abs(normal.dot(p1)) > 0.99f) { // if too similar to p1 p = p2; // use p2 } else { p = p1; // use p1 diff --git a/tools/godotcpp.py b/tools/godotcpp.py index 3646264ba..b8af9345f 100644 --- a/tools/godotcpp.py +++ b/tools/godotcpp.py @@ -467,8 +467,6 @@ def generate(env): # DEBUG_ENABLED enables debugging *features* and debug-only code, which is intended # to give *users* extra debugging information for their game development. env.Append(CPPDEFINES=["DEBUG_ENABLED"]) - # In upstream Godot this is added in typedefs.h when DEBUG_ENABLED is set. - env.Append(CPPDEFINES=["DEBUG_METHODS_ENABLED"]) if env.dev_build: # DEV_ENABLED enables *engine developer* code which should only be compiled for those From b0399d978211418d40b8e622e8e12aa366bf68c0 Mon Sep 17 00:00:00 2001 From: Grublady Date: Tue, 8 Apr 2025 20:34:29 -0400 Subject: [PATCH 20/41] Fix TypedDictionary binding generation (cherry picked from commit 26201dd27aa6c7a8bbc68b655f8665697ac837c3) --- binding_generator.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/binding_generator.py b/binding_generator.py index c5b535c9a..a01389cb6 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -1391,7 +1391,7 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node): fully_used_classes.add(dict_type_name) else: used_classes.add(dict_type_name) - dict_type_name = dict_type_names[2] + dict_type_name = dict_type_names[1] if dict_type_name.endswith("*"): dict_type_name = dict_type_name[:-1] if is_included(dict_type_name, class_name): @@ -1446,7 +1446,7 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node): fully_used_classes.add(dict_type_name) else: used_classes.add(dict_type_name) - dict_type_name = dict_type_names[2] + dict_type_name = dict_type_names[1] if dict_type_name.endswith("*"): dict_type_name = dict_type_name[:-1] if is_included(dict_type_name, class_name): @@ -1955,7 +1955,7 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us if has_return: result.append( - f'\tCHECK_METHOD_BIND_RET(_gde_method_bind, {get_default_value_for_type(method["return_value"]["type"])});' + f'\tCHECK_METHOD_BIND_RET(_gde_method_bind, ({get_default_value_for_type(method["return_value"]["type"])}));' ) else: result.append("\tCHECK_METHOD_BIND(_gde_method_bind);") @@ -2249,7 +2249,7 @@ def generate_utility_functions(api, output_dir): has_return = "return_type" in function and function["return_type"] != "void" if has_return: source.append( - f'\tCHECK_METHOD_BIND_RET(_gde_function, {get_default_value_for_type(function["return_type"])});' + f'\tCHECK_METHOD_BIND_RET(_gde_function, ({get_default_value_for_type(function["return_type"])}));' ) else: source.append("\tCHECK_METHOD_BIND(_gde_function);") From 5dae002a5d4ec3cbc3fe2c663c7b34dc2f598b02 Mon Sep 17 00:00:00 2001 From: Samuel Nicholas Date: Wed, 16 Apr 2025 10:31:50 +0930 Subject: [PATCH 21/41] version bump of mozilla-sccache action to 0.0.9 https://github.blog/changelog/2025-03-20-notification-of-upcoming-breaking-changes-in-github-actions/#decommissioned-cache-service-brownouts (cherry picked from commit bbbcc6adc783f548bc1a8995d3c70774e42d2589) --- .github/workflows/ci-cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-cmake.yml b/.github/workflows/ci-cmake.yml index 706c87b9a..713cf6a68 100644 --- a/.github/workflows/ci-cmake.yml +++ b/.github/workflows/ci-cmake.yml @@ -119,7 +119,7 @@ jobs: submodules: recursive - name: Run sccache-cache - uses: mozilla-actions/sccache-action@v0.0.7 + uses: mozilla-actions/sccache-action@v0.0.9 - name: Setup godot-cpp uses: ./.github/actions/setup-godot-cpp From 6182a2728b54dea95de631e757c82c5191da2d32 Mon Sep 17 00:00:00 2001 From: Marc Gilleron Date: Wed, 16 Apr 2025 20:37:19 +0200 Subject: [PATCH 22/41] Use Math::abs to avoid ambiguity with integer abs (cherry picked from commit 7670de814f99f0011ad27ddc2c2e8a31ae930c7e) --- src/variant/basis.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/variant/basis.cpp b/src/variant/basis.cpp index 67cbb3aca..f0a0b6495 100644 --- a/src/variant/basis.cpp +++ b/src/variant/basis.cpp @@ -272,7 +272,7 @@ Basis Basis::scaled_orthogonal(const Vector3 &p_scale) const { Vector3 dots; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { - dots[j] += s[i] * abs(m.get_column(i).normalized().dot(b.get_column(j))); + dots[j] += s[i] * Math::abs(m.get_column(i).normalized().dot(b.get_column(j))); } } if (sign != std::signbit(dots.x + dots.y + dots.z)) { From b905a87ebe23524257779d39c61ccfc07fca5f4a Mon Sep 17 00:00:00 2001 From: Thaddeus Crews Date: Wed, 2 Apr 2025 12:34:03 -0500 Subject: [PATCH 23/41] SCons: Add `CPPEXTPATH` for external includes (cherry picked from commit 30bfa6f215d12a2c4ac4d09e892c053385f7c09d) --- tools/godotcpp.py | 14 ++++++++++++++ tools/windows.py | 5 +++++ 2 files changed, 19 insertions(+) diff --git a/tools/godotcpp.py b/tools/godotcpp.py index b8af9345f..63df0ad54 100644 --- a/tools/godotcpp.py +++ b/tools/godotcpp.py @@ -2,6 +2,7 @@ import platform import sys +from SCons import __version__ as scons_raw_version from SCons.Action import Action from SCons.Builder import Builder from SCons.Errors import UserError @@ -380,6 +381,8 @@ def options(opts, env): def generate(env): + env.scons_version = env._get_major_minor_revision(scons_raw_version) + # Default num_jobs to local cpu count if not user specified. # SCons has a peculiarity where user-specified options won't be overridden # by SetOption, so we can rely on this to know if we should use our default. @@ -437,6 +440,17 @@ def generate(env): else: # Release opt_level = "speed" + # Allow marking includes as external/system to avoid raising warnings. + if env.scons_version < (4, 2): + env["_CPPEXTINCFLAGS"] = "${_concat(EXTINCPREFIX, CPPEXTPATH, EXTINCSUFFIX, __env__, RDirs, TARGET, SOURCE)}" + else: + env["_CPPEXTINCFLAGS"] = ( + "${_concat(EXTINCPREFIX, CPPEXTPATH, EXTINCSUFFIX, __env__, RDirs, TARGET, SOURCE, affect_signature=False)}" + ) + env["CPPEXTPATH"] = [] + env["EXTINCPREFIX"] = "-isystem " + env["EXTINCSUFFIX"] = "" + env["optimize"] = ARGUMENTS.get("optimize", opt_level) env["debug_symbols"] = get_cmdline_bool("debug_symbols", env.dev_build) diff --git a/tools/windows.py b/tools/windows.py index f66bce423..93ca89e63 100644 --- a/tools/windows.py +++ b/tools/windows.py @@ -130,6 +130,11 @@ def generate(env): if env["silence_msvc"] and not env.GetOption("clean"): silence_msvc(env) + if not env["use_llvm"]: + env.AppendUnique(CCFLAGS=["/experimental:external", "/external:anglebrackets"]) + env.AppendUnique(CCFLAGS=["/external:W0"]) + env["EXTINCPREFIX"] = "/external:I" + elif (sys.platform == "win32" or sys.platform == "msys") and not env["mingw_prefix"]: env["use_mingw"] = True mingw.generate(env) From 947d357252224c82061d7250e502250952b1846d Mon Sep 17 00:00:00 2001 From: Samuel Nicholas Date: Wed, 16 Apr 2025 13:35:01 +0930 Subject: [PATCH 24/41] Match #1758 build option changes https://github.com/enetheru/godot-cpp/commit/d634a5f8c49414cea86efa0d8cb25095064d292c#diff-e2225522e55739f1533a3ce9eee58324ac9c192c8ba30065067964347d22fdacL471 (cherry picked from commit b195a51c6c7d0f53a00061dacd7e05979fe03d92) --- cmake/common_compiler_flags.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/common_compiler_flags.cmake b/cmake/common_compiler_flags.cmake index 8a4d836f5..9d4894f13 100644 --- a/cmake/common_compiler_flags.cmake +++ b/cmake/common_compiler_flags.cmake @@ -159,7 +159,7 @@ function(common_compiler_flags) GDEXTENSION # features - $<${DEBUG_FEATURES}:DEBUG_ENABLED DEBUG_METHODS_ENABLED> + $<${DEBUG_FEATURES}:DEBUG_ENABLED> $<${IS_DEV_BUILD}:DEV_ENABLED> From f4c1de582ced4d403751f7f7cc13917ec3121762 Mon Sep 17 00:00:00 2001 From: David Snopek Date: Fri, 25 Apr 2025 14:31:10 -0500 Subject: [PATCH 25/41] Fix classes without `_to_string()` always returning `"[Wrapped:0]"` (cherry picked from commit f38c056b674b3d9eef5d92582e880a349e2ffe7b) --- binding_generator.py | 10 ++++++++++ include/godot_cpp/classes/wrapped.hpp | 6 +----- test/project/main.gd | 3 +-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/binding_generator.py b/binding_generator.py index a01389cb6..15012f974 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -1723,6 +1723,16 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us result.append(f"\t~{class_name}();") result.append("") + if class_name == "Object": + result.append('\tString _to_string() const { return "<" + get_class() + "#" + itos(get_instance_id()) + ">"; }') + result.append("") + + if class_name == "Node": + result.append( + '\tString _to_string() const { return (!get_name().is_empty() ? String(get_name()) + ":" : "") + Object::_to_string(); }' + ) + result.append("") + result.append("public:") # Special cases. diff --git a/include/godot_cpp/classes/wrapped.hpp b/include/godot_cpp/classes/wrapped.hpp index 2b4a9035e..647d611b1 100644 --- a/include/godot_cpp/classes/wrapped.hpp +++ b/include/godot_cpp/classes/wrapped.hpp @@ -93,7 +93,7 @@ class Wrapped { bool _property_can_revert(const StringName &p_name) const { return false; } bool _property_get_revert(const StringName &p_name, Variant &r_property) const { return false; } void _validate_property(PropertyInfo &p_property) const {} - String _to_string() const { return "[" + String(get_class_static()) + ":" + itos(get_instance_id()) + "]"; } + String _to_string() const { return ""; } static void notification_bind(GDExtensionClassInstancePtr p_instance, int32_t p_what, GDExtensionBool p_reversed) {} static GDExtensionBool set_bind(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionConstVariantPtr p_value) { return false; } @@ -121,10 +121,6 @@ class Wrapped { return string_name; } - uint64_t get_instance_id() const { - return 0; - } - // Must be public but you should not touch this. GodotObject *_owner = nullptr; }; diff --git a/test/project/main.gd b/test/project/main.gd index b69ad75a0..5ade71719 100644 --- a/test/project/main.gd +++ b/test/project/main.gd @@ -18,8 +18,7 @@ func _ready(): # To string. assert_equal(example.to_string(),'[ GDExtension::Example <--> Instance ID:%s ]' % example.get_instance_id()) - # It appears there's a bug with instance ids :-( - #assert_equal($Example/ExampleMin.to_string(), 'ExampleMin:[Wrapped:%s]' % $Example/ExampleMin.get_instance_id()) + assert_equal($Example/ExampleMin.to_string(), 'ExampleMin:' % $Example/ExampleMin.get_instance_id()) # Call static methods. assert_equal(Example.test_static(9, 100), 109); From b41801b6a86758937ef14190aea7b9f625fd613b Mon Sep 17 00:00:00 2001 From: Ben Lubar Date: Mon, 21 Apr 2025 18:45:05 -0500 Subject: [PATCH 26/41] fix iterators making unintended copies (cherry picked from commit 7fd0999b3c042a245b72e8ffab0b4145612687f6) --- src/core/class_db.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/class_db.cpp b/src/core/class_db.cpp index f6257b733..59ef63180 100644 --- a/src/core/class_db.cpp +++ b/src/core/class_db.cpp @@ -392,7 +392,7 @@ void ClassDB::initialize_class(const ClassInfo &p_cl) { } void ClassDB::initialize(GDExtensionInitializationLevel p_level) { - for (const std::pair pair : classes) { + for (const std::pair &pair : classes) { const ClassInfo &cl = pair.second; if (cl.level != p_level) { continue; From 90260ea6591946e7cfc4033d670b90ae527e0273 Mon Sep 17 00:00:00 2001 From: David Snopek Date: Tue, 1 Apr 2025 14:09:46 -0500 Subject: [PATCH 27/41] Stop referring to GDExtension as experimental in the README (cherry picked from commit 7660dd28b3ac42178bbf578fe5fcddb181a6f65a) --- README.md | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 843f7b34e..ac267733e 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,8 @@ > from Godot's `master` branch. > > For users of stable branches, switch to the branch matching your target Godot version: +> - [`4.4`](https://github.com/godotengine/godot-cpp/tree/4.4) +> - [`4.3`](https://github.com/godotengine/godot-cpp/tree/4.3) > - [`4.2`](https://github.com/godotengine/godot-cpp/tree/4.2) > - [`4.1`](https://github.com/godotengine/godot-cpp/tree/4.1) > - [`4.0`](https://github.com/godotengine/godot-cpp/tree/4.0) @@ -49,20 +51,13 @@ Godot version.** ## Compatibility -> [!WARNING] -> -> The GDExtension API is brand new in Godot 4.0, and is still -considered in **beta** stage, despite Godot 4.0 itself being released. -> -> This applies to both the GDExtension interface header, the API JSON, and this -first-party `godot-cpp` extension. -> -> Some compatibility breakage is to be expected as GDExtension and `godot-cpp` -> get more used, documented, and critical issues get resolved. See the -> [Godot issue tracker](https://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aopen+label%3Atopic%3Agdextension) -> and the [godot-cpp issue tracker](https://github.com/godotengine/godot-cpp/issues) -> for a list of known issues, and be sure to provide feedback on issues and PRs -> which affect your use of this extension. +GDExtensions targeting an earlier version of Godot should work in later minor versions, +but not vice-versa. For example, a GDExtension targeting Godot 4.2 should work just fine +in Godot 4.3, but one targeting Godot 4.3 won't work in Godot 4.2. + +There is one exception to this: extensions targeting Godot 4.0 will _not_ work with +Godot 4.1 and later. +See [Updating your GDExtension for 4.1](https://docs.godotengine.org/en/latest/tutorials/migrating/upgrading_to_godot_4.1.html#updating-your-gdextension-for-godot-4-1). ## Contributing From 532a028e177b808fcef086a0fe06675e4e18492f Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Wed, 21 May 2025 16:30:50 +0200 Subject: [PATCH 28/41] fix: Add iOS min SDK version link flags This is required when publishing to the App Store, and consistent with what we already do for the macOS deployment target. (cherry picked from commit 4879eb7bd01716587f813dd97a27238ef92f3f9f) --- tools/ios.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/ios.py b/tools/ios.py index 25c17db31..4e2a45c22 100644 --- a/tools/ios.py +++ b/tools/ios.py @@ -36,9 +36,11 @@ def generate(env): if env["ios_simulator"]: sdk_name = "iphonesimulator" env.Append(CCFLAGS=["-mios-simulator-version-min=" + env["ios_min_version"]]) + env.Append(LINKFLAGS=["-mios-simulator-version-min=" + env["ios_min_version"]]) else: sdk_name = "iphoneos" env.Append(CCFLAGS=["-miphoneos-version-min=" + env["ios_min_version"]]) + env.Append(LINKFLAGS=["-miphoneos-version-min=" + env["ios_min_version"]]) if sys.platform == "darwin": if env["IOS_SDK_PATH"] == "": From 08f893f1ead89bb7d08833a31c4472dc9efe028a Mon Sep 17 00:00:00 2001 From: Thaddeus Crews Date: Sat, 26 Apr 2025 12:23:07 -0500 Subject: [PATCH 29/41] CI: Various version bumps; sync with main repo (cherry picked from commit 64cdf089d98e524fba114f1757c0c41d255f0ed4) --- .clang-format | 233 ++++++++++-------- .editorconfig | 3 +- .pre-commit-config.yaml | 14 +- SConstruct | 2 +- binding_generator.py | 130 +++++----- include/godot_cpp/classes/wrapped.hpp | 20 +- include/godot_cpp/core/method_bind.hpp | 12 +- .../variant/callable_method_pointer.hpp | 9 +- include/godot_cpp/variant/char_string.hpp | 2 +- include/godot_cpp/variant/variant.hpp | 2 +- pyproject.toml | 62 ++--- test/src/example.cpp | 4 +- test/src/example.h | 2 +- 13 files changed, 268 insertions(+), 227 deletions(-) diff --git a/.clang-format b/.clang-format index 1df6c35bf..87731d9eb 100644 --- a/.clang-format +++ b/.clang-format @@ -1,80 +1,105 @@ # Commented out parameters are those with the same value as base LLVM style. # We can uncomment them if we want to change their value, or enforce the -# chosen value in case the base style changes (last sync: Clang 14.0). ---- -### General config, applies to all languages ### -BasedOnStyle: LLVM +# chosen value in case the base style changes (last sync: Clang 17.0.6). +BasedOnStyle: LLVM AccessModifierOffset: -4 AlignAfterOpenBracket: DontAlign # AlignArrayOfStructures: None -# AlignConsecutiveMacros: None -# AlignConsecutiveAssignments: None -# AlignConsecutiveBitFields: None -# AlignConsecutiveDeclarations: None +# AlignConsecutiveAssignments: +# Enabled: false +# AcrossEmptyLines: false +# AcrossComments: false +# AlignCompound: false +# PadOperators: true +# AlignConsecutiveBitFields: +# Enabled: false +# AcrossEmptyLines: false +# AcrossComments: false +# AlignCompound: false +# PadOperators: false +# AlignConsecutiveDeclarations: +# Enabled: false +# AcrossEmptyLines: false +# AcrossComments: false +# AlignCompound: false +# PadOperators: false +# AlignConsecutiveMacros: +# Enabled: false +# AcrossEmptyLines: false +# AcrossComments: false +# AlignCompound: false +# PadOperators: false +# AlignConsecutiveShortCaseStatements: +# Enabled: false +# AcrossEmptyLines: false +# AcrossComments: false +# AlignCaseColons: false # AlignEscapedNewlines: Right -AlignOperands: DontAlign -AlignTrailingComments: false +AlignOperands: DontAlign +AlignTrailingComments: + Kind: Never + OverEmptyLines: 0 # AllowAllArgumentsOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: false -# AllowShortEnumsOnASingleLine: true # AllowShortBlocksOnASingleLine: Never # AllowShortCaseLabelsOnASingleLine: false -# AllowShortFunctionsOnASingleLine: All -# AllowShortLambdasOnASingleLine: All +# AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: Inline # AllowShortIfStatementsOnASingleLine: Never +# AllowShortLambdasOnASingleLine: All # AllowShortLoopsOnASingleLine: false # AlwaysBreakAfterDefinitionReturnType: None # AlwaysBreakAfterReturnType: None # AlwaysBreakBeforeMultilineStrings: false # AlwaysBreakTemplateDeclarations: MultiLine -# AttributeMacros: -# - __capability +AttributeMacros: + - _ALWAYS_INLINE_ + - _FORCE_INLINE_ + - _NO_INLINE_ # BinPackArguments: true # BinPackParameters: true +# BitFieldColonSpacing: Both # BraceWrapping: -# AfterCaseLabel: false -# AfterClass: false +# AfterCaseLabel: false +# AfterClass: false # AfterControlStatement: Never -# AfterEnum: false -# AfterFunction: false -# AfterNamespace: false +# AfterEnum: false +# AfterFunction: false +# AfterNamespace: false # AfterObjCDeclaration: false -# AfterStruct: false -# AfterUnion: false +# AfterStruct: false +# AfterUnion: false # AfterExternBlock: false -# BeforeCatch: false -# BeforeElse: false +# BeforeCatch: false +# BeforeElse: false # BeforeLambdaBody: false -# BeforeWhile: false -# IndentBraces: false +# BeforeWhile: false +# IndentBraces: false # SplitEmptyFunction: true # SplitEmptyRecord: true # SplitEmptyNamespace: true +# BreakAfterAttributes: Never +# BreakAfterJavaFieldAnnotations: false +# BreakArrays: true # BreakBeforeBinaryOperators: None -# BreakBeforeConceptDeclarations: true # BreakBeforeBraces: Attach -# BreakBeforeInheritanceComma: false -# BreakInheritanceList: BeforeColon +# BreakBeforeConceptDeclarations: Always +# BreakBeforeInlineASMColon: OnlyMultiline # BreakBeforeTernaryOperators: true -# BreakConstructorInitializersBeforeComma: false BreakConstructorInitializers: AfterColon +# BreakInheritanceList: BeforeColon # BreakStringLiterals: true -ColumnLimit: 0 -# CommentPragmas: '^ IWYU pragma:' -# QualifierAlignment: Leave +ColumnLimit: 0 +# CommentPragmas: "^ IWYU pragma:" # CompactNamespaces: false ConstructorInitializerIndentWidth: 8 ContinuationIndentWidth: 8 Cpp11BracedListStyle: false -# DeriveLineEnding: true # DerivePointerAlignment: false -# DisableFormat: false +# DisableFormat: false # EmptyLineAfterAccessModifier: Never # EmptyLineBeforeAccessModifier: LogicalBlock # ExperimentalAutoDetectBinPacking: false -# PackConstructorInitializers: BinPack -ConstructorInitializerAllOnOneLineOrOnePerLine: true -# AllowAllConstructorInitializersOnNextLine: true # FixNamespaceComments: true # ForEachMacros: # - foreach @@ -82,34 +107,61 @@ ConstructorInitializerAllOnOneLineOrOnePerLine: true # - BOOST_FOREACH # IfMacros: # - KJ_IF_MAYBE -# IncludeBlocks: Preserve +# IncludeBlocks: Preserve IncludeCategories: - - Regex: '".*"' - Priority: 1 - - Regex: '^<.*\.h>' - Priority: 2 - - Regex: '^<.*' - Priority: 3 -# IncludeIsMainRegex: '(Test)?$' -# IncludeIsMainSourceRegex: '' + - Regex: ^".*"$ + Priority: 1 + - Regex: ^<.*\.h>$ + Priority: 2 + - Regex: ^<.*>$ + Priority: 3 +# IncludeIsMainRegex: (Test)?$ +# IncludeIsMainSourceRegex: "" # IndentAccessModifiers: false -IndentCaseLabels: true # IndentCaseBlocks: false +IndentCaseLabels: true +# IndentExternBlock: AfterExternBlock # IndentGotoLabels: true # IndentPPDirectives: None -# IndentExternBlock: AfterExternBlock -# IndentRequires: false -IndentWidth: 4 +# IndentRequiresClause: true +IndentWidth: 4 # IndentWrappedFunctionNames: false +InsertBraces: true +# InsertNewlineAtEOF: false # InsertTrailingCommas: None +# IntegerLiteralSeparator: +# Binary: 0 +# BinaryMinDigits: 0 +# Decimal: 0 +# DecimalMinDigits: 0 +# Hex: 0 +# HexMinDigits: 0 +JavaImportGroups: + - org.godotengine + - android + - androidx + - com.android + - com.google + - java + - javax # JavaScriptQuotes: Leave # JavaScriptWrapImports: true +# KeepEmptyLinesAtEOF: false KeepEmptyLinesAtTheStartOfBlocks: false # LambdaBodyIndentation: Signature -# MacroBlockBegin: '' -# MacroBlockEnd: '' +# Language: Cpp +# LineEnding: DeriveLF +# MacroBlockBegin: "" +# MacroBlockEnd: "" # MaxEmptyLinesToKeep: 1 # NamespaceIndentation: None +# ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 4 +# ObjCBreakBeforeNestedBlockParam: true +# ObjCSpaceAfterProperty: false +# ObjCSpaceBeforeProtocolList: true +# PPIndentWidth: -1 +PackConstructorInitializers: NextLine # PenaltyBreakAssignment: 2 # PenaltyBreakBeforeFirstCallParameter: 19 # PenaltyBreakComment: 300 @@ -118,82 +170,71 @@ KeepEmptyLinesAtTheStartOfBlocks: false # PenaltyBreakString: 1000 # PenaltyBreakTemplateDeclaration: 10 # PenaltyExcessCharacter: 1000000 -# PenaltyReturnTypeOnItsOwnLine: 60 # PenaltyIndentedWhitespace: 0 +# PenaltyReturnTypeOnItsOwnLine: 60 # PointerAlignment: Right -# PPIndentWidth: -1 +# QualifierAlignment: Leave # ReferenceAlignment: Pointer -# ReflowComments: true +# ReflowComments: true # RemoveBracesLLVM: false +# RemoveParentheses: Leave +RemoveSemicolon: true +# RequiresClausePosition: OwnLine +# RequiresExpressionIndentation: OuterScope # SeparateDefinitionBlocks: Leave # ShortNamespaceLines: 1 -# SortIncludes: CaseSensitive +# SortIncludes: CaseSensitive # SortJavaStaticImport: Before -# SortUsingDeclarations: true +# SortUsingDeclarations: LexicographicNumeric # SpaceAfterCStyleCast: false # SpaceAfterLogicalNot: false # SpaceAfterTemplateKeyword: true +# SpaceAroundPointerQualifiers: Default # SpaceBeforeAssignmentOperators: true # SpaceBeforeCaseColon: false # SpaceBeforeCpp11BracedList: false # SpaceBeforeCtorInitializerColon: true # SpaceBeforeInheritanceColon: true +# SpaceBeforeJsonColon: false # SpaceBeforeParens: ControlStatements # SpaceBeforeParensOptions: # AfterControlStatements: true # AfterForeachMacros: true -# AfterFunctionDefinitionName: false # AfterFunctionDeclarationName: false -# AfterIfMacros: true +# AfterFunctionDefinitionName: false +# AfterIfMacros: true # AfterOverloadedOperator: false +# AfterRequiresInClause: false +# AfterRequiresInExpression: false # BeforeNonEmptyParentheses: false -# SpaceAroundPointerQualifiers: Default # SpaceBeforeRangeBasedForLoopColon: true +# SpaceBeforeSquareBrackets: false # SpaceInEmptyBlock: false -# SpaceInEmptyParentheses: false # SpacesBeforeTrailingComments: 1 -# SpacesInAngles: Never -# SpacesInConditionalStatement: false +# SpacesInAngles: Never # SpacesInContainerLiterals: true -# SpacesInCStyleCastParentheses: false -## Godot TODO: We'll want to use a min of 1, but we need to see how to fix -## our comment capitalization at the same time. SpacesInLineCommentPrefix: - Minimum: 0 - Maximum: -1 -# SpacesInParentheses: false + Minimum: 0 # We want a minimum of 1 for comments, but allow 0 for disabled code. + Maximum: -1 +# SpacesInParens: Never +# SpacesInParensOptions: +# InConditionalStatements: false +# InCStyleCasts: false +# InEmptyParentheses: false +# Other: false # SpacesInSquareBrackets: false -# SpaceBeforeSquareBrackets: false -# BitFieldColonSpacing: Both +Standard: c++20 # StatementAttributeLikeMacros: # - Q_EMIT # StatementMacros: # - Q_UNUSED # - QT_REQUIRE_VERSION -TabWidth: 4 -# UseCRLF: false -UseTab: Always +TabWidth: 4 +UseTab: Always +# VerilogBreakBetweenInstancePorts: true # WhitespaceSensitiveMacros: -# - STRINGIZE -# - PP_STRINGIZE # - BOOST_PP_STRINGIZE -# - NS_SWIFT_NAME # - CF_SWIFT_NAME ---- -### C++ specific config ### -Language: Cpp -Standard: c++17 ---- -### ObjC specific config ### -Language: ObjC -# ObjCBinPackProtocolList: Auto -ObjCBlockIndentWidth: 4 -# ObjCBreakBeforeNestedBlockParam: true -# ObjCSpaceAfterProperty: false -# ObjCSpaceBeforeProtocolList: true ---- -### Java specific config ### -Language: Java -# BreakAfterJavaFieldAnnotations: false -JavaImportGroups: ['org.godotengine', 'android', 'androidx', 'com.android', 'com.google', 'java', 'javax'] -... +# - NS_SWIFT_NAME +# - PP_STRINGIZE +# - STRINGIZE diff --git a/.editorconfig b/.editorconfig index f14ac7f14..0da03e8a7 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,11 +6,12 @@ end_of_line = lf indent_size = 4 indent_style = tab insert_final_newline = true +max_line_length = 120 trim_trailing_whitespace = true [{*.py,SConstruct}] indent_style = space -[*.{yml,yaml}] +[{*.{yml,yaml},.clang-format}] indent_size = 2 indent_style = space diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7354ba41f..e370058f4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,32 +9,36 @@ exclude: | repos: - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v17.0.6 + rev: v20.1.0 hooks: - id: clang-format - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.4.4 + rev: v0.11.4 hooks: - id: ruff args: [--fix] + files: (\.py|SConstruct)$ + types_or: [text] - id: ruff-format + files: (\.py|SConstruct)$ + types_or: [text] - repo: https://github.com/pre-commit/mirrors-mypy - rev: v0.971 + rev: v1.14.1 # Latest version that supports Python 3.8 hooks: - id: mypy files: \.py$ types_or: [text] - repo: https://github.com/codespell-project/codespell - rev: v2.3.0 + rev: v2.4.1 hooks: - id: codespell additional_dependencies: [tomli] - repo: https://github.com/BlankSpruce/gersemi - rev: 0.18.2 + rev: 0.19.2 hooks: - id: gersemi args: ["-i", "--no-warn-about-unknown-commands", "-l", "120"] diff --git a/SConstruct b/SConstruct index 8acea2624..64d335b5d 100644 --- a/SConstruct +++ b/SConstruct @@ -3,7 +3,7 @@ import os EnsureSConsVersion(4, 0) - +EnsurePythonVersion(3, 8) try: Import("env") diff --git a/binding_generator.py b/binding_generator.py index 15012f974..144ff75d1 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -356,7 +356,7 @@ def generate_builtin_bindings(api, output_dir, build_config): add_header("variant_size.hpp", variant_size_source) variant_size_source.append("#pragma once") - variant_size_source.append(f'#define GODOT_CPP_VARIANT_SIZE {builtin_sizes["Variant"]}') + variant_size_source.append(f"#define GODOT_CPP_VARIANT_SIZE {builtin_sizes['Variant']}") variant_size_file.write("\n".join(variant_size_source)) @@ -601,19 +601,19 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl if "constructors" in builtin_api: for constructor in builtin_api["constructors"]: - result.append(f'\t\tGDExtensionPtrConstructor constructor_{constructor["index"]};') + result.append(f"\t\tGDExtensionPtrConstructor constructor_{constructor['index']};") if builtin_api["has_destructor"]: result.append("\t\tGDExtensionPtrDestructor destructor;") if "methods" in builtin_api: for method in builtin_api["methods"]: - result.append(f'\t\tGDExtensionPtrBuiltInMethod method_{method["name"]};') + result.append(f"\t\tGDExtensionPtrBuiltInMethod method_{method['name']};") if "members" in builtin_api: for member in builtin_api["members"]: - result.append(f'\t\tGDExtensionPtrSetter member_{member["name"]}_setter;') - result.append(f'\t\tGDExtensionPtrGetter member_{member["name"]}_getter;') + result.append(f"\t\tGDExtensionPtrSetter member_{member['name']}_setter;") + result.append(f"\t\tGDExtensionPtrGetter member_{member['name']}_getter;") if "indexing_return_type" in builtin_api: result.append("\t\tGDExtensionPtrIndexedSetter indexed_setter;") @@ -628,10 +628,10 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl for operator in builtin_api["operators"]: if "right_type" in operator: result.append( - f'\t\tGDExtensionPtrOperatorEvaluator operator_{get_operator_id_name(operator["name"])}_{operator["right_type"]};' + f"\t\tGDExtensionPtrOperatorEvaluator operator_{get_operator_id_name(operator['name'])}_{operator['right_type']};" ) else: - result.append(f'\t\tGDExtensionPtrOperatorEvaluator operator_{get_operator_id_name(operator["name"])};') + result.append(f"\t\tGDExtensionPtrOperatorEvaluator operator_{get_operator_id_name(operator['name'])};") result.append("\t} _method_bindings;") @@ -693,12 +693,12 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl if class_name == "Vector3" and constant["name"].startswith("AXIS"): if axis_constants_count == 0: result.append("\tenum Axis {") - result.append(f'\t\t{constant["name"]} = {constant["value"]},') + result.append(f"\t\t{constant['name']} = {constant['value']},") axis_constants_count += 1 if axis_constants_count == 3: result.append("\t};") else: - result.append(f'\tstatic const {correct_type(constant["type"])} {constant["name"]};') + result.append(f"\tstatic const {correct_type(constant['type'])} {constant['name']};") if builtin_api["has_destructor"]: result.append(f"\t~{class_name}();") @@ -718,13 +718,13 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl method_signature += "static " if "return_type" in method: - method_signature += f'{correct_type(method["return_type"])}' + method_signature += f"{correct_type(method['return_type'])}" if not method_signature.endswith("*"): method_signature += " " else: method_signature += "void " - method_signature += f'{method["name"]}(' + method_signature += f"{method['name']}(" method_arguments = [] if "arguments" in method: @@ -759,21 +759,21 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl if "members" in builtin_api: for member in builtin_api["members"]: - if f'get_{member["name"]}' not in method_list: - result.append(f'\t{correct_type(member["type"])} get_{member["name"]}() const;') - if f'set_{member["name"]}' not in method_list: - result.append(f'\tvoid set_{member["name"]}({type_for_parameter(member["type"])}value);') + if f"get_{member['name']}" not in method_list: + result.append(f"\t{correct_type(member['type'])} get_{member['name']}() const;") + if f"set_{member['name']}" not in method_list: + result.append(f"\tvoid set_{member['name']}({type_for_parameter(member['type'])}value);") if "operators" in builtin_api: for operator in builtin_api["operators"]: if is_valid_cpp_operator(operator["name"]): if "right_type" in operator: result.append( - f'\t{correct_type(operator["return_type"])} operator{get_operator_cpp_name(operator["name"])}({type_for_parameter(operator["right_type"])}p_other) const;' + f"\t{correct_type(operator['return_type'])} operator{get_operator_cpp_name(operator['name'])}({type_for_parameter(operator['right_type'])}p_other) const;" ) else: result.append( - f'\t{correct_type(operator["return_type"])} operator{get_operator_cpp_name(operator["name"])}() const;' + f"\t{correct_type(operator['return_type'])} operator{get_operator_cpp_name(operator['name'])}() const;" ) # Copy assignment. @@ -1041,7 +1041,7 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl if "constructors" in builtin_api: for constructor in builtin_api["constructors"]: result.append( - f'\t_method_bindings.constructor_{constructor["index"]} = internal::gdextension_interface_variant_get_ptr_constructor({enum_type_name}, {constructor["index"]});' + f"\t_method_bindings.constructor_{constructor['index']} = internal::gdextension_interface_variant_get_ptr_constructor({enum_type_name}, {constructor['index']});" ) if builtin_api["has_destructor"]: @@ -1065,17 +1065,17 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl # TODO: Add error check for hash mismatch. result.append(f'\t_gde_name = StringName("{method["name"]}");') result.append( - f'\t_method_bindings.method_{method["name"]} = internal::gdextension_interface_variant_get_ptr_builtin_method({enum_type_name}, _gde_name._native_ptr(), {method["hash"]});' + f"\t_method_bindings.method_{method['name']} = internal::gdextension_interface_variant_get_ptr_builtin_method({enum_type_name}, _gde_name._native_ptr(), {method['hash']});" ) if "members" in builtin_api: for member in builtin_api["members"]: result.append(f'\t_gde_name = StringName("{member["name"]}");') result.append( - f'\t_method_bindings.member_{member["name"]}_setter = internal::gdextension_interface_variant_get_ptr_setter({enum_type_name}, _gde_name._native_ptr());' + f"\t_method_bindings.member_{member['name']}_setter = internal::gdextension_interface_variant_get_ptr_setter({enum_type_name}, _gde_name._native_ptr());" ) result.append( - f'\t_method_bindings.member_{member["name"]}_getter = internal::gdextension_interface_variant_get_ptr_getter({enum_type_name}, _gde_name._native_ptr());' + f"\t_method_bindings.member_{member['name']}_getter = internal::gdextension_interface_variant_get_ptr_getter({enum_type_name}, _gde_name._native_ptr());" ) if "indexing_return_type" in builtin_api: @@ -1107,11 +1107,11 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl f"GDEXTENSION_VARIANT_TYPE_{camel_to_snake(operator['right_type']).upper()}" ) result.append( - f'\t_method_bindings.operator_{get_operator_id_name(operator["name"])}_{operator["right_type"]} = internal::gdextension_interface_variant_get_ptr_operator_evaluator(GDEXTENSION_VARIANT_OP_{get_operator_id_name(operator["name"]).upper()}, {enum_type_name}, {right_type_variant_type});' + f"\t_method_bindings.operator_{get_operator_id_name(operator['name'])}_{operator['right_type']} = internal::gdextension_interface_variant_get_ptr_operator_evaluator(GDEXTENSION_VARIANT_OP_{get_operator_id_name(operator['name']).upper()}, {enum_type_name}, {right_type_variant_type});" ) else: result.append( - f'\t_method_bindings.operator_{get_operator_id_name(operator["name"])} = internal::gdextension_interface_variant_get_ptr_operator_evaluator(GDEXTENSION_VARIANT_OP_{get_operator_id_name(operator["name"]).upper()}, {enum_type_name}, GDEXTENSION_VARIANT_TYPE_NIL);' + f"\t_method_bindings.operator_{get_operator_id_name(operator['name'])} = internal::gdextension_interface_variant_get_ptr_operator_evaluator(GDEXTENSION_VARIANT_OP_{get_operator_id_name(operator['name']).upper()}, {enum_type_name}, GDEXTENSION_VARIANT_TYPE_NIL);" ) result.append("}") @@ -1136,7 +1136,7 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl result.append(method_signature) method_call = ( - f'\tinternal::_call_builtin_constructor(_method_bindings.constructor_{constructor["index"]}, &opaque' + f"\tinternal::_call_builtin_constructor(_method_bindings.constructor_{constructor['index']}, &opaque" ) if "arguments" in constructor: if len(constructor["arguments"]) == 1 and constructor["arguments"][0]["type"] == class_name: @@ -1204,7 +1204,7 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl method_call += f"return internal::_call_builtin_method_ptr_ret_obj<{return_type}>(" else: method_call += "internal::_call_builtin_method_ptr_no_ret(" - method_call += f'_method_bindings.method_{method["name"]}, ' + method_call += f"_method_bindings.method_{method['name']}, " if "is_static" in method and method["is_static"]: method_call += "nullptr" else: @@ -1233,19 +1233,19 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl if "members" in builtin_api: for member in builtin_api["members"]: - if f'get_{member["name"]}' not in method_list: - result.append(f'{correct_type(member["type"])} {class_name}::get_{member["name"]}() const {{') + if f"get_{member['name']}" not in method_list: + result.append(f"{correct_type(member['type'])} {class_name}::get_{member['name']}() const {{") result.append( - f'\treturn internal::_call_builtin_ptr_getter<{correct_type(member["type"])}>(_method_bindings.member_{member["name"]}_getter, (GDExtensionConstTypePtr)&opaque);' + f"\treturn internal::_call_builtin_ptr_getter<{correct_type(member['type'])}>(_method_bindings.member_{member['name']}_getter, (GDExtensionConstTypePtr)&opaque);" ) result.append("}") - if f'set_{member["name"]}' not in method_list: - result.append(f'void {class_name}::set_{member["name"]}({type_for_parameter(member["type"])}value) {{') + if f"set_{member['name']}" not in method_list: + result.append(f"void {class_name}::set_{member['name']}({type_for_parameter(member['type'])}value) {{") (encode, arg_name) = get_encoded_arg("value", member["type"], None) result += encode result.append( - f'\t_method_bindings.member_{member["name"]}_setter((GDExtensionConstTypePtr)&opaque, (GDExtensionConstTypePtr){arg_name});' + f"\t_method_bindings.member_{member['name']}_setter((GDExtensionConstTypePtr)&opaque, (GDExtensionConstTypePtr){arg_name});" ) result.append("}") @@ -1256,20 +1256,20 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl if is_valid_cpp_operator(operator["name"]): if "right_type" in operator: result.append( - f'{correct_type(operator["return_type"])} {class_name}::operator{get_operator_cpp_name(operator["name"])}({type_for_parameter(operator["right_type"])}p_other) const {{' + f"{correct_type(operator['return_type'])} {class_name}::operator{get_operator_cpp_name(operator['name'])}({type_for_parameter(operator['right_type'])}p_other) const {{" ) (encode, arg_name) = get_encoded_arg("other", operator["right_type"], None) result += encode result.append( - f'\treturn internal::_call_builtin_operator_ptr<{get_gdextension_type(correct_type(operator["return_type"]))}>(_method_bindings.operator_{get_operator_id_name(operator["name"])}_{operator["right_type"]}, (GDExtensionConstTypePtr)&opaque, (GDExtensionConstTypePtr){arg_name});' + f"\treturn internal::_call_builtin_operator_ptr<{get_gdextension_type(correct_type(operator['return_type']))}>(_method_bindings.operator_{get_operator_id_name(operator['name'])}_{operator['right_type']}, (GDExtensionConstTypePtr)&opaque, (GDExtensionConstTypePtr){arg_name});" ) result.append("}") else: result.append( - f'{correct_type(operator["return_type"])} {class_name}::operator{get_operator_cpp_name(operator["name"])}() const {{' + f"{correct_type(operator['return_type'])} {class_name}::operator{get_operator_cpp_name(operator['name'])}() const {{" ) result.append( - f'\treturn internal::_call_builtin_operator_ptr<{get_gdextension_type(correct_type(operator["return_type"]))}>(_method_bindings.operator_{get_operator_id_name(operator["name"])}, (GDExtensionConstTypePtr)&opaque, (GDExtensionConstTypePtr) nullptr);' + f"\treturn internal::_call_builtin_operator_ptr<{get_gdextension_type(correct_type(operator['return_type']))}>(_method_bindings.operator_{get_operator_id_name(operator['name'])}, (GDExtensionConstTypePtr)&opaque, (GDExtensionConstTypePtr) nullptr);" ) result.append("}") result.append("") @@ -1638,12 +1638,12 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us if "enums" in class_api: for enum_api in class_api["enums"]: if enum_api["is_bitfield"]: - result.append(f'\tenum {enum_api["name"]} : uint64_t {{') + result.append(f"\tenum {enum_api['name']} : uint64_t {{") else: - result.append(f'\tenum {enum_api["name"]} {{') + result.append(f"\tenum {enum_api['name']} {{") for value in enum_api["values"]: - result.append(f'\t\t{value["name"]} = {value["value"]},') + result.append(f"\t\t{value['name']} = {value['value']},") result.append("\t};") result.append("") @@ -1651,7 +1651,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us for value in class_api["constants"]: if "type" not in value: value["type"] = "int" - result.append(f'\tstatic const {value["type"]} {value["name"]} = {value["value"]};') + result.append(f"\tstatic const {value['type']} {value['name']} = {value['value']};") result.append("") if is_singleton: @@ -1784,9 +1784,9 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us if "enums" in class_api and class_name != "Object": for enum_api in class_api["enums"]: if enum_api["is_bitfield"]: - result.append(f'VARIANT_BITFIELD_CAST({class_name}::{enum_api["name"]});') + result.append(f"VARIANT_BITFIELD_CAST({class_name}::{enum_api['name']});") else: - result.append(f'VARIANT_ENUM_CAST({class_name}::{enum_api["name"]});') + result.append(f"VARIANT_ENUM_CAST({class_name}::{enum_api['name']});") result.append("") if class_name == "ClassDBSingleton": @@ -1795,12 +1795,12 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us if "enums" in class_api: for enum_api in class_api["enums"]: if enum_api["is_bitfield"]: - result.append(f'\tenum {enum_api["name"]} : uint64_t {{ \\') + result.append(f"\tenum {enum_api['name']} : uint64_t {{ \\") else: - result.append(f'\tenum {enum_api["name"]} {{ \\') + result.append(f"\tenum {enum_api['name']} {{ \\") for value in enum_api["values"]: - result.append(f'\t\t{value["name"]} = {value["value"]}, \\') + result.append(f"\t\t{value['name']} = {value['value']}, \\") result.append("\t}; \\") result.append("\t \\") @@ -1831,7 +1831,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us else: method_signature += "void " - method_signature += f'{method["name"]}(' + method_signature += f"{method['name']}(" method_arguments = [] if "arguments" in method: @@ -1850,7 +1850,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us method_body += "return " if "alias_for" in class_api and return_type.startswith(class_api["alias_for"] + "::"): method_body += f"({return_type})" - method_body += f'ClassDBSingleton::get_singleton()->{method["name"]}(' + method_body += f"ClassDBSingleton::get_singleton()->{method['name']}(" method_body += ", ".join(map(lambda x: escape_argument(x["name"]), method_arguments)) if vararg: method_body += ", p_args..." @@ -1866,9 +1866,9 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us if "enums" in class_api: for enum_api in class_api["enums"]: if enum_api["is_bitfield"]: - result.append(f'\tVARIANT_BITFIELD_CAST({class_api["alias_for"]}::{enum_api["name"]}); \\') + result.append(f"\tVARIANT_BITFIELD_CAST({class_api['alias_for']}::{enum_api['name']}); \\") else: - result.append(f'\tVARIANT_ENUM_CAST({class_api["alias_for"]}::{enum_api["name"]}); \\') + result.append(f"\tVARIANT_ENUM_CAST({class_api['alias_for']}::{enum_api['name']}); \\") result.append("\t") result.append("") @@ -1965,7 +1965,7 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us if has_return: result.append( - f'\tCHECK_METHOD_BIND_RET(_gde_method_bind, ({get_default_value_for_type(method["return_value"]["type"])}));' + f"\tCHECK_METHOD_BIND_RET(_gde_method_bind, ({get_default_value_for_type(method['return_value']['type'])}));" ) else: result.append("\tCHECK_METHOD_BIND(_gde_method_bind);") @@ -2047,7 +2047,7 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us method_signature += " {" if "return_value" in method and correct_type(method["return_value"]["type"]) != "void": result.append(method_signature) - result.append(f'\treturn {get_default_value_for_type(method["return_value"]["type"])};') + result.append(f"\treturn {get_default_value_for_type(method['return_value']['type'])};") result.append("}") else: method_signature += "}" @@ -2083,7 +2083,7 @@ def generate_global_constants(api, output_dir): if len(api["global_constants"]) > 0: for constant in api["global_constants"]: - header.append(f'const int64_t {escape_identifier(constant["name"])} = {constant["value"]};') + header.append(f"const int64_t {escape_identifier(constant['name'])} = {constant['value']};") header.append("") @@ -2092,12 +2092,12 @@ def generate_global_constants(api, output_dir): continue if enum_def["is_bitfield"]: - header.append(f'enum {enum_def["name"]} : uint64_t {{') + header.append(f"enum {enum_def['name']} : uint64_t {{") else: - header.append(f'enum {enum_def["name"]} {{') + header.append(f"enum {enum_def['name']} {{") for value in enum_def["values"]: - header.append(f'\t{value["name"]} = {value["value"]},') + header.append(f"\t{value['name']} = {value['value']},") header.append("};") header.append("") @@ -2125,8 +2125,8 @@ def generate_version_header(api, output_dir): header.append(f"#define GODOT_VERSION_MAJOR {api['header']['version_major']}") header.append(f"#define GODOT_VERSION_MINOR {api['header']['version_minor']}") header.append(f"#define GODOT_VERSION_PATCH {api['header']['version_patch']}") - header.append(f"#define GODOT_VERSION_STATUS \"{api['header']['version_status']}\"") - header.append(f"#define GODOT_VERSION_BUILD \"{api['header']['version_build']}\"") + header.append(f'#define GODOT_VERSION_STATUS "{api["header"]["version_status"]}"') + header.append(f'#define GODOT_VERSION_BUILD "{api["header"]["version_build"]}"') header.append("") @@ -2158,9 +2158,9 @@ def generate_global_constant_binds(api, output_dir): continue if enum_def["is_bitfield"]: - header.append(f'VARIANT_BITFIELD_CAST({enum_def["name"]});') + header.append(f"VARIANT_BITFIELD_CAST({enum_def['name']});") else: - header.append(f'VARIANT_ENUM_CAST({enum_def["name"]});') + header.append(f"VARIANT_ENUM_CAST({enum_def['name']});") # Variant::Type is not a global enum, but only one line, it is worth to place in this file instead of creating new file. header.append("VARIANT_ENUM_CAST(godot::Variant::Type);") @@ -2259,7 +2259,7 @@ def generate_utility_functions(api, output_dir): has_return = "return_type" in function and function["return_type"] != "void" if has_return: source.append( - f'\tCHECK_METHOD_BIND_RET(_gde_function, ({get_default_value_for_type(function["return_type"])}));' + f"\tCHECK_METHOD_BIND_RET(_gde_function, ({get_default_value_for_type(function['return_type'])}));" ) else: source.append("\tCHECK_METHOD_BIND(_gde_function);") @@ -2271,7 +2271,7 @@ def generate_utility_functions(api, output_dir): if function["return_type"] == "Object": function_call += "internal::_call_utility_ret_obj(_gde_function" else: - function_call += f'internal::_call_utility_ret<{get_gdextension_type(correct_type(function["return_type"]))}>(_gde_function' + function_call += f"internal::_call_utility_ret<{get_gdextension_type(correct_type(function['return_type']))}>(_gde_function" else: function_call += "internal::_call_utility_no_ret(_gde_function" @@ -2289,7 +2289,7 @@ def generate_utility_functions(api, output_dir): function_call += ", ".join(arguments) else: if has_return: - source.append(f'\t{get_gdextension_type(correct_type(function["return_type"]))} ret;') + source.append(f"\t{get_gdextension_type(correct_type(function['return_type']))} ret;") else: source.append("\tVariant ret;") function_call += "_gde_function(&ret, reinterpret_cast(p_args), p_arg_count" @@ -2483,7 +2483,7 @@ def make_varargs_template( if len(class_befor_signature) > 0: function_signature += class_befor_signature + "::" - function_signature += f'{escape_identifier(function_data["name"])}' + function_signature += f"{escape_identifier(function_data['name'])}" method_arguments = [] if "arguments" in function_data: @@ -2508,7 +2508,7 @@ def make_varargs_template( if argument["type"] == "Variant": args_array += escape_argument(argument["name"]) else: - args_array += f'Variant({escape_argument(argument["name"])})' + args_array += f"Variant({escape_argument(argument['name'])})" args_array += ", " args_array += "Variant(p_args)... };" @@ -2524,7 +2524,7 @@ def make_varargs_template( if return_type != "void": call_line += "return " - call_line += f'{escape_identifier(function_data["name"])}_internal(call_args.data(), variant_args.size());' + call_line += f"{escape_identifier(function_data['name'])}_internal(call_args.data(), variant_args.size());" result.append(call_line) else: base = "(GDExtensionTypePtr)&opaque" @@ -2534,7 +2534,7 @@ def make_varargs_template( ret = "nullptr" if return_type != "void": ret = "&ret" - result.append(f'\t{correct_type(function_data["return_type"])} ret;') + result.append(f"\t{correct_type(function_data['return_type'])} ret;") function_name = function_data["name"] result.append( diff --git a/include/godot_cpp/classes/wrapped.hpp b/include/godot_cpp/classes/wrapped.hpp index 647d611b1..f54544bcc 100644 --- a/include/godot_cpp/classes/wrapped.hpp +++ b/include/godot_cpp/classes/wrapped.hpp @@ -188,7 +188,9 @@ private: friend class ::godot::Wrapped; \ \ protected: \ - virtual bool _is_extension_class() const override { return true; } \ + virtual bool _is_extension_class() const override { \ + return true; \ + } \ \ static const ::godot::StringName *_get_extension_class_name() { \ const ::godot::StringName &string_name = get_class_static(); \ @@ -200,35 +202,35 @@ protected: } \ \ static void (::godot::Wrapped::*_get_notification())(int) { \ - return (void(::godot::Wrapped::*)(int)) & m_class::_notification; \ + return (void (::godot::Wrapped::*)(int)) & m_class::_notification; \ } \ \ static bool (::godot::Wrapped::*_get_set())(const ::godot::StringName &p_name, const ::godot::Variant &p_property) { \ - return (bool(::godot::Wrapped::*)(const ::godot::StringName &p_name, const ::godot::Variant &p_property)) & m_class::_set; \ + return (bool (::godot::Wrapped::*)(const ::godot::StringName &p_name, const ::godot::Variant &p_property)) & m_class::_set; \ } \ \ static bool (::godot::Wrapped::*_get_get())(const ::godot::StringName &p_name, ::godot::Variant &r_ret) const { \ - return (bool(::godot::Wrapped::*)(const ::godot::StringName &p_name, ::godot::Variant &r_ret) const) & m_class::_get; \ + return (bool (::godot::Wrapped::*)(const ::godot::StringName &p_name, ::godot::Variant &r_ret) const) & m_class::_get; \ } \ \ static void (::godot::Wrapped::*_get_get_property_list())(::godot::List<::godot::PropertyInfo> * p_list) const { \ - return (void(::godot::Wrapped::*)(::godot::List<::godot::PropertyInfo> * p_list) const) & m_class::_get_property_list; \ + return (void (::godot::Wrapped::*)(::godot::List<::godot::PropertyInfo> * p_list) const) & m_class::_get_property_list; \ } \ \ static bool (::godot::Wrapped::*_get_property_can_revert())(const ::godot::StringName &p_name) const { \ - return (bool(::godot::Wrapped::*)(const ::godot::StringName &p_name) const) & m_class::_property_can_revert; \ + return (bool (::godot::Wrapped::*)(const ::godot::StringName &p_name) const) & m_class::_property_can_revert; \ } \ \ static bool (::godot::Wrapped::*_get_property_get_revert())(const ::godot::StringName &p_name, ::godot::Variant &) const { \ - return (bool(::godot::Wrapped::*)(const ::godot::StringName &p_name, ::godot::Variant &) const) & m_class::_property_get_revert; \ + return (bool (::godot::Wrapped::*)(const ::godot::StringName &p_name, ::godot::Variant &) const) & m_class::_property_get_revert; \ } \ \ static void (::godot::Wrapped::*_get_validate_property())(::godot::PropertyInfo & p_property) const { \ - return (void(::godot::Wrapped::*)(::godot::PropertyInfo & p_property) const) & m_class::_validate_property; \ + return (void (::godot::Wrapped::*)(::godot::PropertyInfo & p_property) const) & m_class::_validate_property; \ } \ \ static ::godot::String (::godot::Wrapped::*_get_to_string())() const { \ - return (::godot::String(::godot::Wrapped::*)() const) & m_class::_to_string; \ + return (::godot::String (::godot::Wrapped::*)() const) & m_class::_to_string; \ } \ \ template \ diff --git a/include/godot_cpp/core/method_bind.hpp b/include/godot_cpp/core/method_bind.hpp index 07d51be6e..ef5ab018d 100644 --- a/include/godot_cpp/core/method_bind.hpp +++ b/include/godot_cpp/core/method_bind.hpp @@ -149,8 +149,7 @@ class MethodBind { template class MethodBindVarArgBase : public MethodBind { protected: - R(T::*method) - (const Variant **, GDExtensionInt, GDExtensionCallError &); + R (T::*method)(const Variant **, GDExtensionInt, GDExtensionCallError &); std::vector arguments; public: @@ -434,8 +433,7 @@ template template #endif // TYPED_METHOD_BIND class MethodBindTR : public MethodBind { - R(MB_T::*method) - (P...); + R (MB_T::*method)(P...); protected: // GCC raises warnings in the case P = {} as the comparison is always false... @@ -517,8 +515,7 @@ template template #endif // TYPED_METHOD_BIND class MethodBindTRC : public MethodBind { - R(MB_T::*method) - (P...) const; + R (MB_T::*method)(P...) const; protected: // GCC raises warnings in the case P = {} as the comparison is always false... @@ -663,8 +660,7 @@ MethodBind *create_static_method_bind(void (*p_method)(P...)) { template class MethodBindTRS : public MethodBind { - R(*function) - (P...); + R (*function)(P...); protected: // GCC raises warnings in the case P = {} as the comparison is always false... diff --git a/include/godot_cpp/variant/callable_method_pointer.hpp b/include/godot_cpp/variant/callable_method_pointer.hpp index e9aea09bc..876d1d806 100644 --- a/include/godot_cpp/variant/callable_method_pointer.hpp +++ b/include/godot_cpp/variant/callable_method_pointer.hpp @@ -104,8 +104,7 @@ template class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase { struct Data { T *instance; - R(T::*method) - (P...); + R (T::*method)(P...); } data; static_assert(sizeof(Data) % 4 == 0); @@ -146,8 +145,7 @@ template class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase { struct Data { T *instance; - R(T::*method) - (P...) const; + R (T::*method)(P...) const; } data; static_assert(sizeof(Data) % 4 == 0); @@ -227,8 +225,7 @@ Callable create_custom_callable_static_function_pointer(void (*p_method)(P...)) template class CallableCustomStaticMethodPointerRet : public CallableCustomMethodPointerBase { struct Data { - R(*method) - (P...); + R (*method)(P...); } data; static_assert(sizeof(Data) % 4 == 0); diff --git a/include/godot_cpp/variant/char_string.hpp b/include/godot_cpp/variant/char_string.hpp index b7b795b52..908dc3432 100644 --- a/include/godot_cpp/variant/char_string.hpp +++ b/include/godot_cpp/variant/char_string.hpp @@ -113,7 +113,7 @@ class CharStringT { CharStringT &operator+=(T p_char); int64_t length() const { return size() ? size() - 1 : 0; } const T *get_data() const; - operator const T *() const { return get_data(); }; + operator const T *() const { return get_data(); } protected: void copy_from(const T *p_cstr); diff --git a/include/godot_cpp/variant/variant.hpp b/include/godot_cpp/variant/variant.hpp index 6a0264a3a..b1bb7b633 100644 --- a/include/godot_cpp/variant/variant.hpp +++ b/include/godot_cpp/variant/variant.hpp @@ -145,7 +145,7 @@ class Variant { static GDExtensionTypeFromVariantConstructorFunc to_type_constructor[VARIANT_MAX]; public: - _FORCE_INLINE_ GDExtensionVariantPtr _native_ptr() const { return const_cast(&opaque); } + _FORCE_INLINE_ GDExtensionVariantPtr _native_ptr() const { return const_cast(&opaque); } Variant(); Variant(std::nullptr_t n) : Variant() {} diff --git a/pyproject.toml b/pyproject.toml index 0e9c4b444..0a51b3b3d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,16 +5,16 @@ ignore_missing_imports = true namespace_packages = true no_implicit_optional = true pretty = true -scripts_are_modules = true show_column_numbers = true warn_redundant_casts = true warn_return_any = true warn_unreachable = true +python_version = "3.8" [tool.ruff] -extend-include = ["SConstruct"] +extend-include = ["*SConstruct"] line-length = 120 -target-version = "py37" +target-version = "py38" [tool.ruff.lint] extend-select = [ @@ -27,32 +27,32 @@ extend-select = [ ] [tool.codespell] -enable-colors = "" -write-changes = "" -check-hidden = "" +enable-colors = true +write-changes = true +check-hidden = true quiet-level = 3 -builtin = "clear,rare,en-GB_to_en-US" -ignore-words-list = """\ - breaked, - cancelled, - checkin, - curvelinear, - doubleclick, - expct, - findn, - gird, - hel, - inout, - labelin, - lod, - mis, - nd, - numer, - ot, - outin, - requestor, - te, - textin, - thirdparty, - vai -""" +builtin = ["clear", "rare", "en-GB_to_en-US"] +ignore-words-list = [ + "breaked", + "cancelled", + "checkin", + "curvelinear", + "doubleclick", + "expct", + "findn", + "gird", + "hel", + "inout", + "labelin", + "lod", + "mis", + "nd", + "numer", + "ot", + "outin", + "requestor", + "te", + "textin", + "thirdparty", + "vai", +] diff --git a/test/src/example.cpp b/test/src/example.cpp index f51c1c175..97915a0fd 100644 --- a/test/src/example.cpp +++ b/test/src/example.cpp @@ -161,7 +161,7 @@ bool Example::_property_can_revert(const StringName &p_name) const { } else { return false; } -}; +} bool Example::_property_get_revert(const StringName &p_name, Variant &r_property) const { if (p_name == StringName("property_from_list")) { @@ -170,7 +170,7 @@ bool Example::_property_get_revert(const StringName &p_name, Variant &r_property } else { return false; } -}; +} void Example::_validate_property(PropertyInfo &p_property) const { String name = p_property.name; diff --git a/test/src/example.h b/test/src/example.h index b40fcab16..22e9382bd 100644 --- a/test/src/example.h +++ b/test/src/example.h @@ -58,7 +58,7 @@ class ExampleMin : public Control { GDCLASS(ExampleMin, Control); protected: - static void _bind_methods(){}; + static void _bind_methods() {} }; class Example : public Control { From 2bd3d5314e8a09533a7a871f6a79131a631b3648 Mon Sep 17 00:00:00 2001 From: Thaddeus Crews Date: Sat, 26 Apr 2025 12:29:50 -0500 Subject: [PATCH 30/41] CI: Ensure utf-8 support on Windows GHA (cherry picked from commit 42f6dc6d49cf2a9607df1d2025e44814cea29c0b) --- .github/workflows/ci-scons.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci-scons.yml b/.github/workflows/ci-scons.yml index b951c29c0..96790bc9b 100644 --- a/.github/workflows/ci-scons.yml +++ b/.github/workflows/ci-scons.yml @@ -10,6 +10,8 @@ env: # Use UTF-8 on Linux. LANG: en_US.UTF-8 LC_ALL: en_US.UTF-8 + # Use UTF-8 on Windows. + PYTHONIOENCODING: utf8 concurrency: group: ci-scons-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }} From 2eb13f897134e843890b8d3f7e7386964675cc99 Mon Sep 17 00:00:00 2001 From: Dyllan Cole Date: Sat, 31 May 2025 19:23:50 -0400 Subject: [PATCH 31/41] Fix incorrect binding_generator_generate_bindings variable names (cherry picked from commit 4824aa41e82ac9de3a466c137f32d23b6fee7578) --- cmake/GodotCPPModule.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/GodotCPPModule.cmake b/cmake/GodotCPPModule.cmake index 00e00fe5e..67fc4dcee 100644 --- a/cmake/GodotCPPModule.cmake +++ b/cmake/GodotCPPModule.cmake @@ -86,9 +86,9 @@ missing. ]] function( binding_generator_generate_bindings API_FILE - USE_TEMPLATE_GET_NODE, - BITS, - PRECISION, + USE_TEMPLATE_GET_NODE + BITS + PRECISION OUTPUT_DIR ) # This code snippet will be squashed into a single line From ac2263f126387d106457702a877ca8ee90dde152 Mon Sep 17 00:00:00 2001 From: Tom Date: Wed, 16 Apr 2025 20:26:55 +0100 Subject: [PATCH 32/41] Fixed a crash with an Array constructor (cherry picked from commit ddd4f2513cad5b78b8a259f395d41a9fb5f7ae47) --- include/godot_cpp/variant/variant.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/godot_cpp/variant/variant.hpp b/include/godot_cpp/variant/variant.hpp index b1bb7b633..5d314a741 100644 --- a/include/godot_cpp/variant/variant.hpp +++ b/include/godot_cpp/variant/variant.hpp @@ -408,7 +408,8 @@ Array::ConstIterator Array::end() const { return Array::ConstIterator(ptr() + size()); } -Array::Array(std::initializer_list p_init) { +Array::Array(std::initializer_list p_init) : + Array() { ERR_FAIL_COND(resize(p_init.size()) != 0); size_t i = 0; From 0be68c870f1daa456fb20d4c7b47b32f68a80986 Mon Sep 17 00:00:00 2001 From: Lukas Tenbrink Date: Fri, 2 May 2025 17:12:32 +0200 Subject: [PATCH 33/41] Make ndk version configurable as a command-like argument. (cherry picked from commit 16e47d7ae5bc45af90caeab16beecfe9ec4802c5) --- tools/android.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/android.py b/tools/android.py index fee4ed255..dbd38cdfb 100644 --- a/tools/android.py +++ b/tools/android.py @@ -11,6 +11,11 @@ def options(opts): "Target Android API level", "21", ) + opts.Add( + "ndk_version", + "Fully qualified version of ndk to use for compilation.", + "23.2.8568313", + ) opts.Add( "ANDROID_HOME", "Path to your Android SDK installation. By default, uses ANDROID_HOME from your defined environment variables.", @@ -22,14 +27,9 @@ def exists(env): return get_android_ndk_root(env) is not None -# This must be kept in sync with the value in https://github.com/godotengine/godot/blob/master/platform/android/detect.py#L58. -def get_ndk_version(): - return "23.2.8568313" - - def get_android_ndk_root(env): if env["ANDROID_HOME"]: - return env["ANDROID_HOME"] + "/ndk/" + get_ndk_version() + return env["ANDROID_HOME"] + "/ndk/" + env["ndk_version"] else: return os.environ.get("ANDROID_NDK_ROOT") @@ -68,7 +68,7 @@ def generate(env): if not os.path.exists(toolchain): print("ERROR: Could not find NDK toolchain at " + toolchain + ".") - print("Make sure NDK version " + get_ndk_version() + " is installed.") + print("Make sure NDK version " + env["ndk_version"] + " is installed.") env.Exit(1) env.PrependENVPath("PATH", toolchain + "/bin") # This does nothing half of the time, but we'll put it here anyways From 980edc22a7137af275cf1caf4aa021524d5a2703 Mon Sep 17 00:00:00 2001 From: MJacred Date: Mon, 9 Jun 2025 11:49:03 +0200 Subject: [PATCH 34/41] Fix URL to gdextension cpp example in the official docs (cherry picked from commit f25c4df5c477f58d6839d6a63a3768540940862f) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ac267733e..0b572bb98 100644 --- a/README.md +++ b/README.md @@ -140,4 +140,4 @@ See the [godot-cpp-template](https://github.com/godotengine/godot-cpp-template) generic reusable template. Or checkout the code for the [Summator example](https://github.com/paddy-exe/GDExtensionSummator) -as shown in the [official documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/gdextension/gdextension_cpp_example.html). +as shown in the [official documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/cpp/gdextension_cpp_example.html). From eaeafdf596e7277f93df1300f62e68e79ad5a6b2 Mon Sep 17 00:00:00 2001 From: "marcin.mirski" Date: Wed, 4 Jun 2025 16:54:45 -0700 Subject: [PATCH 35/41] Fix: Add STATUS to CMake message commands missing them (cherry picked from commit 8eac097c372ab1931f43281498dcbe57abfcbf10) --- cmake/common_compiler_flags.cmake | 2 +- cmake/godotcpp.cmake | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/cmake/common_compiler_flags.cmake b/cmake/common_compiler_flags.cmake index 9d4894f13..8a9a41ccb 100644 --- a/cmake/common_compiler_flags.cmake +++ b/cmake/common_compiler_flags.cmake @@ -47,7 +47,7 @@ by default, we need to test for it. ]] function(compiler_detection) if(${CMAKE_CXX_COMPILER_ID} STREQUAL Clang) if(${CMAKE_CXX_COMPILER_FRONTEND_VARIANT} STREQUAL MSVC) - message("Using clang-cl") + message(STATUS "Using clang-cl") set(IS_CLANG "0" PARENT_SCOPE) set(IS_MSVC "1" PARENT_SCOPE) set(NOT_MSVC "0" PARENT_SCOPE) diff --git a/cmake/godotcpp.cmake b/cmake/godotcpp.cmake index b93280543..f0dbba620 100644 --- a/cmake/godotcpp.cmake +++ b/cmake/godotcpp.cmake @@ -29,7 +29,7 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/windows.cmake) # Detect number of processors include(ProcessorCount) ProcessorCount(PROC_MAX) -message("Auto-detected ${PROC_MAX} CPU cores available for build parallelism.") +message(STATUS "Auto-detected ${PROC_MAX} CPU cores available for build parallelism.") # List of known platforms set(PLATFORM_LIST @@ -197,15 +197,16 @@ function(godotcpp_generate) another compiler simulating the Visual C++ cl command-line syntax. ]] if(MSVC) math(EXPR PROC_N "(${PROC_MAX}-1) | (${X}-2)>>31 & 1") - message("Using ${PROC_N} cores for multi-threaded compilation.") + message(STATUS "Using ${PROC_N} cores for multi-threaded compilation.") # TODO You can override it at configure time with ...." ) else() message( + STATUS "Using ${CMAKE_BUILD_PARALLEL_LEVEL} cores, You can override" " it at configure time by using -j or --parallel on the build" " command." ) - message(" eg. cmake --build . -j 7 ...") + message(STATUS " eg. cmake --build . -j 7 ...") endif() #[[ GODOTCPP_SYMBOL_VISIBLITY @@ -245,8 +246,8 @@ function(godotcpp_generate) # Build Profile if(GODOTCPP_BUILD_PROFILE) message(STATUS "Using build profile to trim api file") - message("\tBUILD_PROFILE = '${GODOTCPP_BUILD_PROFILE}'") - message("\tAPI_SOURCE = '${GODOTCPP_GDEXTENSION_API_FILE}'") + message(STATUS "\tBUILD_PROFILE = '${GODOTCPP_BUILD_PROFILE}'") + message(STATUS "\tAPI_SOURCE = '${GODOTCPP_GDEXTENSION_API_FILE}'") build_profile_generate_trimmed_api( "${GODOTCPP_BUILD_PROFILE}" "${GODOTCPP_GDEXTENSION_API_FILE}" From bda8a0fbd66668dabf04f8897a2b48c571564d08 Mon Sep 17 00:00:00 2001 From: "marcin.mirski" Date: Thu, 5 Jun 2025 11:48:03 -0700 Subject: [PATCH 36/41] Improve CMAKE_BUILD_PARALLEL_LEVEL message (cherry picked from commit 0c2e66e41483ad73c32abd929c32ec34688bf462) --- cmake/godotcpp.cmake | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cmake/godotcpp.cmake b/cmake/godotcpp.cmake index f0dbba620..a0c544fc4 100644 --- a/cmake/godotcpp.cmake +++ b/cmake/godotcpp.cmake @@ -200,10 +200,15 @@ function(godotcpp_generate) message(STATUS "Using ${PROC_N} cores for multi-threaded compilation.") # TODO You can override it at configure time with ...." ) else() + if(CMAKE_BUILD_PARALLEL_LEVEL) + set(_cores "${CMAKE_BUILD_PARALLEL_LEVEL}") + else() + set(_cores "all") + endif() message( STATUS - "Using ${CMAKE_BUILD_PARALLEL_LEVEL} cores, You can override" - " it at configure time by using -j or --parallel on the build" + "Using ${_cores} cores. You can override" + " this at configure time by using -j or --parallel in the build" " command." ) message(STATUS " eg. cmake --build . -j 7 ...") From da3b350e85241a608ec83706e7f621974a269ede Mon Sep 17 00:00:00 2001 From: Tom Date: Sun, 20 Apr 2025 20:33:26 +0100 Subject: [PATCH 37/41] Cleaned up the MethodBind class (cherry picked from commit ca5af3c86153aaa91250d7608a9d29932b38afbf) --- include/godot_cpp/core/method_bind.hpp | 100 +++++++++++++------------ src/core/method_bind.cpp | 30 ++++---- 2 files changed, 67 insertions(+), 63 deletions(-) diff --git a/include/godot_cpp/core/method_bind.hpp b/include/godot_cpp/core/method_bind.hpp index ef5ab018d..6ed61fc39 100644 --- a/include/godot_cpp/core/method_bind.hpp +++ b/include/godot_cpp/core/method_bind.hpp @@ -47,14 +47,14 @@ namespace godot { class MethodBind { + uint32_t hint_flags = METHOD_FLAGS_DEFAULT; StringName name; StringName instance_class; int argument_count = 0; - uint32_t hint_flags = METHOD_FLAGS_DEFAULT; bool _static = false; - bool _is_const = false; - bool _has_return = false; + bool _const = false; + bool _returns = false; bool _vararg = false; std::vector argument_names; @@ -62,20 +62,20 @@ class MethodBind { std::vector default_arguments; protected: + void _set_const(bool p_const); + void _set_static(bool p_static); + void _set_returns(bool p_returns); + void _set_vararg(bool p_vararg); virtual GDExtensionVariantType gen_argument_type(int p_arg) const = 0; virtual PropertyInfo gen_argument_type_info(int p_arg) const = 0; - void generate_argument_types(int p_count); - void set_const(bool p_const); - void set_return(bool p_return); - void set_static(bool p_static); - void set_vararg(bool p_vararg); - void set_argument_count(int p_count); + void _generate_argument_types(int p_count); + + void set_argument_count(int p_count) { argument_count = p_count; } public: - StringName get_name() const; - void set_name(const StringName &p_name); - _FORCE_INLINE_ int get_default_argument_count() const { return (int)default_arguments.size(); } _FORCE_INLINE_ const std::vector &get_default_arguments() const { return default_arguments; } + _FORCE_INLINE_ int get_default_argument_count() const { return (int)default_arguments.size(); } + _FORCE_INLINE_ Variant has_default_argument(int p_arg) const { const int num_default_args = (int)(default_arguments.size()); const int idx = p_arg - (argument_count - num_default_args); @@ -96,19 +96,6 @@ class MethodBind { return default_arguments[idx]; } } - _FORCE_INLINE_ StringName get_instance_class() const { return instance_class; } - _FORCE_INLINE_ void set_instance_class(StringName p_class) { instance_class = p_class; } - - _FORCE_INLINE_ int get_argument_count() const { return argument_count; } - _FORCE_INLINE_ bool is_const() const { return _is_const; } - _FORCE_INLINE_ bool is_static() const { return _static; } - _FORCE_INLINE_ bool is_vararg() const { return _vararg; } - _FORCE_INLINE_ bool has_return() const { return _has_return; } - _FORCE_INLINE_ uint32_t get_hint_flags() const { return hint_flags | (is_const() ? GDEXTENSION_METHOD_FLAG_CONST : 0) | (is_vararg() ? GDEXTENSION_METHOD_FLAG_VARARG : 0) | (is_static() ? GDEXTENSION_METHOD_FLAG_STATIC : 0); } - _FORCE_INLINE_ void set_hint_flags(uint32_t p_hint_flags) { hint_flags = p_hint_flags; } - void set_argument_names(const std::vector &p_names); - std::vector get_argument_names() const; - void set_default_arguments(const std::vector &p_default_arguments) { default_arguments = p_default_arguments; } _FORCE_INLINE_ GDExtensionVariantType get_argument_type(int p_argument) const { ERR_FAIL_COND_V(p_argument < -1 || p_argument > argument_count, GDEXTENSION_VARIANT_TYPE_NIL); @@ -116,7 +103,6 @@ class MethodBind { } PropertyInfo get_argument_info(int p_argument) const; - virtual GDExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const = 0; std::vector get_arguments_info_list() const { std::vector vec; @@ -127,6 +113,31 @@ class MethodBind { } return vec; } + + void set_argument_names(const std::vector &p_names); + std::vector get_argument_names() const; + + virtual GDExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const = 0; + + _FORCE_INLINE_ void set_hint_flags(uint32_t p_hint_flags) { hint_flags = p_hint_flags; } + _FORCE_INLINE_ uint32_t get_hint_flags() const { return hint_flags | (is_const() ? GDEXTENSION_METHOD_FLAG_CONST : 0) | (is_vararg() ? GDEXTENSION_METHOD_FLAG_VARARG : 0) | (is_static() ? GDEXTENSION_METHOD_FLAG_STATIC : 0); } + _FORCE_INLINE_ StringName get_instance_class() const { return instance_class; } + _FORCE_INLINE_ void set_instance_class(StringName p_class) { instance_class = p_class; } + + _FORCE_INLINE_ int get_argument_count() const { return argument_count; } + + virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionCallError &r_error) const = 0; + virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_return) const = 0; + + StringName get_name() const; + void set_name(const StringName &p_name); + _FORCE_INLINE_ bool is_const() const { return _const; } + _FORCE_INLINE_ bool is_static() const { return _static; } + _FORCE_INLINE_ bool is_vararg() const { return _vararg; } + _FORCE_INLINE_ bool has_return() const { return _returns; } + + void set_default_arguments(const std::vector &p_default_arguments) { default_arguments = p_default_arguments; } + std::vector get_arguments_metadata_list() const { std::vector vec; // First element is return value @@ -137,9 +148,6 @@ class MethodBind { return vec; } - virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionCallError &r_error) const = 0; - virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_return) const = 0; - static void bind_call(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error); static void bind_ptrcall(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_return); @@ -180,8 +188,8 @@ class MethodBindVarArgBase : public MethodBind { const MethodInfo &p_method_info, bool p_return_nil_is_variant) : method(p_method) { - set_vararg(true); - set_const(true); + _set_vararg(true); + _set_const(true); set_argument_count(p_method_info.arguments.size()); if (p_method_info.arguments.size()) { arguments = p_method_info.arguments; @@ -194,8 +202,8 @@ class MethodBindVarArgBase : public MethodBind { set_argument_names(names); } - generate_argument_types((int)p_method_info.arguments.size()); - set_return(should_returns); + _generate_argument_types((int)p_method_info.arguments.size()); + _set_returns(should_returns); } ~MethodBindVarArgBase() {} @@ -332,7 +340,7 @@ class MethodBindT : public MethodBind { MethodBindT(void (MB_T::*p_method)(P...)) { method = p_method; - generate_argument_types(sizeof...(P)); + _generate_argument_types(sizeof...(P)); set_argument_count(sizeof...(P)); } }; @@ -408,9 +416,9 @@ class MethodBindTC : public MethodBind { MethodBindTC(void (MB_T::*p_method)(P...) const) { method = p_method; - generate_argument_types(sizeof...(P)); + _generate_argument_types(sizeof...(P)); set_argument_count(sizeof...(P)); - set_const(true); + _set_const(true); } }; @@ -490,9 +498,9 @@ class MethodBindTR : public MethodBind { MethodBindTR(R (MB_T::*p_method)(P...)) { method = p_method; - generate_argument_types(sizeof...(P)); + _generate_argument_types(sizeof...(P)); set_argument_count(sizeof...(P)); - set_return(true); + _set_returns(true); } }; @@ -572,10 +580,10 @@ class MethodBindTRC : public MethodBind { MethodBindTRC(R (MB_T::*p_method)(P...) const) { method = p_method; - generate_argument_types(sizeof...(P)); + _generate_argument_types(sizeof...(P)); set_argument_count(sizeof...(P)); - set_return(true); - set_const(true); + _set_returns(true); + _set_const(true); } }; @@ -644,9 +652,9 @@ class MethodBindTS : public MethodBind { MethodBindTS(void (*p_function)(P...)) { function = p_function; - generate_argument_types(sizeof...(P)); + _generate_argument_types(sizeof...(P)); set_argument_count(sizeof...(P)); - set_static(true); + _set_static(true); } }; @@ -712,10 +720,10 @@ class MethodBindTRS : public MethodBind { MethodBindTRS(R (*p_function)(P...)) { function = p_function; - generate_argument_types(sizeof...(P)); + _generate_argument_types(sizeof...(P)); set_argument_count(sizeof...(P)); - set_static(true); - set_return(true); + _set_static(true); + _set_returns(true); } }; diff --git a/src/core/method_bind.cpp b/src/core/method_bind.cpp index 0b9b5ebac..734b2e692 100644 --- a/src/core/method_bind.cpp +++ b/src/core/method_bind.cpp @@ -32,32 +32,28 @@ namespace godot { -StringName MethodBind::get_name() const { - return name; +void MethodBind::_set_const(bool p_const) { + _const = p_const; } -void MethodBind::set_name(const StringName &p_name) { - name = p_name; -} - -void MethodBind::set_argument_count(int p_count) { - argument_count = p_count; +void MethodBind::_set_static(bool p_static) { + _static = p_static; } -void MethodBind::set_const(bool p_const) { - _is_const = p_const; +void MethodBind::_set_returns(bool p_returns) { + _returns = p_returns; } -void MethodBind::set_return(bool p_return) { - _has_return = p_return; +void MethodBind::_set_vararg(bool p_vararg) { + _vararg = p_vararg; } -void MethodBind::set_static(bool p_static) { - _static = p_static; +StringName MethodBind::get_name() const { + return name; } -void MethodBind::set_vararg(bool p_vararg) { - _vararg = p_vararg; +void MethodBind::set_name(const StringName &p_name) { + name = p_name; } void MethodBind::set_argument_names(const std::vector &p_names) { @@ -68,7 +64,7 @@ std::vector MethodBind::get_argument_names() const { return argument_names; } -void MethodBind::generate_argument_types(int p_count) { +void MethodBind::_generate_argument_types(int p_count) { set_argument_count(p_count); if (argument_types != nullptr) { From 4f2f319fb23e67e9741698629bfa8180ccc2aba0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pa=CC=84vels=20Nadtoc=CC=8Cajevs?= <7645683+bruvzg@users.noreply.github.com> Date: Wed, 18 Jun 2025 13:18:37 +0300 Subject: [PATCH 38/41] Fix binding generation for TypedArray/TypedDictionary with refcounted elements. (cherry picked from commit ed53a70e719ec066240207132f1281910c2e4b8d) --- binding_generator.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/binding_generator.py b/binding_generator.py index 144ff75d1..4032cba3f 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -2755,9 +2755,22 @@ def correct_type(type_name, meta=None, use_alias=True): if type_name in type_conversion: return type_conversion[type_name] if type_name.startswith("typedarray::"): - return type_name.replace("typedarray::", "TypedArray<") + ">" + arr_type_name = type_name.replace("typedarray::", "") + if is_refcounted(arr_type_name): + arr_type_name = "Ref<" + arr_type_name + ">" + return "TypedArray<" + arr_type_name + ">" if type_name.startswith("typeddictionary::"): - return type_name.replace("typeddictionary::", "TypedDictionary<").replace(";", ", ") + ">" + dict_type_name = type_name.replace("typeddictionary::", "") + dict_type_names = dict_type_name.split(";") + if is_refcounted(dict_type_names[0]): + key_name = "Ref<" + dict_type_names[0] + ">" + else: + key_name = dict_type_names[0] + if is_refcounted(dict_type_names[1]): + val_name = "Ref<" + dict_type_names[1] + ">" + else: + val_name = dict_type_names[1] + return "TypedDictionary<" + key_name + ", " + val_name + ">" if is_enum(type_name): if is_bitfield(type_name): base_class = get_enum_class(type_name) From 63716910092eb14546fd612a15e1bec490d41aa6 Mon Sep 17 00:00:00 2001 From: Samuel Nicholas Date: Thu, 19 Jun 2025 10:24:48 +0930 Subject: [PATCH 39/41] added missing include .hpp and .inc detection removed redundant .py detection. (cherry picked from commit 6d11a780bf6478debb37569a7243a8d325809ea3) --- .github/workflows/runner.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/runner.yml b/.github/workflows/runner.yml index d056236ab..62f9327d9 100644 --- a/.github/workflows/runner.yml +++ b/.github/workflows/runner.yml @@ -34,13 +34,14 @@ jobs: - '.github/workflows/*.yml' - '**/*.py' - '**/*.cpp' + - '**/*.hpp' - '**/*.h' + - '**/*.inc' - 'test/build_profile.json' - 'gdextension/extension_api.json' scons: - '**/SConstruct' - '**/SCsub' - - '**/*.py' cmake: - '**/CMakeLists.txt' - '**/*.cmake' From 022ce432b84eb23008a65c4d4b1f7e354a38ab68 Mon Sep 17 00:00:00 2001 From: David Snopek Date: Fri, 20 Jun 2025 12:23:49 -0500 Subject: [PATCH 40/41] Disable double precisions builds in CI (cherry picked from commit b46c31a50e43e357a9316010eb83276aac82491f) --- .github/workflows/ci-cmake.yml | 9 --------- .github/workflows/ci-scons.yml | 9 --------- 2 files changed, 18 deletions(-) diff --git a/.github/workflows/ci-cmake.yml b/.github/workflows/ci-cmake.yml index 713cf6a68..26a99508a 100644 --- a/.github/workflows/ci-cmake.yml +++ b/.github/workflows/ci-cmake.yml @@ -40,15 +40,6 @@ jobs: artifact-path: cmake-build/bin/libgodot-cpp.linux.template_release.x86_64.a run-tests: true - - name: 🐧 Linux (GCC, Makefiles, Double Precision) - os: ubuntu-22.04 - platform: linux - config-flags: -DCMAKE_BUILD_TYPE=Release -DGODOTCPP_PRECISION=double - artifact-name: godot-cpp-linux-glibc2.27-x86_64-double-release.cmake - artifact-path: cmake-build/bin/libgodot-cpp.linux.template_release.double.x86_64.a - flags: precision=double - run-tests: false - - name: 🏁 Windows (x86_64, MSVC) os: windows-2019 platform: windows diff --git a/.github/workflows/ci-scons.yml b/.github/workflows/ci-scons.yml index 96790bc9b..ce81df930 100644 --- a/.github/workflows/ci-scons.yml +++ b/.github/workflows/ci-scons.yml @@ -33,15 +33,6 @@ jobs: run-tests: true cache-name: linux-x86_64 - - name: 🐧 Linux (GCC, Double Precision) - os: ubuntu-22.04 - platform: linux - artifact-name: godot-cpp-linux-glibc2.27-x86_64-double-release - artifact-path: bin/libgodot-cpp.linux.template_release.double.x86_64.a - flags: precision=double - run-tests: false - cache-name: linux-x86_64-f64 - - name: 🏁 Windows (x86_64, MSVC) os: windows-2019 platform: windows From 2f0dbc7bba6fdc36f76d464309dcee067a118c41 Mon Sep 17 00:00:00 2001 From: David Snopek Date: Tue, 24 Jun 2025 14:47:40 -0500 Subject: [PATCH 41/41] Update CI to use `windows-2022` (cherry picked from commit 8938e7e4e3bdcc12c25dc5e542e65880c73d9369) --- .github/workflows/ci-cmake.yml | 4 ++-- .github/workflows/ci-scons.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-cmake.yml b/.github/workflows/ci-cmake.yml index 26a99508a..7d5e77315 100644 --- a/.github/workflows/ci-cmake.yml +++ b/.github/workflows/ci-cmake.yml @@ -41,7 +41,7 @@ jobs: run-tests: true - name: 🏁 Windows (x86_64, MSVC) - os: windows-2019 + os: windows-2022 platform: windows compiler: msvc build-flags: --config Release @@ -50,7 +50,7 @@ jobs: run-tests: false - name: 🏁 Windows (x86_64, MinGW, Ninja) - os: windows-2019 + os: windows-2022 platform: windows compiler: mingw config-flags: diff --git a/.github/workflows/ci-scons.yml b/.github/workflows/ci-scons.yml index ce81df930..37b4ce395 100644 --- a/.github/workflows/ci-scons.yml +++ b/.github/workflows/ci-scons.yml @@ -34,7 +34,7 @@ jobs: cache-name: linux-x86_64 - name: 🏁 Windows (x86_64, MSVC) - os: windows-2019 + os: windows-2022 platform: windows artifact-name: godot-cpp-windows-msvc2019-x86_64-release artifact-path: bin/libgodot-cpp.windows.template_release.x86_64.lib @@ -42,7 +42,7 @@ jobs: cache-name: windows-x86_64-msvc - name: 🏁 Windows (x86_64, MinGW) - os: windows-2019 + os: windows-2022 platform: windows artifact-name: godot-cpp-linux-mingw-x86_64-release artifact-path: bin/libgodot-cpp.windows.template_release.x86_64.a