Add copy/move constructors and assignment op to builtin types

pull/602/head
George Marques 2021-08-26 17:26:33 -03:00 committed by Bastiaan Olij
parent 3a9ff8de7a
commit f19bb9f57c
1 changed files with 59 additions and 5 deletions

View File

@ -284,6 +284,8 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
result.append("") result.append("")
result.append("public:") result.append("public:")
copy_constructor_index = -1
if "constructors" in builtin_api: if "constructors" in builtin_api:
for constructor in builtin_api["constructors"]: for constructor in builtin_api["constructors"]:
method_signature = f"\t{class_name}(" method_signature = f"\t{class_name}("
@ -291,10 +293,15 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
method_signature += make_function_parameters( method_signature += make_function_parameters(
constructor["arguments"], include_default=True, for_builtin=True constructor["arguments"], include_default=True, for_builtin=True
) )
if len(constructor["arguments"]) == 1 and constructor["arguments"][0]["type"] == class_name:
copy_constructor_index = constructor["index"]
method_signature += ");" method_signature += ");"
result.append(method_signature) result.append(method_signature)
# Move constructor.
result.append(f'\t{class_name}({class_name} &&other);')
# Special cases. # Special cases.
if class_name == "String" or class_name == "StringName" or class_name == "NodePath": if class_name == "String" or class_name == "StringName" or class_name == "NodePath":
result.append(f"\t{class_name}(const char *from);") result.append(f"\t{class_name}(const char *from);")
@ -383,6 +390,13 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
f'\t{correct_type(operator["return_type"])} operator{operator["name"].replace("unary", "")}() const;' f'\t{correct_type(operator["return_type"])} operator{operator["name"].replace("unary", "")}() const;'
) )
# Copy assignment.
if copy_constructor_index >= 0:
result.append(f"\t{class_name} &operator=(const {class_name} &other);")
# Move assignment.
result.append(f"\t{class_name} &operator=({class_name} &&other);")
# Special cases. # Special cases.
if class_name == "String": if class_name == "String":
result.append("String &operator=(const char *p_str);") result.append("String &operator=(const char *p_str);")
@ -449,6 +463,8 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl
result.append("#include <godot_cpp/core/builtin_ptrcall.hpp>") result.append("#include <godot_cpp/core/builtin_ptrcall.hpp>")
result.append("") result.append("")
result.append("#include <utility>")
result.append("")
result.append("namespace godot {") result.append("namespace godot {")
result.append("") result.append("")
@ -517,6 +533,8 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl
result.append("}") result.append("}")
result.append("") result.append("")
copy_constructor_index = -1
if "constructors" in builtin_api: if "constructors" in builtin_api:
for constructor in builtin_api["constructors"]: for constructor in builtin_api["constructors"]:
method_signature = f"{class_name}::{class_name}(" method_signature = f"{class_name}::{class_name}("
@ -532,6 +550,8 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl
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 "arguments" in constructor:
if len(constructor["arguments"]) == 1 and constructor["arguments"][0]["type"] == class_name:
copy_constructor_index = constructor["index"]
method_call += ", " method_call += ", "
arguments = [] arguments = []
for argument in constructor["arguments"]: for argument in constructor["arguments"]:
@ -549,6 +569,12 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl
result.append("}") result.append("}")
result.append("") result.append("")
# Move constructor.
result.append(f'{class_name}::{class_name}({class_name} &&other) {{')
result.append("\tstd::swap(opaque, other.opaque);")
result.append("}")
result.append("")
if builtin_api["has_destructor"]: if builtin_api["has_destructor"]:
result.append(f"{class_name}::~{class_name}() {{") result.append(f"{class_name}::~{class_name}() {{")
result.append("\t_method_bindings.destructor(&opaque);") result.append("\t_method_bindings.destructor(&opaque);")
@ -638,8 +664,33 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl
f'\treturn internal::_call_builtin_operator_ptr<{correct_type(operator["return_type"])}>(_method_bindings.operator_{get_operator_id_name(operator["name"])}, (const GDNativeTypePtr)&opaque, (const GDNativeTypePtr)nullptr);' f'\treturn internal::_call_builtin_operator_ptr<{correct_type(operator["return_type"])}>(_method_bindings.operator_{get_operator_id_name(operator["name"])}, (const GDNativeTypePtr)&opaque, (const GDNativeTypePtr)nullptr);'
) )
result.append("}") result.append("}")
result.append("") result.append("")
# Copy assignment.
if copy_constructor_index >= 0:
result.append(f"{class_name} &{class_name}::operator=(const {class_name} &other) {{")
if builtin_api["has_destructor"]:
result.append("\t_method_bindings.destructor(&opaque);")
(encode, arg_name) = get_encoded_arg(
"other",
class_name,
None,
)
result += encode
result.append(
f"\tinternal::_call_builtin_constructor(_method_bindings.constructor_{copy_constructor_index}, &opaque, {arg_name});"
)
result.append("\treturn *this;")
result.append("}")
result.append("")
# Move assignment.
result.append(f"{class_name} &{class_name}::operator=({class_name} &&other) {{")
result.append("\tstd::swap(opaque, other.opaque);")
result.append("\treturn *this;")
result.append("}")
result.append("")
result.append("} //namespace godot") result.append("} //namespace godot")
return "\n".join(result) return "\n".join(result)
@ -699,7 +750,6 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
type_name = method["return_value"]["type"] type_name = method["return_value"]["type"]
if type_name.endswith("*"): if type_name.endswith("*"):
type_name = type_name[:-1] type_name = type_name[:-1]
print("New type name ", type_name)
if is_included(type_name, class_name): if is_included(type_name, class_name):
if is_enum(type_name): if is_enum(type_name):
fully_used_classes.add(get_enum_class(type_name)) fully_used_classes.add(get_enum_class(type_name))
@ -936,11 +986,15 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
if is_singleton: if is_singleton:
result.append(f"{class_name} *{class_name}::get_singleton() {{") result.append(f"{class_name} *{class_name}::get_singleton() {{")
result.append(f'\tstatic GDNativeObjectPtr singleton_obj = internal::interface->global_get_singleton("{class_name}");') result.append(
f'\tstatic GDNativeObjectPtr singleton_obj = internal::interface->global_get_singleton("{class_name}");'
)
result.append("#ifdef DEBUG_ENABLED") result.append("#ifdef DEBUG_ENABLED")
result.append('\tERR_FAIL_COND_V(singleton_obj == nullptr, nullptr);') result.append("\tERR_FAIL_COND_V(singleton_obj == nullptr, nullptr);")
result.append("#endif // DEBUG_ENABLED") result.append("#endif // DEBUG_ENABLED")
result.append(f'\tstatic {class_name} *singleton = reinterpret_cast<{class_name} *>(internal::interface->object_get_instance_binding(singleton_obj, internal::token, &{class_name}::___binding_callbacks));') result.append(
f"\tstatic {class_name} *singleton = reinterpret_cast<{class_name} *>(internal::interface->object_get_instance_binding(singleton_obj, internal::token, &{class_name}::___binding_callbacks));"
)
result.append("\treturn singleton;") result.append("\treturn singleton;")
result.append("}") result.append("}")
result.append("") result.append("")