From 6fcc184587094056f74e777abc8ffd5ee30a73c4 Mon Sep 17 00:00:00 2001 From: Thaddeus Crews Date: Fri, 7 Mar 2025 17:52:09 -0600 Subject: [PATCH 01/40] 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 1efc5b4e..9697687f 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -51,11 +51,7 @@ virtual $RETVAL _##m_name($FUNCARGS) $CONST override; \\ 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 c99c4220..63a6b75f 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: + header_start = -1 + header_end = -1 + + with open(file.strip(), "rt", encoding="utf-8", newline="\n") as f: lines = f.readlines() - if len(lines) <= HEADER_BEGIN_OFFSET: - continue # Most likely a dummy file. + for idx, line in enumerate(lines): + sline = line.strip() - if lines[HEADER_CHECK_OFFSET].startswith("#import"): - continue # Early catch obj-c file. + if header_start < 0: + if sline == "": # Skip empty lines at the top. + continue - name = f"GODOT_{Path(file).name}".upper().replace(".", "_").replace("-", "_").replace(" ", "_") + 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 - HEADER_CHECK = f"#ifndef {name}\n" - HEADER_BEGIN = f"#define {name}\n" - HEADER_END = f"#endif // {name}\n" - - if ( - lines[HEADER_CHECK_OFFSET] == HEADER_CHECK - and lines[HEADER_BEGIN_OFFSET] == HEADER_BEGIN - and lines[HEADER_END_OFFSET] == HEADER_END - ): + if (HEADER_CHECK_OFFSET := header_end) < 0 or HEADER_CHECK_OFFSET >= len(lines): + invalid.append(file) + continue + + if lines[HEADER_CHECK_OFFSET].startswith("#pragma once"): + continue + + # Might be using legacy header guards. + HEADER_BEGIN_OFFSET = HEADER_CHECK_OFFSET + 1 + HEADER_END_OFFSET = len(lines) - 1 + + 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 - break - elif line.startswith("#import"): - objc = True + # Verify `#pragma once` doesn't exist at invalid location. + misplaced = False + for line in lines: + if line.startswith("#pragma once"): + misplaced = True break - if objc: + if misplaced: + invalid.append(file) 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) - 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 02/40] 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 7870bfc7..366008a4 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 @@ public: }; } // 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 8511fe4c..8a5a9aa9 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 7a07dcb1..2b4a9035 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 @@ private: #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 26ed4ca3..6a877735 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 286051fa..cf5310e2 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 ca20c44f..1dcfebe3 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 07ce14d3..c5115aa9 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 555806b8..c8c80041 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 a27c2cb0..1337b0b7 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 1949360a..7da52109 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 1934ee45..4905ba89 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 f2da66ce..07d51be6 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 8889e821..8c84dbc7 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 aa81d4dc..4d0029a9 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 @@ public: #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 917ec6cc..9eab6e5c 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 9f3bc96f..815622b9 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 @@ public: }; } // 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 61f4330c..69afaf07 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 dd71d48a..23da33e3 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 e131c510..59ad87e4 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 40693aa7..7659f8a9 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 @@ public: }; } // namespace godot - -#endif // GODOT_GODOT_HPP diff --git a/include/godot_cpp/templates/cowdata.hpp b/include/godot_cpp/templates/cowdata.hpp index dcb74ecc..68918f7a 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 59cd8e0b..67dfb4e7 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 @@ public: }; } // 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 1845a1bb..67ba443a 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 @@ public: }; } // namespace godot - -#endif // GODOT_HASH_SET_HPP diff --git a/include/godot_cpp/templates/hashfuncs.hpp b/include/godot_cpp/templates/hashfuncs.hpp index 40b10a9e..3fcedb69 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 fa596056..bbc818c7 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 @@ public: }; } // 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 c5481e48..7b684874 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 f8754130..5c064c1c 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 6ab71fd7..0ddb1983 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 @@ public: }; } // 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 69aa8d7f..f826896f 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 @@ public: }; } // 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 1dd4a393..6d27d402 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 @@ public: }; } // 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 98cb04b2..e6c29689 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 @@ public: #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 11a9db52..aa3374e8 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 @@ public: }; } // 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 f7a65f68..cdd1f258 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 @@ public: }; } // 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 7ce5c784..c2727dd9 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 @@ public: }; } // 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 530d545e..17c21bc5 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 @@ public: }; } // 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 cb20c6e9..190c1e00 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 @@ public: }; } // 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 aaa84f33..50593f30 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 926ccd39..b6fa3c03 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 @@ public: }; } // namespace godot - -#endif // GODOT_VMAP_HPP diff --git a/include/godot_cpp/templates/vset.hpp b/include/godot_cpp/templates/vset.hpp index ce21ba83..42167403 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 @@ public: }; } // namespace godot - -#endif // GODOT_VSET_HPP diff --git a/include/godot_cpp/variant/aabb.hpp b/include/godot_cpp/variant/aabb.hpp index 46eaca96..17048d60 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 3d948aab..f408aa72 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 4b7a6b44..6ede9ead 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 48a81422..1ab18bd3 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 @@ public: }; } // 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 f3d688b4..e9aea09b 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 991c0392..b7b795b5 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 066f7945..6b672be3 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 86f1a396..878a7d87 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 d7708e5d..e2c87832 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 d2184ca4..f2c440a2 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 cc715778..b7eb1f89 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 5cf23a35..33569add 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 14cbeb51..3a5e18e3 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 2c42aa7f..94c340a8 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 f83f0399..5135d555 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 2ad84ff3..b0c1d2e7 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 36bbcc97..9b735c59 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 deb5871a..ff78c516 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 f6b70523..0e4cda25 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 623810bb..637e12dd 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 8252f348..32004f01 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 bee40d5c..73a121a4 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 69d77265..f92d0209 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 d489b415..15bc3bde 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 ff95fa7a..1f5ff559 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 4325fe99..285feeaf 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 6e6ff399..b40fcab1 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 @@ protected: 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 5f124da7..d19fd01a 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 55835fc1..a2c39be0 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 03/40] 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 00000000..8c434111 --- /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 04/40] 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 | 76 +- 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 | 154 +- src/variant/color.cpp | 57 +- src/variant/plane.cpp | 6 +- src/variant/projection.cpp | 360 +- 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, 4801 insertions(+), 876 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 7da52109..44cc3014 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 17048d60..cac22196 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 6ede9ead..efe21cf6 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 00000000..f31e761f --- /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 6b672be3..71522c6c 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); } -static _FORCE_INLINE_ bool is_ascii_lower_case(char32_t c) { - return (c >= 'a' && c <= 'z'); +constexpr bool is_unicode_identifier_continue(char32_t p_char) { + BSEARCH_CHAR_RANGE(xid_continue); } -static _FORCE_INLINE_ bool is_digit(char32_t c) { - return (c >= '0' && c <= '9'); +constexpr bool is_unicode_upper_case(char32_t p_char) { + BSEARCH_CHAR_RANGE(uppercase_letter); } -static _FORCE_INLINE_ bool is_hex_digit(char32_t c) { - return (is_digit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); +constexpr bool is_unicode_lower_case(char32_t p_char) { + BSEARCH_CHAR_RANGE(lowercase_letter); } -static _FORCE_INLINE_ bool is_binary_digit(char32_t c) { - return (c == '0' || c == '1'); +constexpr bool is_unicode_letter(char32_t p_char) { + BSEARCH_CHAR_RANGE(unicode_letter); } -static _FORCE_INLINE_ bool is_ascii_char(char32_t c) { - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); +#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_ascii_alphanumeric_char(char32_t c) { - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); +constexpr bool is_ascii_lower_case(char32_t p_char) { + return (p_char >= 'a' && p_char <= 'z'); } -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_digit(char32_t p_char) { + return (p_char >= '0' && p_char <= '9'); } -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_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_control(char32_t p_char) { +constexpr bool is_binary_digit(char32_t p_char) { + return (p_char == '0' || p_char == '1'); +} + +constexpr bool is_ascii_alphabet_char(char32_t p_char) { + return (p_char >= 'a' && p_char <= 'z') || (p_char >= 'A' && p_char <= 'Z'); +} + +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 878a7d87..d3bbc725 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; + // 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)); - float sharedexp = 65408.000f; // Result of: ((pow2to9 - 1.0f) / pow2to9) * powf(2.0f, 31.0f - 15.0f) + // 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); - float cRed = MAX(0.0f, MIN(sharedexp, r)); - float cGreen = MAX(0.0f, MIN(sharedexp, g)); - float cBlue = MAX(0.0f, MIN(sharedexp, b)); + // Compute the maximum channel, no less than 1.0*2^-15 + const float MaxChannel = MAX(MAX(_r, _g), MAX(_b, kMinVal)); - float cMax = MAX(cRed, MAX(cGreen, cBlue)); + // 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; - float expp = MAX(-B - 1.0f, floor(Math::log(cMax) / (real_t)Math_LN2)) + 1.0f + B; + E.f = MaxChannel; + E.i += 0x07804000; // Add 15 to the exponent and 0x4000 to the mantissa + E.i &= 0x7F800000; // Zero the mantissa - float sMax = (float)floor((cMax / Math::pow(2.0f, expp - B - N)) + 0.5f); + // 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; - float exps = expp + 1.0f; + // Convert the Bias to the correct exponent in the upper 5 bits. + E.i <<= 4; + E.i += 0x10000000; - 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); + // 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 e2c87832..3a2c359c 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 f2c440a2..97ae7c81 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 b7eb1f89..e2283e6a 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 33569add..c93fe57e 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 3a5e18e3..a5e33404 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 94c340a8..0c593ede 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 5135d555..9170e568 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 b0c1d2e7..80392e39 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 32004f01..400bdeff 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 73a121a4..3278af9f 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 f92d0209..796daeca 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 15bc3bde..2901b366 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 1f5ff559..3348f611 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 285feeaf..1a7471af 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 ded17d2b..c0ac6389 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 d8a99191..67cbb3ac 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(); - - return m.is_equal_approx(identity); + 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)); } +// 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 4e3b870e..1fb5211a 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 caea516e..05aadcaa 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 ddedc93f..e983cd20 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]; - } - } - } + // 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; - /** Product of pivots, gives determinant when finished **/ - determinant *= pvt_val; - if (Math::is_zero_approx(determinant)) { - return; /** Matrix is singular (zero determinant). **/ - } + real_t wtmp[4][8]; + real_t m0, m1, m2, m3, s; + real_t *r0, *r1, *r2, *r3; - /** "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; - } - } +#define MAT(m, r, c) (m)[(c) * 4 + (r)] - /** "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; - } - } + r0 = wtmp[0]; + r1 = wtmp[1]; + r2 = wtmp[2]; + r3 = wtmp[3]; - /** Divide column by minus pivot value **/ - for (i = 0; i < 4; i++) { - if (i != k) { - columns[i][k] /= (-pvt_val); - } - } + 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; - /** 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]; - } - } - } + 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; - /** Divide row by pivot **/ - for (j = 0; j < 4; j++) { - if (j != k) { - columns[k][j] /= pvt_val; - } - } + 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; - /** Replace pivot by reciprocal (at last we can touch it). **/ - columns[k][k] = 1.0 / pvt_val; + 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; - } - } - - 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[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; + } + + /* 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 3dd7af54..af75cf45 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 62730a9d..7192a711 100644 --- a/src/variant/rect2.cpp +++ b/src/variant/rect2.cpp @@ -211,31 +211,31 @@ next4: 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 @@ next4: 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 @@ next4: } 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 3b2c0b09..b6b330bd 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 d71e9191..765bc62e 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 12201f1f..cb190db1 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 4baff3bb..d39cb7b4 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,6 +47,18 @@ Vector2i Vector2i::clampi(int32_t p_min, int32_t p_max) const { CLAMP(y, p_min, p_max)); } +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)); +} + int64_t Vector2i::length_squared() const { return x * (int64_t)x + y * (int64_t)y; } @@ -67,14 +67,6 @@ double Vector2i::length() const { return Math::sqrt((double)length_squared()); } -int64_t Vector2i::distance_squared_to(const Vector2i &p_to) const { - return (p_to - *this).length_squared(); -} - -double Vector2i::distance_to(const Vector2i &p_to) const { - return (p_to - *this).length(); -} - Vector2i Vector2i::operator+(const Vector2i &p_v) const { return Vector2i(x + p_v.x, y + p_v.y); } @@ -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 d2ad6a9f..fe42c189 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 7b25d897..a1e7213b 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 2f1bb592..9b58c940 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 b0e330ca..d138610d 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 05/40] 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 68918f7a..39ba5c8e 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 @@ private: 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 @@ public: 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 @@ public: 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; + 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 67dfb4e7..a0a8cada 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 @@ private: 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 @@ private: 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 @@ private: 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 @@ private: } // 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 @@ public: } 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 67ba443a..a4eb6854 100644 --- a/include/godot_cpp/templates/hash_set.hpp +++ b/include/godot_cpp/templates/hash_set.hpp @@ -75,19 +75,20 @@ private: 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 @@ private: 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 @@ private: 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 @@ private: } // 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 @@ private: distance = existing_probe_len; } - pos = (pos + 1) % capacity; + pos = fastmod(pos + 1, capacity_inv, capacity); distance++; } } @@ -236,7 +238,7 @@ public: } 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 @@ public: } 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 @@ public: 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 @@ public: 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 3fcedb69..566b8c71 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 bbc818c7..9291f5e4 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 @@ public: data->erase(this); } + void transfer_to_back(List *p_dst_list); + _FORCE_INLINE_ Element() {} }; @@ -223,7 +227,7 @@ private: 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 @@ private: 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 @@ public: /** * 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: } }; +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 7b684874..0ef322fb 100644 --- a/include/godot_cpp/templates/local_vector.hpp +++ b/include/godot_cpp/templates/local_vector.hpp @@ -58,21 +58,18 @@ public: 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 @@ public: 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 @@ public: _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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 5c064c1c..423a7099 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 0ddb1983..c0dc4bf3 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 @@ public: typedef KeyValue ValueType; struct Iterator { + friend class RBMap; + _FORCE_INLINE_ KeyValue &operator*() const { return E->key_value(); } @@ -110,11 +114,16 @@ public: 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 @@ public: 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 @@ private: 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 @@ public: _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 f826896f..612be911 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 @@ private: 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 @@ public: _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 e6c29689..42cdb244 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: } _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 @@ public: } }; -#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 aa3374e8..27a5c9d0 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 @@ public: } } 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 cdd1f258..4b4e3942 100644 --- a/include/godot_cpp/templates/self_list.hpp +++ b/include/godot_cpp/templates/self_list.hpp @@ -100,11 +100,74 @@ public: 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 @@ public: _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 c2727dd9..fe136585 100644 --- a/include/godot_cpp/templates/sort_array.hpp +++ b/include/godot_cpp/templates/sort_array.hpp @@ -78,8 +78,8 @@ public: } } - 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 @@ public: /* 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 @@ public: 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 @@ public: 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 @@ public: } } - 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 @@ public: 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 @@ public: } } - 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 @@ public: p_max_depth--; - int cut = partitioner( + int64_t cut = partitioner( p_first, p_last, median_of_3( @@ -219,7 +219,7 @@ public: } } - 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 @@ public: p_max_depth--; - int cut = partitioner( + int64_t cut = partitioner( p_first, p_last, median_of_3( @@ -248,10 +248,10 @@ public: 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 @@ public: 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 @@ public: } } - 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 @@ public: } } - 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 50593f30..51eb825d 100644 --- a/include/godot_cpp/templates/vector.hpp +++ b/include/godot_cpp/templates/vector.hpp @@ -68,6 +68,7 @@ private: 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 @@ public: 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 @@ public: 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 @@ public: } _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 b6fa3c03..ea043d9f 100644 --- a/include/godot_cpp/templates/vmap.hpp +++ b/include/godot_cpp/templates/vmap.hpp @@ -72,16 +72,16 @@ private: 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 @@ private: 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 @@ public: } 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 @@ public: } _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 42167403..13d6e996 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 @@ public: 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 06/40] [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 7f803821..33db862d 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 f88e47ff..541249cb 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 07/40] 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 c8c80041..3e4db062 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 8c84dbc7..820e59e9 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 08/40] 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 59ad87e4..e584aab3 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 09/40] 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 e2283e6a..42eb4166 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 e983cd20..d8e35d44 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 10/40] 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 89289d75..f01d75da 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 9e85d880..ae801987 100644 --- a/tools/linux.py +++ b/tools/linux.py @@ -5,6 +5,7 @@ from SCons.Variables import BoolVariable 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 11/40] 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 9697687f..b8256076 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 0e4cda25..683f480f 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 8fe8a733..4206b886 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 12/40] . (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 b8256076..c5b535c9 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 9b735c59..69afdaae 100644 --- a/include/godot_cpp/variant/typed_array.hpp +++ b/include/godot_cpp/variant/typed_array.hpp @@ -53,6 +53,8 @@ public: 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 @@ public: 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 683f480f..6a0264a3 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 13/40] 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 287fb238..008a6b4f 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 00000000..706c87b9 --- /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 5782b310..b951c29c 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 a2e4f91b..d056236a 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 a3d81322..868e8012 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 32dce3ec..4c2be6d8 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 8ae938bf..b9328054 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 00000000..d8251816 --- /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 14/40] 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 8a5a9aa9..541c5ce3 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 423a7099..15c7c356 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 ff78c516..122655a4 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 @@ public: _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 @@ public: _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 15/40] 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 00000000..b1c36967 --- /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 00000000..fa1a310e --- /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 00000000..1266fc06 --- /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 e786025a..89988fd3 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 df3dd70f..9b711dd6 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 00000000..15057856 --- /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 16/40] 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 008a6b4f..1be9293c 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 17/40] 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 c93fe57e..d0efa086 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 18/40] 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 6a877735..ba99aa38 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 c5115aa9..9395f201 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 -// To maintain compatibility an alias is defined outside the namespace. -// Consider it deprecated. -using real_t = godot::real_t; +#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) + +// 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 00000000..deaab87c --- /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 44cc3014..f7ebc0c0 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 00000000..73d86148 --- /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 4905ba89..917ccded 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 97ae7c81..c7572045 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 796daeca..034e6ca2 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 05aadcaa..9b72c7af 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 3646264b..b8af9345 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 19/40] 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 c5b535c9..a01389cb 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 20/40] 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 706c87b9..713cf6a6 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 21/40] 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 67cbb3ac..f0a0b649 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 22/40] 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 b8af9345..63df0ad5 100644 --- a/tools/godotcpp.py +++ b/tools/godotcpp.py @@ -2,6 +2,7 @@ import os 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 f66bce42..93ca89e6 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 23/40] 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 8a4d836f..9d4894f1 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 24/40] 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 a01389cb..15012f97 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 2b4a9035..647d611b 100644 --- a/include/godot_cpp/classes/wrapped.hpp +++ b/include/godot_cpp/classes/wrapped.hpp @@ -93,7 +93,7 @@ protected: 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 @@ public: 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 b69ad75a..5ade7171 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 25/40] 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 f6257b73..59ef6318 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 26/40] 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 843f7b34..ac267733 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 27/40] 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 25c17db3..4e2a45c2 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 28/40] CI: Various version bumps; sync with main repo (cherry picked from commit 64cdf089d98e524fba114f1757c0c41d255f0ed4) --- .clang-format | 241 ++++++++++-------- .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, 272 insertions(+), 231 deletions(-) diff --git a/.clang-format b/.clang-format index 1df6c35b..87731d9e 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 -# SpaceInEmptyBlock: false -# SpaceInEmptyParentheses: false -# SpacesBeforeTrailingComments: 1 -# SpacesInAngles: Never -# SpacesInConditionalStatement: false -# 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 -# SpacesInSquareBrackets: false # SpaceBeforeSquareBrackets: false -# BitFieldColonSpacing: Both +# SpaceInEmptyBlock: false +# SpacesBeforeTrailingComments: 1 +# SpacesInAngles: Never +# SpacesInContainerLiterals: true +SpacesInLineCommentPrefix: + 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 +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 f14ac7f1..0da03e8a 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 7354ba41..e370058f 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 8acea262..64d335b5 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 15012f97..144ff75d 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 647d611b..f54544bc 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 07d51be6..ef5ab018 100644 --- a/include/godot_cpp/core/method_bind.hpp +++ b/include/godot_cpp/core/method_bind.hpp @@ -149,8 +149,7 @@ public: 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 e9aea09b..876d1d80 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 b7b795b5..908dc343 100644 --- a/include/godot_cpp/variant/char_string.hpp +++ b/include/godot_cpp/variant/char_string.hpp @@ -113,7 +113,7 @@ public: 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 6a0264a3..b1bb7b63 100644 --- a/include/godot_cpp/variant/variant.hpp +++ b/include/godot_cpp/variant/variant.hpp @@ -145,7 +145,7 @@ private: 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 0e9c4b44..0a51b3b3 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 f51c1c17..97915a0f 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 b40fcab1..22e9382b 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 29/40] 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 b951c29c..96790bc9 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 30/40] 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 00e00fe5..67fc4dce 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 31/40] 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 b1bb7b63..5d314a74 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 32/40] 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 fee4ed25..dbd38cdf 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 33/40] 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 ac267733..0b572bb9 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 34/40] 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 9d4894f1..8a9a41cc 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 b9328054..f0dbba62 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 35/40] 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 f0dbba62..a0c544fc 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 36/40] Cleaned up the MethodBind class (cherry picked from commit ca5af3c86153aaa91250d7608a9d29932b38afbf) --- include/godot_cpp/core/method_bind.hpp | 100 +++++++++++++------------ src/core/method_bind.cpp | 38 +++++----- 2 files changed, 71 insertions(+), 67 deletions(-) diff --git a/include/godot_cpp/core/method_bind.hpp b/include/godot_cpp/core/method_bind.hpp index ef5ab018..6ed61fc3 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 @@ public: 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 @@ public: } 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 @@ public: } 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 0b9b5eba..734b2e69 100644 --- a/src/core/method_bind.cpp +++ b/src/core/method_bind.cpp @@ -32,6 +32,22 @@ namespace godot { +void MethodBind::_set_const(bool p_const) { + _const = p_const; +} + +void MethodBind::_set_static(bool p_static) { + _static = p_static; +} + +void MethodBind::_set_returns(bool p_returns) { + _returns = p_returns; +} + +void MethodBind::_set_vararg(bool p_vararg) { + _vararg = p_vararg; +} + StringName MethodBind::get_name() const { return name; } @@ -40,26 +56,6 @@ 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_const(bool p_const) { - _is_const = p_const; -} - -void MethodBind::set_return(bool p_return) { - _has_return = p_return; -} - -void MethodBind::set_static(bool p_static) { - _static = p_static; -} - -void MethodBind::set_vararg(bool p_vararg) { - _vararg = p_vararg; -} - void MethodBind::set_argument_names(const std::vector &p_names) { argument_names = 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 37/40] 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 144ff75d..4032cba3 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 38/40] 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 d056236a..62f9327d 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 39/40] 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 713cf6a6..26a99508 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 96790bc9..ce81df93 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 40/40] 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 26a99508..7d5e7731 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 ce81df93..37b4ce39 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