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])