Thaddeus Crews 2024-01-19 14:48:49 +01:00 committed by GitHub
commit 90c719eee3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 134 additions and 111 deletions

View File

@ -4,9 +4,10 @@ import json
import re import re
import shutil import shutil
from pathlib import Path from pathlib import Path
from typing import Tuple, Set, Dict, List, Any
def generate_mod_version(argcount, const=False, returns=False): def generate_mod_version(argcount: int, const: bool = False, returns: bool = False) -> str:
s = """ s = """
#define MODBIND$VER($RETTYPE m_name$ARG) \\ #define MODBIND$VER($RETTYPE m_name$ARG) \\
virtual $RETVAL _##m_name($FUNCARGS) $CONST override; \\ virtual $RETVAL _##m_name($FUNCARGS) $CONST override; \\
@ -48,7 +49,7 @@ virtual $RETVAL _##m_name($FUNCARGS) $CONST override; \\
return s return s
def generate_wrappers(target): def generate_wrappers(target: Path) -> None:
max_versions = 12 max_versions = 12
txt = """ txt = """
@ -70,7 +71,7 @@ def generate_wrappers(target):
f.write(txt) f.write(txt)
def get_file_list(api_filepath, output_dir, headers=False, sources=False): def get_file_list(api_filepath: str, output_dir: str, headers: bool = False, sources: bool = False) -> List[str]:
api = {} api = {}
files = [] files = []
with open(api_filepath, encoding="utf-8") as api_file: with open(api_filepath, encoding="utf-8") as api_file:
@ -137,18 +138,18 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False):
return files return files
def print_file_list(api_filepath, output_dir, headers=False, sources=False): def print_file_list(api_filepath: str, output_dir: str, headers: bool = False, sources: bool = False) -> None:
print(*get_file_list(api_filepath, output_dir, headers, sources), sep=";", end=None) print(*get_file_list(api_filepath, output_dir, headers, sources), sep=";", end=None)
def scons_emit_files(target, source, env): def scons_emit_files(target: Any, source: Any, env: Any) -> Tuple[List[Any], Any]:
files = [env.File(f) for f in get_file_list(str(source[0]), target[0].abspath, True, True)] files = [env.File(f) for f in get_file_list(str(source[0]), target[0].abspath, True, True)]
env.Clean(target, files) env.Clean(target, files)
env["godot_cpp_gen_dir"] = target[0].abspath env["godot_cpp_gen_dir"] = target[0].abspath
return files, source return files, source
def scons_generate_bindings(target, source, env): def scons_generate_bindings(target: Any, source: Any, env: Any) -> None:
generate_bindings( generate_bindings(
str(source[0]), str(source[0]),
env["generate_template_get_node"], env["generate_template_get_node"],
@ -159,9 +160,9 @@ def scons_generate_bindings(target, source, env):
return None return None
def generate_bindings(api_filepath, use_template_get_node, bits="64", precision="single", output_dir="."): def generate_bindings(
api = None api_filepath: str, use_template_get_node: bool, bits: str = "64", precision: str = "single", output_dir: str = "."
) -> None:
target_dir = Path(output_dir) / "gen" target_dir = Path(output_dir) / "gen"
with open(api_filepath, encoding="utf-8") as api_file: with open(api_filepath, encoding="utf-8") as api_file:
@ -192,7 +193,7 @@ native_structures = []
singletons = [] singletons = []
def generate_builtin_bindings(api, output_dir, build_config): def generate_builtin_bindings(api: Dict[str, Any], output_dir: Path, build_config: str) -> None:
global builtin_classes global builtin_classes
core_gen_folder = Path(output_dir) / "include" / "godot_cpp" / "core" core_gen_folder = Path(output_dir) / "include" / "godot_cpp" / "core"
@ -222,7 +223,7 @@ def generate_builtin_bindings(api, output_dir, build_config):
# Create a file for Variant size, since that class isn't generated. # Create a file for Variant size, since that class isn't generated.
variant_size_filename = include_gen_folder / "variant_size.hpp" variant_size_filename = include_gen_folder / "variant_size.hpp"
with variant_size_filename.open("+w", encoding="utf-8") as variant_size_file: with variant_size_filename.open("+w", encoding="utf-8") as variant_size_file:
variant_size_source = [] variant_size_source: List[str] = []
add_header("variant_size.hpp", variant_size_source) add_header("variant_size.hpp", variant_size_source)
header_guard = "GODOT_CPP_VARIANT_SIZE_HPP" header_guard = "GODOT_CPP_VARIANT_SIZE_HPP"
@ -245,8 +246,8 @@ def generate_builtin_bindings(api, output_dir, build_config):
source_filename = source_gen_folder / (camel_to_snake(builtin_api["name"]) + ".cpp") source_filename = source_gen_folder / (camel_to_snake(builtin_api["name"]) + ".cpp")
# Check used classes for header include # Check used classes for header include
used_classes = set() used_classes: Set[str] = set()
fully_used_classes = set() fully_used_classes: Set[str] = set()
class_name = builtin_api["name"] class_name = builtin_api["name"]
@ -292,21 +293,25 @@ def generate_builtin_bindings(api, output_dir, build_config):
if type_name in used_classes: if type_name in used_classes:
used_classes.remove(type_name) used_classes.remove(type_name)
used_classes = list(used_classes) used_classes_list: List[str] = list(used_classes)
used_classes.sort() used_classes_list.sort()
fully_used_classes = list(fully_used_classes) fully_used_classes_list: List[str] = list(fully_used_classes)
fully_used_classes.sort() fully_used_classes_list.sort()
with header_filename.open("w+", encoding="utf-8") as header_file: with header_filename.open("w+", encoding="utf-8") as header_file:
header_file.write(generate_builtin_class_header(builtin_api, size, used_classes, fully_used_classes)) header_file.write(
generate_builtin_class_header(builtin_api, size, used_classes_list, fully_used_classes_list)
)
with source_filename.open("w+", encoding="utf-8") as source_file: with source_filename.open("w+", encoding="utf-8") as source_file:
source_file.write(generate_builtin_class_source(builtin_api, size, used_classes, fully_used_classes)) source_file.write(
generate_builtin_class_source(builtin_api, size, used_classes_list, fully_used_classes_list)
)
# Create a header with all builtin types for convenience. # Create a header with all builtin types for convenience.
builtin_header_filename = include_gen_folder / "builtin_types.hpp" builtin_header_filename = include_gen_folder / "builtin_types.hpp"
with builtin_header_filename.open("w+", encoding="utf-8") as builtin_header_file: with builtin_header_filename.open("w+", encoding="utf-8") as builtin_header_file:
builtin_header = [] builtin_header: List[str] = []
add_header("builtin_types.hpp", builtin_header) add_header("builtin_types.hpp", builtin_header)
builtin_header.append("#ifndef GODOT_CPP_BUILTIN_TYPES_HPP") builtin_header.append("#ifndef GODOT_CPP_BUILTIN_TYPES_HPP")
@ -326,7 +331,7 @@ def generate_builtin_bindings(api, output_dir, build_config):
# Create a header with bindings for builtin types. # Create a header with bindings for builtin types.
builtin_binds_filename = include_gen_folder / "builtin_binds.hpp" builtin_binds_filename = include_gen_folder / "builtin_binds.hpp"
with builtin_binds_filename.open("w+", encoding="utf-8") as builtin_binds_file: with builtin_binds_filename.open("w+", encoding="utf-8") as builtin_binds_file:
builtin_binds = [] builtin_binds: List[str] = []
add_header("builtin_binds.hpp", builtin_binds) add_header("builtin_binds.hpp", builtin_binds)
builtin_binds.append("#ifndef GODOT_CPP_BUILTIN_BINDS_HPP") builtin_binds.append("#ifndef GODOT_CPP_BUILTIN_BINDS_HPP")
@ -353,8 +358,8 @@ def generate_builtin_bindings(api, output_dir, build_config):
) )
def generate_builtin_class_vararg_method_implements_header(builtin_classes): def generate_builtin_class_vararg_method_implements_header(builtin_classes: List[Dict[str, Any]]) -> str:
result = [] result: List[str] = []
add_header("builtin_vararg_methods.hpp", result) add_header("builtin_vararg_methods.hpp", result)
@ -381,8 +386,10 @@ def generate_builtin_class_vararg_method_implements_header(builtin_classes):
return "\n".join(result) return "\n".join(result)
def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_classes): def generate_builtin_class_header(
result = [] builtin_api: Dict[str, Any], size: int, used_classes: List[str], fully_used_classes: List[str]
) -> str:
result: List[str] = []
class_name = builtin_api["name"] class_name = builtin_api["name"]
snake_class_name = camel_to_snake(class_name).upper() snake_class_name = camel_to_snake(class_name).upper()
@ -782,8 +789,10 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
return "\n".join(result) return "\n".join(result)
def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_classes): def generate_builtin_class_source(
result = [] builtin_api: Dict[str, Any], size: int, used_classes: List[str], fully_used_classes: List[str]
) -> str:
result: List[str] = []
class_name = builtin_api["name"] class_name = builtin_api["name"]
snake_class_name = camel_to_snake(class_name) snake_class_name = camel_to_snake(class_name)
@ -922,7 +931,7 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl
(encode, arg_name) = get_encoded_arg( (encode, arg_name) = get_encoded_arg(
argument["name"], argument["name"],
argument["type"], argument["type"],
argument["meta"] if "meta" in argument else None, argument["meta"] if "meta" in argument else "",
) )
result += encode result += encode
arguments.append(arg_name) arguments.append(arg_name)
@ -981,7 +990,7 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl
(encode, arg_name) = get_encoded_arg( (encode, arg_name) = get_encoded_arg(
argument["name"], argument["name"],
argument["type"], argument["type"],
argument["meta"] if "meta" in argument else None, argument["meta"] if "meta" in argument else "",
) )
result += encode result += encode
arguments.append(arg_name) arguments.append(arg_name)
@ -1003,7 +1012,7 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl
if f'set_{member["name"]}' not in method_list: if f'set_{member["name"]}' not in method_list:
result.append(f'void {class_name}::set_{member["name"]}({type_for_parameter(member["type"])}value) {{') 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) (encode, arg_name) = get_encoded_arg("value", member["type"])
result += encode result += encode
result.append( 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});'
@ -1019,7 +1028,7 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl
result.append( result.append(
f'{correct_type(operator["return_type"])} {class_name}::operator{operator["name"]}({type_for_parameter(operator["right_type"])}other) const {{' f'{correct_type(operator["return_type"])} {class_name}::operator{operator["name"]}({type_for_parameter(operator["right_type"])}other) const {{'
) )
(encode, arg_name) = get_encoded_arg("other", operator["right_type"], None) (encode, arg_name) = get_encoded_arg("other", operator["right_type"])
result += encode result += encode
result.append( 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});'
@ -1043,7 +1052,6 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl
(encode, arg_name) = get_encoded_arg( (encode, arg_name) = get_encoded_arg(
"other", "other",
class_name, class_name,
None,
) )
result += encode result += encode
result.append( result.append(
@ -1070,7 +1078,7 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl
return "\n".join(result) return "\n".join(result)
def generate_engine_classes_bindings(api, output_dir, use_template_get_node): def generate_engine_classes_bindings(api: Dict[str, Any], output_dir: Path, use_template_get_node: bool) -> None:
global engine_classes global engine_classes
global singletons global singletons
global native_structures global native_structures
@ -1103,8 +1111,8 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
for class_api in api["classes"]: for class_api in api["classes"]:
# Check used classes for header include. # Check used classes for header include.
used_classes = set() used_classes: Set[str] = set()
fully_used_classes = set() fully_used_classes: Set[str] = set()
class_name = class_api["name"] class_name = class_api["name"]
@ -1201,19 +1209,23 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
if type_name in used_classes: if type_name in used_classes:
used_classes.remove(type_name) used_classes.remove(type_name)
used_classes = list(used_classes) used_classes_list: List[str] = list(used_classes)
used_classes.sort() used_classes_list.sort()
fully_used_classes = list(fully_used_classes) fully_used_classes_list: List[str] = list(fully_used_classes)
fully_used_classes.sort() fully_used_classes_list.sort()
with header_filename.open("w+", encoding="utf-8") as header_file: with header_filename.open("w+", encoding="utf-8") as header_file:
header_file.write( header_file.write(
generate_engine_class_header(class_api, used_classes, fully_used_classes, use_template_get_node) generate_engine_class_header(
class_api, used_classes_list, fully_used_classes_list, use_template_get_node
)
) )
with source_filename.open("w+", encoding="utf-8") as source_file: with source_filename.open("w+", encoding="utf-8") as source_file:
source_file.write( source_file.write(
generate_engine_class_source(class_api, used_classes, fully_used_classes, use_template_get_node) generate_engine_class_source(
class_api, used_classes_list, fully_used_classes_list, use_template_get_node
)
) )
for native_struct in api["native_structures"]: for native_struct in api["native_structures"]:
@ -1224,27 +1236,27 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
header_filename = include_gen_folder / (snake_struct_name + ".hpp") header_filename = include_gen_folder / (snake_struct_name + ".hpp")
result = [] result: List[str] = []
add_header(f"{snake_struct_name}.hpp", result) add_header(f"{snake_struct_name}.hpp", result)
header_guard = f"GODOT_CPP_{snake_struct_name.upper()}_HPP" header_guard = f"GODOT_CPP_{snake_struct_name.upper()}_HPP"
result.append(f"#ifndef {header_guard}") result.append(f"#ifndef {header_guard}")
result.append(f"#define {header_guard}") result.append(f"#define {header_guard}")
used_classes = [] used_classes_list = []
expanded_format = native_struct["format"].replace("(", " ").replace(")", ";").replace(",", ";") expanded_format = native_struct["format"].replace("(", " ").replace(")", ";").replace(",", ";")
for field in expanded_format.split(";"): for field in expanded_format.split(";"):
field_type = field.strip().split(" ")[0].split("::")[0] field_type = field.strip().split(" ")[0].split("::")[0]
if field_type != "" and not is_included_type(field_type) and not is_pod_type(field_type): if field_type != "" and not is_included_type(field_type) and not is_pod_type(field_type):
if not field_type in used_classes: if not field_type in used_classes_list:
used_classes.append(field_type) used_classes_list.append(field_type)
result.append("") result.append("")
for included in used_classes: for included in used_classes_list:
result.append(f"#include <godot_cpp/{get_include_path(included)}>") result.append(f"#include <godot_cpp/{get_include_path(included)}>")
if len(used_classes) == 0: if len(used_classes_list) == 0:
result.append("#include <godot_cpp/core/method_ptrcall.hpp>") result.append("#include <godot_cpp/core/method_ptrcall.hpp>")
result.append("") result.append("")
@ -1268,9 +1280,11 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
header_file.write("\n".join(result)) header_file.write("\n".join(result))
def generate_engine_class_header(class_api, used_classes, fully_used_classes, use_template_get_node): def generate_engine_class_header(
class_api: Dict[str, Any], used_classes: List[str], fully_used_classes: List[str], use_template_get_node: bool
) -> str:
global singletons global singletons
result = [] result: List[str] = []
class_name = class_api["name"] class_name = class_api["name"]
snake_class_name = camel_to_snake(class_name).upper() snake_class_name = camel_to_snake(class_name).upper()
@ -1473,7 +1487,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
method_signature += f'{correct_type(method["return_type"])} ' method_signature += f'{correct_type(method["return_type"])} '
elif "return_value" in method: elif "return_value" in method:
method_signature += ( method_signature += (
correct_type(method["return_value"]["type"], method["return_value"].get("meta", None)) + " " correct_type(method["return_value"]["type"], method["return_value"].get("meta", "")) + " "
) )
else: else:
method_signature += "void " method_signature += "void "
@ -1509,9 +1523,11 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
return "\n".join(result) return "\n".join(result)
def generate_engine_class_source(class_api, used_classes, fully_used_classes, use_template_get_node): def generate_engine_class_source(
class_api: Dict[str, Any], used_classes: List[str], fully_used_classes: List[str], use_template_get_node: bool
) -> str:
global singletons global singletons
result = [] result: List[str] = []
class_name = class_api["name"] class_name = class_api["name"]
snake_class_name = camel_to_snake(class_name) snake_class_name = camel_to_snake(class_name)
@ -1586,7 +1602,7 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
if not vararg: if not vararg:
if has_return: if has_return:
return_type = method["return_value"]["type"] return_type = method["return_value"]["type"]
meta_type = method["return_value"]["meta"] if "meta" in method["return_value"] else None meta_type = method["return_value"]["meta"] if "meta" in method["return_value"] else ""
if is_enum(return_type): if is_enum(return_type):
if method["is_static"]: if method["is_static"]:
method_call += f"return ({get_gdextension_type(correct_type(return_type, meta_type))})internal::_call_native_mb_ret<int64_t>(_gde_method_bind, nullptr" method_call += f"return ({get_gdextension_type(correct_type(return_type, meta_type))})internal::_call_native_mb_ret<int64_t>(_gde_method_bind, nullptr"
@ -1625,7 +1641,7 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
(encode, arg_name) = get_encoded_arg( (encode, arg_name) = get_encoded_arg(
argument["name"], argument["name"],
argument["type"], argument["type"],
argument["meta"] if "meta" in argument else None, argument["meta"] if "meta" in argument else "",
) )
result += encode result += encode
arguments.append(arg_name) arguments.append(arg_name)
@ -1672,7 +1688,7 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
return "\n".join(result) return "\n".join(result)
def generate_global_constants(api, output_dir): def generate_global_constants(api: Dict[str, Any], output_dir: Path) -> None:
include_gen_folder = Path(output_dir) / "include" / "godot_cpp" / "classes" include_gen_folder = Path(output_dir) / "include" / "godot_cpp" / "classes"
source_gen_folder = Path(output_dir) / "src" / "classes" source_gen_folder = Path(output_dir) / "src" / "classes"
@ -1681,7 +1697,7 @@ def generate_global_constants(api, output_dir):
# Generate header # Generate header
header = [] header: List[str] = []
add_header("global_constants.hpp", header) add_header("global_constants.hpp", header)
header_filename = include_gen_folder / "global_constants.hpp" header_filename = include_gen_folder / "global_constants.hpp"
@ -1723,8 +1739,8 @@ def generate_global_constants(api, output_dir):
header_file.write("\n".join(header)) header_file.write("\n".join(header))
def generate_version_header(api, output_dir): def generate_version_header(api: Dict[str, Any], output_dir: Path) -> None:
header = [] header: List[str] = []
header_filename = "version.hpp" header_filename = "version.hpp"
add_header(header_filename, header) add_header(header_filename, header)
@ -1752,7 +1768,7 @@ def generate_version_header(api, output_dir):
header_file.write("\n".join(header)) header_file.write("\n".join(header))
def generate_global_constant_binds(api, output_dir): def generate_global_constant_binds(api: Dict[str, Any], output_dir: Path) -> None:
include_gen_folder = Path(output_dir) / "include" / "godot_cpp" / "classes" include_gen_folder = Path(output_dir) / "include" / "godot_cpp" / "classes"
source_gen_folder = Path(output_dir) / "src" / "classes" source_gen_folder = Path(output_dir) / "src" / "classes"
@ -1761,7 +1777,7 @@ def generate_global_constant_binds(api, output_dir):
# Generate header # Generate header
header = [] header: List[str] = []
add_header("global_constants_binds.hpp", header) add_header("global_constants_binds.hpp", header)
header_filename = include_gen_folder / "global_constants_binds.hpp" header_filename = include_gen_folder / "global_constants_binds.hpp"
@ -1793,7 +1809,7 @@ def generate_global_constant_binds(api, output_dir):
header_file.write("\n".join(header)) header_file.write("\n".join(header))
def generate_utility_functions(api, output_dir): def generate_utility_functions(api: Dict[str, Any], output_dir: Path) -> None:
include_gen_folder = Path(output_dir) / "include" / "godot_cpp" / "variant" include_gen_folder = Path(output_dir) / "include" / "godot_cpp" / "variant"
source_gen_folder = Path(output_dir) / "src" / "variant" source_gen_folder = Path(output_dir) / "src" / "variant"
@ -1802,7 +1818,7 @@ def generate_utility_functions(api, output_dir):
# Generate header. # Generate header.
header = [] header: List[str] = []
add_header("utility_functions.hpp", header) add_header("utility_functions.hpp", header)
header_filename = include_gen_folder / "utility_functions.hpp" header_filename = include_gen_folder / "utility_functions.hpp"
@ -1843,7 +1859,7 @@ def generate_utility_functions(api, output_dir):
# Generate source. # Generate source.
source = [] source: List[str] = []
add_header("utility_functions.cpp", source) add_header("utility_functions.cpp", source)
source_filename = source_gen_folder / "utility_functions.cpp" source_filename = source_gen_folder / "utility_functions.cpp"
@ -1892,7 +1908,7 @@ def generate_utility_functions(api, output_dir):
(encode, arg_name) = get_encoded_arg( (encode, arg_name) = get_encoded_arg(
argument["name"], argument["name"],
argument["type"], argument["type"],
argument["meta"] if "meta" in argument else None, argument["meta"] if "meta" in argument else "",
) )
source += encode source += encode
arguments.append(arg_name) arguments.append(arg_name)
@ -1922,17 +1938,19 @@ def generate_utility_functions(api, output_dir):
# Helper functions. # Helper functions.
def camel_to_snake(name): def camel_to_snake(name: str) -> str:
name = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", name) name = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", name)
name = re.sub("([a-z0-9])([A-Z])", r"\1_\2", name) name = re.sub("([a-z0-9])([A-Z])", r"\1_\2", name)
return name.replace("2_D", "2D").replace("3_D", "3D").lower() return name.replace("2_D", "2D").replace("3_D", "3D").lower()
def make_function_parameters(parameters, include_default=False, for_builtin=False, is_vararg=False): def make_function_parameters(
parameters: List[Dict[str, Any]], include_default: bool = False, for_builtin: bool = False, is_vararg: bool = False
) -> str:
signature = [] signature = []
for index, par in enumerate(parameters): for index, par in enumerate(parameters):
parameter = type_for_parameter(par["type"], par["meta"] if "meta" in par else None) parameter = type_for_parameter(par["type"], par["meta"] if "meta" in par else "")
parameter_name = escape_identifier(par["name"]) parameter_name = escape_identifier(par["name"])
if len(parameter_name) == 0: if len(parameter_name) == 0:
parameter_name = "arg_" + str(index + 1) parameter_name = "arg_" + str(index + 1)
@ -1954,7 +1972,7 @@ def make_function_parameters(parameters, include_default=False, for_builtin=Fals
return ", ".join(signature) return ", ".join(signature)
def type_for_parameter(type_name, meta=None): def type_for_parameter(type_name: str, meta: str = "") -> str:
if type_name == "void": if type_name == "void":
return "Variant " return "Variant "
elif is_pod_type(type_name) and type_name != "Nil" or is_enum(type_name): elif is_pod_type(type_name) and type_name != "Nil" or is_enum(type_name):
@ -1965,7 +1983,7 @@ def type_for_parameter(type_name, meta=None):
return f"{correct_type(type_name)}" return f"{correct_type(type_name)}"
def get_include_path(type_name): def get_include_path(type_name: str) -> str:
base_dir = "" base_dir = ""
if type_name == "Object": if type_name == "Object":
base_dir = "core" base_dir = "core"
@ -1977,8 +1995,8 @@ def get_include_path(type_name):
return f"{base_dir}/{camel_to_snake(type_name)}.hpp" return f"{base_dir}/{camel_to_snake(type_name)}.hpp"
def get_encoded_arg(arg_name, type_name, type_meta): def get_encoded_arg(arg_name: str, type_name: str, type_meta: str = "") -> Tuple[List[str], str]:
result = [] result: List[str] = []
name = escape_identifier(arg_name) name = escape_identifier(arg_name)
arg_type = correct_type(type_name) arg_type = correct_type(type_name)
@ -1997,8 +2015,13 @@ def get_encoded_arg(arg_name, type_name, type_meta):
def make_signature( def make_signature(
class_name, function_data, for_header=False, use_template_get_node=True, for_builtin=False, static=False class_name: str,
): function_data: Dict[str, Any],
for_header: bool = False,
use_template_get_node: bool = True,
for_builtin: bool = False,
static: bool = False,
) -> str:
function_signature = "" function_signature = ""
is_vararg = "is_vararg" in function_data and function_data["is_vararg"] is_vararg = "is_vararg" in function_data and function_data["is_vararg"]
@ -2014,12 +2037,12 @@ def make_signature(
function_signature += "static " function_signature += "static "
return_type = "void" return_type = "void"
return_meta = None return_meta = ""
if "return_type" in function_data: if "return_type" in function_data:
return_type = correct_type(function_data["return_type"]) return_type = correct_type(function_data["return_type"])
elif "return_value" in function_data: elif "return_value" in function_data:
return_type = function_data["return_value"]["type"] return_type = function_data["return_value"]["type"]
return_meta = function_data["return_value"]["meta"] if "meta" in function_data["return_value"] else None return_meta = function_data["return_value"]["meta"] if "meta" in function_data["return_value"] else ""
function_signature += correct_type( function_signature += correct_type(
return_type, return_type,
@ -2059,14 +2082,14 @@ def make_signature(
def make_varargs_template( def make_varargs_template(
function_data, function_data: Dict[str, Any],
static=False, static: bool = False,
class_befor_signature="", class_before_signature: str = "",
with_public_declare=True, with_public_declare: bool = True,
with_indent=True, with_indent: bool = True,
for_builtin_classes=False, for_builtin_classes: bool = False,
): ) -> List[str]:
result = [] result: List[str] = []
function_signature = "" function_signature = ""
@ -2079,12 +2102,12 @@ def make_varargs_template(
function_signature += "static " function_signature += "static "
return_type = "void" return_type = "void"
return_meta = None return_meta = ""
if "return_type" in function_data: if "return_type" in function_data:
return_type = correct_type(function_data["return_type"]) return_type = correct_type(function_data["return_type"])
elif "return_value" in function_data: elif "return_value" in function_data:
return_type = function_data["return_value"]["type"] return_type = function_data["return_value"]["type"]
return_meta = function_data["return_value"]["meta"] if "meta" in function_data["return_value"] else None return_meta = function_data["return_value"]["meta"] if "meta" in function_data["return_value"] else ""
function_signature += correct_type( function_signature += correct_type(
return_type, return_type,
@ -2094,8 +2117,8 @@ def make_varargs_template(
if not function_signature.endswith("*"): if not function_signature.endswith("*"):
function_signature += " " function_signature += " "
if len(class_befor_signature) > 0: if len(class_before_signature) > 0:
function_signature += class_befor_signature + "::" function_signature += class_before_signature + "::"
function_signature += f'{escape_identifier(function_data["name"])}' function_signature += f'{escape_identifier(function_data["name"])}'
method_arguments = [] method_arguments = []
@ -2169,7 +2192,7 @@ def make_varargs_template(
# Engine idiosyncrasies. # Engine idiosyncrasies.
def is_pod_type(type_name): def is_pod_type(type_name: str) -> bool:
""" """
Those are types for which no class should be generated. Those are types for which no class should be generated.
""" """
@ -2192,12 +2215,12 @@ def is_pod_type(type_name):
] ]
def is_included_type(type_name): def is_included_type(type_name: str) -> bool:
# Types which we already have implemented. # Types which we already have implemented.
return is_included_struct_type(type_name) or type_name in ["ObjectID"] return is_included_struct_type(type_name) or type_name in ["ObjectID"]
def is_included_struct_type(type_name): def is_included_struct_type(type_name: str) -> bool:
# Struct types which we already have implemented. # Struct types which we already have implemented.
return type_name in [ return type_name in [
"AABB", "AABB",
@ -2219,7 +2242,7 @@ def is_included_struct_type(type_name):
] ]
def is_packed_array(type_name): def is_packed_array(type_name: str) -> bool:
""" """
Those are types for which we add our extra packed array functions. Those are types for which we add our extra packed array functions.
""" """
@ -2236,7 +2259,7 @@ def is_packed_array(type_name):
] ]
def needs_copy_instead_of_move(type_name): def needs_copy_instead_of_move(type_name: str) -> bool:
""" """
Those are types which need initialised data or we'll get warning spam so need a copy instead of move. Those are types which need initialised data or we'll get warning spam so need a copy instead of move.
""" """
@ -2245,15 +2268,15 @@ def needs_copy_instead_of_move(type_name):
] ]
def is_enum(type_name): def is_enum(type_name: str) -> bool:
return type_name.startswith("enum::") or type_name.startswith("bitfield::") return type_name.startswith("enum::") or type_name.startswith("bitfield::")
def is_bitfield(type_name): def is_bitfield(type_name: str) -> bool:
return type_name.startswith("bitfield::") return type_name.startswith("bitfield::")
def get_enum_class(enum_name: str): def get_enum_class(enum_name: str) -> str:
if "." in enum_name: if "." in enum_name:
if is_bitfield(enum_name): if is_bitfield(enum_name):
return enum_name.replace("bitfield::", "").split(".")[0] return enum_name.replace("bitfield::", "").split(".")[0]
@ -2263,21 +2286,21 @@ def get_enum_class(enum_name: str):
return "GlobalConstants" return "GlobalConstants"
def get_enum_fullname(enum_name: str): def get_enum_fullname(enum_name: str) -> str:
if is_bitfield(enum_name): if is_bitfield(enum_name):
return enum_name.replace("bitfield::", "BitField<") + ">" return enum_name.replace("bitfield::", "BitField<") + ">"
else: else:
return enum_name.replace("enum::", "") return enum_name.replace("enum::", "")
def get_enum_name(enum_name: str): def get_enum_name(enum_name: str) -> str:
if is_bitfield(enum_name): if is_bitfield(enum_name):
return enum_name.replace("bitfield::", "").split(".")[-1] return enum_name.replace("bitfield::", "").split(".")[-1]
else: else:
return enum_name.replace("enum::", "").split(".")[-1] return enum_name.replace("enum::", "").split(".")[-1]
def is_variant(type_name): def is_variant(type_name: str) -> bool:
return ( return (
type_name == "Variant" type_name == "Variant"
or type_name in builtin_classes or type_name in builtin_classes
@ -2286,22 +2309,22 @@ def is_variant(type_name):
) )
def is_engine_class(type_name): def is_engine_class(type_name: str) -> bool:
global engine_classes global engine_classes
return type_name == "Object" or type_name in engine_classes return type_name == "Object" or type_name in engine_classes
def is_struct_type(type_name): def is_struct_type(type_name: str) -> bool:
# This is used to determine which keyword to use for forward declarations. # This is used to determine which keyword to use for forward declarations.
global native_structures global native_structures
return is_included_struct_type(type_name) or type_name in native_structures return is_included_struct_type(type_name) or type_name in native_structures
def is_refcounted(type_name): def is_refcounted(type_name: str) -> bool:
return type_name in engine_classes and engine_classes[type_name] return type_name in engine_classes and engine_classes[type_name]
def is_included(type_name, current_type): def is_included(type_name: str, current_type: str) -> bool:
""" """
Check if a builtin type should be included. Check if a builtin type should be included.
This removes Variant and POD types from inclusion, and the current type. This removes Variant and POD types from inclusion, and the current type.
@ -2316,7 +2339,7 @@ def is_included(type_name, current_type):
return is_engine_class(to_include) or is_variant(to_include) return is_engine_class(to_include) or is_variant(to_include)
def correct_default_value(value, type_name): def correct_default_value(value: str, type_name: str) -> str:
value_map = { value_map = {
"null": "nullptr", "null": "nullptr",
'""': "String()", '""': "String()",
@ -2335,15 +2358,15 @@ def correct_default_value(value, type_name):
return value return value
def correct_typed_array(type_name): def correct_typed_array(type_name: str) -> str:
if type_name.startswith("typedarray::"): if type_name.startswith("typedarray::"):
return type_name.replace("typedarray::", "TypedArray<") + ">" return type_name.replace("typedarray::", "TypedArray<") + ">"
return type_name return type_name
def correct_type(type_name, meta=None): def correct_type(type_name: str, meta: str = "") -> str:
type_conversion = {"float": "double", "int": "int64_t", "Nil": "Variant"} type_conversion = {"float": "double", "int": "int64_t", "Nil": "Variant"}
if meta != None: if meta:
if "int" in meta: if "int" in meta:
return f"{meta}_t" return f"{meta}_t"
elif meta in type_conversion: elif meta in type_conversion:
@ -2374,7 +2397,7 @@ def correct_type(type_name, meta=None):
return type_name return type_name
def get_gdextension_type(type_name): def get_gdextension_type(type_name: str) -> str:
type_conversion_map = { type_conversion_map = {
"bool": "int8_t", "bool": "int8_t",
"uint8_t": "int64_t", "uint8_t": "int64_t",
@ -2395,7 +2418,7 @@ def get_gdextension_type(type_name):
return type_name return type_name
def escape_identifier(id): def escape_identifier(id: str) -> str:
cpp_keywords_map = { cpp_keywords_map = {
"class": "_class", "class": "_class",
"char": "_char", "char": "_char",
@ -2418,7 +2441,7 @@ def escape_identifier(id):
return id return id
def get_operator_id_name(op): def get_operator_id_name(op: str) -> str:
op_id_map = { op_id_map = {
"==": "equal", "==": "equal",
"!=": "not_equal", "!=": "not_equal",
@ -2450,7 +2473,7 @@ def get_operator_id_name(op):
return op_id_map[op] return op_id_map[op]
def get_default_value_for_type(type_name): def get_default_value_for_type(type_name: str) -> str:
if type_name == "int": if type_name == "int":
return "0" return "0"
if type_name == "float": if type_name == "float":
@ -2501,7 +2524,7 @@ header = """\
""" """
def add_header(filename, lines): def add_header(filename: str, lines: List[str]) -> None:
desired_length = len(header.split("\n")[0]) desired_length = len(header.split("\n")[0])
pad_spaces = desired_length - 6 - len(filename) pad_spaces = desired_length - 6 - len(filename)