From 7a52122ef736a9525f98c37d3e56c4c3095b61e5 Mon Sep 17 00:00:00 2001 From: Anson Bridges Date: Thu, 15 Sep 2022 16:43:08 -0400 Subject: Script for converting properly formatted .gd to a c++ template --- src/gdn_header_template | 27 ++++++++++ src/gdn_src_template | 17 +++++++ src/script_to_header.py | 127 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+) create mode 100644 src/gdn_header_template create mode 100644 src/gdn_src_template create mode 100644 src/script_to_header.py (limited to 'src') diff --git a/src/gdn_header_template b/src/gdn_header_template new file mode 100644 index 0000000..d6e3d3e --- /dev/null +++ b/src/gdn_header_template @@ -0,0 +1,27 @@ +#ifndef {HEADER_NAME} +#define {HEADER_NAME} + +#include +#include <{BASE_CLASS_NAME}.hpp> + +namespace godot { + +class {CLASS_NAME} : public {BASE_CLASS_NAME} { + GODOT_CLASS({CLASS_NAME}, {BASE_CLASS_NAME}) + +private: +{VARS} + +public: + static void _register_methods(); + + {CLASS_NAME}(); + ~{CLASS_NAME}(); + + void _init(); + +{FUNCS} +}; + +} +#endif diff --git a/src/gdn_src_template b/src/gdn_src_template new file mode 100644 index 0000000..35c86fb --- /dev/null +++ b/src/gdn_src_template @@ -0,0 +1,17 @@ +#include "{NEW_FILE_BASE}.h" + +using namespace godot; + +{CLASS_NAME}::{CLASS_NAME} () { } +{CLASS_NAME}::~{CLASS_NAME} () { } + +void {CLASS_NAME}::_register_methods() { +{REGISTER_METHODS} +{REGISTER_VARS} +} + +void {CLASS_NAME}::_init() { + {INIT_VARS} +} + +{FULL_FUNCS} diff --git a/src/script_to_header.py b/src/script_to_header.py new file mode 100644 index 0000000..452a09d --- /dev/null +++ b/src/script_to_header.py @@ -0,0 +1,127 @@ +import sys +from os.path import exists + +RPC_DICT = {"remote" : "GODOT_METHOD_RPC_MODE_REMOTE", "remotesync" : "GODOT_METHOD_RPC_MODE_REMOTESYNC", \ + "master" : "GODOT_METHOD_RPC_MODE_MASTER", "mastersync" : "GODOT_METHOD_RPC_MODE_MASTERSYNC", \ + "puppet" : "GODOT_METHOD_RPC_MODE_PUPPET", "puppetsync" : "GODOT_METHOD_RPC_MODE_PUPPETSYNC"} + +def script_to_gdn(filename): + if not exists(filename) or not filename.endswith(".gd"): + return + class_name = filename[:-3] + new_file_base = class_name.lower() + header_name = class_name.upper() + "_H" + base_class_name = "Node" + class_vars = [] # {export bool, onready bool, type str, varname str, initialvalue} + funcs = [] # {net type, return type, name, [args], [content]} args = [name, type], content = func content lines list + + script = open(filename, "r") + template_h = open("gdn_header_template", "r") + template_c = open("gdn_src_template", "r") + + header_file_text = template_h.read(); template_h.close(); + src_file_text = template_c.read(); template_c.close(); + + lines = script.readlines() + for I in range(len(lines)): + line = lines[I] + if line.startswith("extends"): + base_class_name = line.split(" ")[-1].strip(); + + if line.startswith("var") or line.startswith("export var") or line.startswith("const") or line.startswith("onready var"): + class_vars.append( [ line.startswith("export"), line.startswith("onready"), line.split(":")[1].split('=')[0].strip(), line.split(":")[0].split(" ")[-1], "" if "=" not in line else line.split("=")[-1].strip() ]) + + if line.startswith("func") or line.startswith("remote") or line.startswith("master") or line.startswith("puppet"): + functype = line[0:line.index(" ")] + + args = line[line.index("(")+1 : line.index(")")].split(",") + for i, arg in enumerate(args): + if arg == "": + args = [] + break + args[i] = [arg.split(":")[0].strip(), arg.split(":")[1].strip()] + + returntype = "void" + if "->" in line: + returntype = line[line.index("->"+1),line.index(":").strip()] + + funcname = line[ line[0:line.index("(")].rindex(" ") : int(line.index("(")) ].strip() + + content = [] + I+=1 + line = lines[I] + while line.startswith('\t'): + content.append(line) + I+=1 + if I != len(lines): + line = lines[I] + else: + line = "EOF" + I-=1 + + funcs.append( [functype, returntype, funcname, args, content] ) + script.close() + + header_file_text = header_file_text.replace("{HEADER_NAME}", header_name).replace("{BASE_CLASS_NAME}", base_class_name).replace("{CLASS_NAME}", class_name) + + var_text = "" + for var in class_vars: + var_text += '\t' + var[2] + " " + var[3] + ";\n" # type varname; + header_file_text = header_file_text.replace("{VARS}", var_text) + + func_text = "" + for func in funcs: + func_text += '\t' + func[1] + " " + func[2] + "(" # type functionname( + for i,arg in enumerate(func[3]): + func_text += arg[1] + " " + arg[0] + if i != len(func[3])-1: + func_text += ", " + func_text += ");\n" + header_file_text = header_file_text.replace("{FUNCS}", func_text) + #print(header_file_text) + with open(new_file_base+".h", "w") as f: + f.write(header_file_text) + + #SOURCE CODE: + src_file_text = src_file_text.replace("{CLASS_NAME}", class_name).replace("{NEW_FILE_BASE}",new_file_base) + + reg_vars = "" + vars_init = "" + vars_ready = "" + for var in class_vars: + if var[0]: #export + reg_vars += "\tregister_property<"+class_name+", "+var[2]+">(\""+var[3]+"\", &"+class_name+"::"+var[3]+", "+var[2]+"("+var[4]+"));\n" + elif var[1]: #onready + vars_ready += "\t"+var[3]+" = "+var[4]+";\n" + else: + vars_init += "\t"+var[3]+" = "+var[4]+";\n" + reg_vars = reg_vars[:-1] + reg_methods = "" + src_func_text = "" + for func in funcs: + reg_methods += "\tregister_method(\"" + func[2]+"\", &"+class_name+"::"+func[2] + if func[0] != "func": + reg_methods += ", " + RPC_DICT[func[0]] + reg_methods += ");\n" + + src_func_text += func[1] + " " + class_name + "::" + func[2] + "(" #returntype ClassName::functionname( + for i,arg in enumerate(func[3]): + src_func_text += arg[1] + " " + arg[0] + if i != len(func[3])-1: + src_func_text += ", " + src_func_text += ") {\n" + if func[2] == "_ready": + src_func_text += vars_ready + src_func_text += "//" + "//".join(func[4]) #join content (commented out) + src_func_text += "}\n\n" + + src_file_text = src_file_text.replace("{INIT_VARS}", vars_init).replace("{REGISTER_METHODS}",reg_methods).replace("{REGISTER_VARS}", reg_vars).replace("{FULL_FUNCS}", src_func_text) + + with open(new_file_base+".cpp", "w") as f: + f.write(src_file_text) + +if __name__ == "__main__": + n = len(sys.argv) + if n != 2: + quit() + script_to_gdn(sys.argv[1]) -- cgit v1.2.3