From 3b16f34d893fd79a8720c5933e406ce19bf7b3f9 Mon Sep 17 00:00:00 2001 From: Duncan Sparks Date: Wed, 17 Jun 2020 12:12:57 -0700 Subject: [PATCH 1/4] Add option for template get_node --- SConstruct | 7 +++++- binding_generator.py | 55 +++++++++++++++++++++++++++++++++++--------- 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/SConstruct b/SConstruct index 881b44dc..17659731 100644 --- a/SConstruct +++ b/SConstruct @@ -144,6 +144,11 @@ opts.Add( 'Path to your Android NDK installation. By default, uses ANDROID_NDK_ROOT from your defined environment variables.', os.environ.get("ANDROID_NDK_ROOT", None) ) +opts.Add(BoolVariable( + 'generate_template_get_node', + "Generate a template version of the Node class's get_node.", + False +)) env = Environment(ENV = os.environ) opts.Update(env) @@ -362,7 +367,7 @@ if env['generate_bindings']: # Actually create the bindings here import binding_generator - binding_generator.generate_bindings(json_api_file) + binding_generator.generate_bindings(json_api_file, env['generate_template_get_node']) # Sources to compile sources = [] diff --git a/binding_generator.py b/binding_generator.py index 3b01f0ba..1992f6d6 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -4,9 +4,15 @@ import json # comment. +# Convenience function for using template get_node +def correct_method_name(class_name, method): + if method["name"] == "get_node" and class_name == "Node": + method["name"] = "get_node_internal" + + classes = [] -def generate_bindings(path): +def generate_bindings(path, use_template_get_node): global classes classes = json.load(open(path)) @@ -15,11 +21,11 @@ def generate_bindings(path): for c in classes: # print c['name'] - used_classes = get_used_classes(c) + used_classes = get_used_classes(c, use_template_get_node) - header = generate_class_header(used_classes, c) + header = generate_class_header(used_classes, c, use_template_get_node) - impl = generate_class_implementation(icalls, used_classes, c) + impl = generate_class_implementation(icalls, used_classes, c, use_template_get_node) header_file = open("include/gen/" + strip_name(c["name"]) + ".hpp", "w+") header_file.write(header) @@ -62,7 +68,7 @@ def make_gdnative_type(t): return strip_name(t) + " " -def generate_class_header(used_classes, c): +def generate_class_header(used_classes, c, use_template_get_node): source = [] source.append("#ifndef GODOT_CPP_" + strip_name(c["name"]).upper() + "_HPP") @@ -140,6 +146,8 @@ def generate_class_header(used_classes, c): source.append("\tstruct ___method_bindings {") for method in c["methods"]: + if use_template_get_node: + correct_method_name(class_name, method) source.append("\t\tgodot_method_bind *mb_" + method["name"] + ";") source.append("\t};") @@ -201,7 +209,8 @@ def generate_class_header(used_classes, c): source.append("") for method in c["methods"]: - + if use_template_get_node: + correct_method_name(class_name, method) method_signature = "" # TODO decide what to do about virtual methods @@ -279,10 +288,28 @@ def generate_class_header(used_classes, c): source.append("\t" + method_signature + ";") source.append(vararg_templates) - source.append("};") - source.append("") + if use_template_get_node: + # Extra definition for template get_node that calls the renamed get_node_internal; has a default template parameter for backwards compatibility. + if class_name == "Node": + source.append("\ttemplate ") + source.append("\tT *get_node(const NodePath path) const {") + source.append("\t\treturn Object::cast_to(get_node_internal(path));") + source.append("\t}") + source.append("};") + source.append("") + + # ...And a specialized version so we don't unnecessarily cast when using the default. + if class_name == "Node": + source.append("template <>") + source.append("inline Node *Node::get_node(const NodePath path) const {") + source.append("\treturn get_node_internal(path);") + source.append("}") + source.append("") + else: + source.append("};") + source.append("") source.append("}") source.append("") @@ -296,7 +323,7 @@ def generate_class_header(used_classes, c): -def generate_class_implementation(icalls, used_classes, c): +def generate_class_implementation(icalls, used_classes, c, use_template_get_node): class_name = strip_name(c["name"]) source = [] source.append("#include \"" + class_name + ".hpp\"") @@ -353,7 +380,9 @@ def generate_class_implementation(icalls, used_classes, c): source.append("void " + class_name + "::___init_method_bindings() {") for method in c["methods"]: - source.append("\t___mb.mb_" + method["name"] + " = godot::api->godot_method_bind_get_method(\"" + c["name"] + "\", \"" + method["name"] + "\");") + if use_template_get_node: + correct_method_name(class_name, method) + source.append("\t___mb.mb_" + method["name"] + " = godot::api->godot_method_bind_get_method(\"" + c["name"] + "\", \"" + ("get_node" if use_template_get_node and method["name"] == "get_node_internal" else method["name"]) + "\");") source.append("}") source.append("") @@ -365,6 +394,8 @@ def generate_class_implementation(icalls, used_classes, c): source.append("}") for method in c["methods"]: + if use_template_get_node: + correct_method_name(class_name, method) method_signature = "" @@ -710,9 +741,11 @@ def get_icall_name(sig): -def get_used_classes(c): +def get_used_classes(c, use_template_get_node): classes = [] for method in c["methods"]: + if use_template_get_node: + correct_method_name(strip_name(c["name"]), method) if is_class_type(method["return_type"]) and not (method["return_type"] in classes): classes.append(method["return_type"]) From bd72bd4d6854f281d7f999ab41330063766fa6e9 Mon Sep 17 00:00:00 2001 From: Duncan Sparks Date: Sun, 23 Aug 2020 09:01:23 -0700 Subject: [PATCH 2/4] Fix redundant check in binding_generator.py --- binding_generator.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/binding_generator.py b/binding_generator.py index 9b54b22c..b4bfc2a5 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -291,24 +291,22 @@ def generate_class_header(used_classes, c, use_template_get_node): source.append(vararg_templates) - if use_template_get_node: + if use_template_get_node and class_name == "Node": # Extra definition for template get_node that calls the renamed get_node_internal; has a default template parameter for backwards compatibility. - if class_name == "Node": - source.append("\ttemplate ") - source.append("\tT *get_node(const NodePath path) const {") - source.append("\t\treturn Object::cast_to(get_node_internal(path));") - source.append("\t}") + source.append("\ttemplate ") + source.append("\tT *get_node(const NodePath path) const {") + source.append("\t\treturn Object::cast_to(get_node_internal(path));") + source.append("\t}") source.append("};") source.append("") # ...And a specialized version so we don't unnecessarily cast when using the default. - if class_name == "Node": - source.append("template <>") - source.append("inline Node *Node::get_node(const NodePath path) const {") - source.append("\treturn get_node_internal(path);") - source.append("}") - source.append("") + source.append("template <>") + source.append("inline Node *Node::get_node(const NodePath path) const {") + source.append("\treturn get_node_internal(path);") + source.append("}") + source.append("") else: source.append("};") source.append("") From 6bca96ed42b03f97f787ba9497c95bf9f65d6f81 Mon Sep 17 00:00:00 2001 From: Duncan Sparks Date: Sun, 23 Aug 2020 09:02:12 -0700 Subject: [PATCH 3/4] Change default parameter to "yes" --- SConstruct | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index 17659731..b63ee57d 100644 --- a/SConstruct +++ b/SConstruct @@ -147,7 +147,7 @@ opts.Add( opts.Add(BoolVariable( 'generate_template_get_node', "Generate a template version of the Node class's get_node.", - False + True )) env = Environment(ENV = os.environ) From a2ebc8bbec0cdc80b2539786f64078930830d464 Mon Sep 17 00:00:00 2001 From: Duncan Sparks Date: Sun, 23 Aug 2020 10:30:27 -0700 Subject: [PATCH 4/4] Update binding_generator.py --- binding_generator.py | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/binding_generator.py b/binding_generator.py index b4bfc2a5..b7cfe81f 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -5,9 +5,10 @@ import json # comment. # Convenience function for using template get_node -def correct_method_name(class_name, method): - if method["name"] == "get_node" and class_name == "Node": - method["name"] = "get_node_internal" +def correct_method_name(method_list): + for method in method_list: + if method["name"] == "get_node": + method["name"] = "get_node_internal" classes = [] @@ -21,7 +22,9 @@ def generate_bindings(path, use_template_get_node): for c in classes: # print c['name'] - used_classes = get_used_classes(c, use_template_get_node) + used_classes = get_used_classes(c) + if use_template_get_node and c["name"] == "Node": + correct_method_name(c["methods"]) header = generate_class_header(used_classes, c, use_template_get_node) @@ -148,8 +151,6 @@ def generate_class_header(used_classes, c, use_template_get_node): source.append("\tstruct ___method_bindings {") for method in c["methods"]: - if use_template_get_node: - correct_method_name(class_name, method) source.append("\t\tgodot_method_bind *mb_" + method["name"] + ";") source.append("\t};") @@ -211,8 +212,6 @@ def generate_class_header(used_classes, c, use_template_get_node): source.append("") for method in c["methods"]: - if use_template_get_node: - correct_method_name(class_name, method) method_signature = "" # TODO decide what to do about virtual methods @@ -383,8 +382,6 @@ def generate_class_implementation(icalls, used_classes, c, use_template_get_node source.append("void " + class_name + "::___init_method_bindings() {") for method in c["methods"]: - if use_template_get_node: - correct_method_name(class_name, method) source.append("\t___mb.mb_" + method["name"] + " = godot::api->godot_method_bind_get_method(\"" + c["name"] + "\", \"" + ("get_node" if use_template_get_node and method["name"] == "get_node_internal" else method["name"]) + "\");") source.append("}") @@ -397,8 +394,6 @@ def generate_class_implementation(icalls, used_classes, c, use_template_get_node source.append("}") for method in c["methods"]: - if use_template_get_node: - correct_method_name(class_name, method) method_signature = "" method_signature += make_gdnative_type(method["return_type"], ref_allowed) @@ -746,11 +741,9 @@ def get_icall_name(sig): -def get_used_classes(c, use_template_get_node): +def get_used_classes(c): classes = [] for method in c["methods"]: - if use_template_get_node: - correct_method_name(strip_name(c["name"]), method) if is_class_type(method["return_type"]) and not (method["return_type"] in classes): classes.append(method["return_type"])