diff --git a/binding_generator.py b/binding_generator.py index e7609b2c..480cdef3 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -542,8 +542,14 @@ def generate_builtin_bindings(api, output_dir, build_config): builtin_header.append("") + includes = [] for builtin in builtin_classes: - builtin_header.append(f"#include ") + includes.append(f"godot_cpp/variant/{camel_to_snake(builtin)}.hpp") + + includes.sort() + + for include in includes: + builtin_header.append(f"#include <{include}>") builtin_header.append("") @@ -599,11 +605,10 @@ def generate_builtin_class_vararg_method_implements_header(builtin_classes): continue result += make_varargs_template( - method, "is_static" in method and method["is_static"], class_name, False, False, True + method, "is_static" in method and method["is_static"], class_name, False, True ) result.append("") - result.append("") result.append(f"#endif // ! {header_guard}") return "\n".join(result) @@ -628,38 +633,53 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl # Special cases. if class_name == "String": + result.append("#include ") result.append("#include ") result.append("#include ") - result.append("#include ") + result.append("") if class_name == "PackedStringArray": result.append("#include ") + result.append("") if class_name == "PackedColorArray": result.append("#include ") + result.append("") if class_name == "PackedVector2Array": result.append("#include ") + result.append("") if class_name == "PackedVector3Array": result.append("#include ") + result.append("") if class_name == "PackedVector4Array": result.append("#include ") + result.append("") if is_packed_array(class_name): result.append("#include ") result.append("#include ") + result.append("") if class_name == "Array": result.append("#include ") + result.append("") if class_name == "Callable": result.append("#include ") - - for include in fully_used_classes: - if include == "TypedArray": - result.append("#include ") - else: - result.append(f"#include ") + result.append("") if len(fully_used_classes) > 0: + includes = [] + for include in fully_used_classes: + if include == "TypedArray": + includes.append("godot_cpp/variant/typed_array.hpp") + else: + includes.append(f"godot_cpp/{get_include_path(include)}") + + includes.sort() + + for include in includes: + result.append(f"#include <{include}>") + result.append("") result.append("#include ") @@ -737,7 +757,7 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl result.append("public:") result.append( - f"\t_FORCE_INLINE_ GDExtensionTypePtr _native_ptr() const {{ return const_cast(&opaque); }}" + f"\t_FORCE_INLINE_ GDExtensionTypePtr _native_ptr() const {{ return const_cast(&opaque); }}" ) copy_constructor_index = -1 @@ -918,7 +938,7 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl result.append(f"\tconst {return_type} *ptr() const;") result.append(f"\t{return_type} *ptrw();") iterators = """ - struct Iterator { + struct Iterator { _FORCE_INLINE_ $TYPE &operator*() const { return *elem_ptr; } @@ -980,19 +1000,17 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl } _FORCE_INLINE_ ConstIterator end() const { return ConstIterator(ptr() + size()); - } -""" + }""" result.append(iterators.replace("$TYPE", return_type)) init_list = """ - _FORCE_INLINE_ $CLASS(std::initializer_list<$TYPE> p_init) { + _FORCE_INLINE_ $CLASS(std::initializer_list<$TYPE> p_init) { ERR_FAIL_COND(resize(p_init.size()) != 0); size_t i = 0; for (const $TYPE &element : p_init) { set(i++, element); } - } -""" + }""" result.append(init_list.replace("$TYPE", return_type).replace("$CLASS", class_name)) if class_name == "Array": @@ -1031,7 +1049,9 @@ 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) @@ -1045,7 +1065,6 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl add_header(f"{snake_class_name}.cpp", result) - result.append("") result.append(f"#include ") result.append("") result.append("#include ") @@ -1054,10 +1073,16 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl result.append("") # Only used since the "fully used" is included in header already. - for include in used_classes: - result.append(f"#include ") - if len(used_classes) > 0: + includes = [] + for included in used_classes: + includes.append(f"godot_cpp/{get_include_path(included)}") + + includes.sort() + + for included in includes: + result.append(f"#include <{included}>") + result.append("") result.append("#include ") @@ -1307,7 +1332,7 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl f'{correct_type(operator["return_type"])} {class_name}::operator{operator["name"].replace("unary", "")}() 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("") @@ -1343,6 +1368,7 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl result.append("") result.append("} //namespace godot") + result.append("") return "\n".join(result) @@ -1518,11 +1544,18 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node): result.append("") - for included in used_classes: - result.append(f"#include ") + if len(used_classes) > 0: + includes = [] + for included in used_classes: + includes.append(f"godot_cpp/{get_include_path(included)}") - if len(used_classes) == 0: + includes.sort() + + for include in includes: + result.append(f"#include <{include}>") + else: result.append("#include ") + result.append("") result.append("namespace godot {") @@ -1562,16 +1595,23 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us result.append("") - for included in fully_used_classes: - if included == "TypedArray": - result.append("#include ") - else: - result.append(f"#include ") + if len(fully_used_classes) > 0: + includes = [] + for included in fully_used_classes: + if included == "TypedArray": + includes.append("godot_cpp/variant/typed_array.hpp") + else: + includes.append(f"godot_cpp/{get_include_path(included)}") + + includes.sort() + + for include in includes: + result.append(f"#include <{include}>") + + result.append("") if class_name == "EditorPlugin": result.append("#include ") - - if len(fully_used_classes) > 0: result.append("") if class_name != "Object" and class_name != "ClassDBSingleton": @@ -1610,7 +1650,6 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us result.append("") result.append("public:") - result.append("") if "enums" in class_api: for enum_api in class_api["enums"]: @@ -1643,6 +1682,10 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us vararg = "is_vararg" in method and method["is_vararg"] + if vararg: + result.append("") + result.append("private:") + method_signature = "\t" method_signature += make_signature( class_name, method, for_header=True, use_template_get_node=use_template_get_node @@ -1650,6 +1693,8 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us result.append(method_signature + ";") if vararg: + result.append("") + result.append("public:") # Add templated version. result += make_varargs_template(method) @@ -1664,6 +1709,8 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us ) result.append(method_signature + ";") + result.append("") + result.append("protected:") # T is the custom class we want to register (from which the call initiates, going up the inheritance chain), # B is its base class (can be a custom class too, that's why we pass it). @@ -1680,7 +1727,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us # If the method is different from the base class, it means T overrides it, so it needs to be bound. # Note that with an `if constexpr`, the code inside the `if` will not even be compiled if the # condition returns false (in such cases it can't compile due to ambiguity). - f"\t\tif constexpr (!std::is_same_v) {{" + f"\t\tif constexpr (!std::is_same_v) {{" ) result.append(f"\t\t\tBIND_VIRTUAL_METHOD(T, {method_name});") result.append("\t\t}") @@ -1708,7 +1755,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us if class_name == "WorkerThreadPool": result.append("\tenum {") - result.append("\tINVALID_TASK_ID = -1") + result.append("\t\tINVALID_TASK_ID = -1") result.append("\t};") result.append("\ttypedef int64_t TaskID;") result.append("\ttypedef int64_t GroupID;") @@ -1720,8 +1767,6 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us ) if class_name == "Object": - result.append("") - result.append("\ttemplate ") result.append("\tstatic T *cast_to(Object *p_object);") @@ -1736,7 +1781,6 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us "\tT *get_node(const NodePath &p_path) const { return Object::cast_to(get_node_internal(p_path)); }" ) - result.append("") result.append("};") result.append("") @@ -1820,7 +1864,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us result.append(method_body) result.append("\t} \\") - result.append("\t;") + result.append("\t") result.append("") result.append("#define CLASSDB_SINGLETON_VARIANT_CAST \\") @@ -1832,10 +1876,11 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us else: result.append(f'\tVARIANT_ENUM_CAST({class_api["alias_for"]}::{enum_api["name"]}); \\') - result.append("\t;") + result.append("\t") result.append("") result.append(f"#endif // ! {header_guard}") + result.append("") return "\n".join(result) @@ -1857,10 +1902,16 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us result.append("#include ") result.append("") - for included in used_classes: - result.append(f"#include ") - if len(used_classes) > 0: + includes = [] + for included in used_classes: + includes.append(f"godot_cpp/{get_include_path(included)}") + + includes.sort() + + for included in includes: + result.append(f"#include <{included}>") + result.append("") result.append("namespace godot {") @@ -2010,8 +2061,8 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us result.append(method_signature) result.append("") + result.append("} // namespace godot") result.append("") - result.append("} // namespace godot ") return "\n".join(result) @@ -2039,23 +2090,24 @@ def generate_global_constants(api, output_dir): header.append("namespace godot {") header.append("") - for constant in api["global_constants"]: - header.append(f'\tconst int64_t {escape_identifier(constant["name"])} = {constant["value"]};') + 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("") + header.append("") for enum_def in api["global_enums"]: if enum_def["name"].startswith("Variant."): continue if enum_def["is_bitfield"]: - header.append(f'\tenum {enum_def["name"]} : uint64_t {{') + header.append(f'enum {enum_def["name"]} : uint64_t {{') else: - header.append(f'\tenum {enum_def["name"]} {{') + header.append(f'enum {enum_def["name"]} {{') for value in enum_def["values"]: - header.append(f'\t\t{value["name"]} = {value["value"]},') - header.append("\t};") + header.append(f'\t{value["name"]} = {value["value"]},') + header.append("};") header.append("") header.append("} // namespace godot") @@ -2174,11 +2226,17 @@ def generate_utility_functions(api, output_dir): vararg = "is_vararg" in function and function["is_vararg"] + if vararg: + header.append("") + header.append("private:") + function_signature = "\t" function_signature += make_signature("UtilityFunctions", function, for_header=True, static=True) header.append(function_signature + ";") if vararg: + header.append("") + header.append("public:") # Add templated version. header += make_varargs_template(function, static=True) @@ -2199,8 +2257,8 @@ def generate_utility_functions(api, output_dir): source.append("#include ") source.append("") - source.append("#include ") source.append("#include ") + source.append("#include ") source.append("") source.append("namespace godot {") source.append("") @@ -2302,7 +2360,7 @@ def make_function_parameters(parameters, include_default=False, for_builtin=Fals signature.append(parameter) if is_vararg: - signature.append("const Args&... p_args") + signature.append("const Args &...p_args") return ", ".join(signature) @@ -2360,9 +2418,6 @@ def make_signature( if "is_virtual" in function_data and function_data["is_virtual"]: function_signature += "virtual " - if is_vararg: - function_signature += "private: " - if static: function_signature += "static " @@ -2415,7 +2470,6 @@ def make_varargs_template( function_data, static=False, class_befor_signature="", - with_public_declare=True, with_indent=True, for_builtin_classes=False, ): @@ -2423,10 +2477,7 @@ def make_varargs_template( function_signature = "" - if with_public_declare: - function_signature = "public: " - - function_signature += "template " + result.append("template ") if static: function_signature += "static " @@ -2469,7 +2520,7 @@ def make_varargs_template( function_signature += " {" result.append(function_signature) - args_array = f"\tstd::array variant_args {{ " + args_array = f"\tstd::array variant_args{{ " for argument in method_arguments: if argument["type"] == "Variant": args_array += escape_argument(argument["name"])