Browse Source

Merge pull request #416 from DuncanSparks/template_get_node

Add option to generate template version of Node::get_node
Marc 5 years ago
parent
commit
824f4ef481
2 changed files with 39 additions and 10 deletions
  1. 6 1
      SConstruct
  2. 33 9
      binding_generator.py

+ 6 - 1
SConstruct

@@ -144,6 +144,11 @@ opts.Add(
     'Path to your Android NDK installation. By default, uses ANDROID_NDK_ROOT from your defined environment variables.',
     'Path to your Android NDK installation. By default, uses ANDROID_NDK_ROOT from your defined environment variables.',
     os.environ.get("ANDROID_NDK_ROOT", None)
     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.",
+	True
+))
 
 
 env = Environment(ENV = os.environ)
 env = Environment(ENV = os.environ)
 opts.Update(env)
 opts.Update(env)
@@ -362,7 +367,7 @@ if env['generate_bindings']:
     # Actually create the bindings here
     # Actually create the bindings here
     import binding_generator
     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 to compile
 sources = []
 sources = []

+ 33 - 9
binding_generator.py

@@ -4,9 +4,16 @@ import json
 
 
 # comment.
 # comment.
 
 
+# Convenience function for using template get_node
+def correct_method_name(method_list):
+    for method in method_list:
+        if method["name"] == "get_node":
+            method["name"] = "get_node_internal"
+
+
 classes = []
 classes = []
 
 
-def generate_bindings(path):
+def generate_bindings(path, use_template_get_node):
 
 
     global classes
     global classes
     classes = json.load(open(path))
     classes = json.load(open(path))
@@ -16,10 +23,12 @@ def generate_bindings(path):
     for c in classes:
     for c in classes:
         # print c['name']
         # print c['name']
         used_classes = get_used_classes(c)
         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)
+        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 = open("include/gen/" + strip_name(c["name"]) + ".hpp", "w+")
         header_file.write(header)
         header_file.write(header)
@@ -62,7 +71,7 @@ def make_gdnative_type(t, ref_allowed):
         return strip_name(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 = []
     source.append("#ifndef GODOT_CPP_" + strip_name(c["name"]).upper() + "_HPP")
     source.append("#ifndef GODOT_CPP_" + strip_name(c["name"]).upper() + "_HPP")
@@ -207,7 +216,6 @@ def generate_class_header(used_classes, c):
         source.append("")
         source.append("")
 
 
     for method in c["methods"]:
     for method in c["methods"]:
-
         method_signature = ""
         method_signature = ""
 
 
         # TODO decide what to do about virtual methods
         # TODO decide what to do about virtual methods
@@ -285,10 +293,26 @@ def generate_class_header(used_classes, c):
         source.append("\t" + method_signature + ";")
         source.append("\t" + method_signature + ";")
 
 
     source.append(vararg_templates)
     source.append(vararg_templates)
-    source.append("};")
-    source.append("")
 
 
+    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.
+        source.append("\ttemplate <class T = Node>")
+        source.append("\tT *get_node(const NodePath path) const {")
+        source.append("\t\treturn Object::cast_to<T>(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.
+        source.append("template <>")
+        source.append("inline Node *Node::get_node<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("}")
     source.append("")
     source.append("")
@@ -302,7 +326,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"])
     class_name = strip_name(c["name"])
 
 
     ref_allowed = class_name != "Object" and class_name != "Reference"
     ref_allowed = class_name != "Object" and class_name != "Reference"
@@ -365,7 +389,7 @@ def generate_class_implementation(icalls, used_classes, c):
     source.append("void " + class_name + "::___init_method_bindings() {")
     source.append("void " + class_name + "::___init_method_bindings() {")
 
 
     for method in c["methods"]:
     for method in c["methods"]:
-        source.append("\t___mb.mb_" + method["name"] + " = godot::api->godot_method_bind_get_method(\"" + c["name"] + "\", \"" + method["name"] + "\");")
+        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("\tgodot_string_name class_name;")
     source.append("\tgodot_string_name class_name;")
     source.append("\tgodot::api->godot_string_name_new_data(&class_name, \"" + c["name"] + "\");")
     source.append("\tgodot::api->godot_string_name_new_data(&class_name, \"" + c["name"] + "\");")