mirror of
https://github.com/Relintai/utilities_gamedev.git
synced 2024-11-12 10:35:11 +01:00
423 lines
11 KiB
GDScript
423 lines
11 KiB
GDScript
tool
|
|
extends Reference
|
|
|
|
class GDSStaticClassParser:
|
|
var scope_data : String = ""
|
|
var raw_scope_data : String = ""
|
|
var static_methods : PoolStringArray = PoolStringArray()
|
|
|
|
func convert_to_string(current_scope_level : int = 0) -> String:
|
|
var s : String = scope_data + "- (" + raw_scope_data + ")---GDSScope---\n"
|
|
|
|
for m in static_methods:
|
|
s += m + "\n"
|
|
|
|
s += "\n"
|
|
|
|
return s
|
|
|
|
func get_cpp_header_string() -> String:
|
|
var s : String = ""
|
|
|
|
s += "class _" + scope_data + " : public Object {\n"
|
|
s += " GDCLASS(" + scope_data + ", Object);\n\n"
|
|
|
|
s += " public:\n"
|
|
|
|
s += "\n"
|
|
|
|
for m in static_methods:
|
|
s += " " + transform_method_to_cpp(m) + ";\n"
|
|
|
|
s += "\n"
|
|
s += " static _" + scope_data + "* get_singleton();\n"
|
|
s += "\n"
|
|
s += " " + scope_data + "();\n"
|
|
s += " ~" + scope_data + "();\n"
|
|
s += "\n"
|
|
s += " protected:\n"
|
|
s += " static void _bind_methods();\n"
|
|
|
|
s += "\n"
|
|
s += " static _" + scope_data + "* self;\n"
|
|
|
|
s += "\n"
|
|
s += "};"
|
|
s += "\n"
|
|
|
|
return s
|
|
|
|
func get_cpp_impl_string(current_scope_level : int = 0, owner_class_name : String = "") -> String:
|
|
var s : String = ""
|
|
|
|
s += "\n"
|
|
|
|
for m in static_methods:
|
|
#scope_data
|
|
|
|
s += transform_method_to_cpp(m, "_" + scope_data + "::", false) + " {\n"
|
|
s += " " + transform_method_to_cpp_call(m, scope_data + "::") + ";\n"
|
|
s += "}\n\n"
|
|
|
|
s += "_" + scope_data + "* _" + scope_data + "::get_singleton() {\n"
|
|
s += " return self;\n"
|
|
s += "}\n\n"
|
|
|
|
s += "\n"
|
|
|
|
s += "_" + scope_data + "::_" + scope_data + "() {\n"
|
|
s += " self = this;\n"
|
|
s += "}\n\n"
|
|
|
|
s += "_" + scope_data + "::~_" + scope_data + "() {\n"
|
|
s += " self = nullptr;\n"
|
|
s += "}\n\n"
|
|
s += "\n"
|
|
s += "static void _" + scope_data + "::_bind_methods() {\n"
|
|
|
|
s += create_cpp_binds_string()
|
|
|
|
s += "}\n\n"
|
|
|
|
s += "_" + scope_data + "* _" + scope_data + "::self = nullptr;\n"
|
|
|
|
return s
|
|
|
|
func create_cpp_binds_string() -> String:
|
|
var s : String = ""
|
|
|
|
for m in static_methods:
|
|
s += " " + transform_method_to_cpp_binding(m, "_" + scope_data) + ";\n"
|
|
|
|
s += "\n"
|
|
|
|
return s
|
|
|
|
func transform_method_to_cpp(func_raw_data : String, name_prefix : String = "", default_params : bool = true) -> String:
|
|
var func_data : String = func_raw_data
|
|
var func_ret_type : String = "void"
|
|
|
|
var indx : int = func_raw_data.find(" -> ")
|
|
|
|
if indx != -1:
|
|
func_ret_type = func_raw_data.substr(indx + 4)
|
|
func_data = func_raw_data.substr(0, indx)
|
|
|
|
var func_final : String = func_ret_type + " "
|
|
indx = func_data.find("(")
|
|
var func_name : String = func_data.substr(0, indx)
|
|
func_final += name_prefix + func_name + "("
|
|
|
|
var func_params : String = func_data.substr(indx + 1, func_data.length() - indx - 2)
|
|
|
|
if func_params != "":
|
|
var params : PoolStringArray = func_params.split(",", false)
|
|
|
|
for i in range(params.size()):
|
|
var p : String = params[i]
|
|
|
|
var default_value_indx : int = p.find("=")
|
|
var default_value : String
|
|
|
|
if default_value_indx != -1:
|
|
default_value = p.substr(default_value_indx + 1).strip_edges()
|
|
p = p.substr(0, default_value_indx).strip_edges()
|
|
|
|
var type_indx : int = p.find(":")
|
|
|
|
if type_indx != -1:
|
|
var param_type : String = p.substr(type_indx + 1).strip_edges()
|
|
p = p.substr(0, type_indx).strip_edges()
|
|
|
|
if param_type == "int" || param_type == "float" || param_type == "bool" || param_type == "RID":
|
|
func_final += "const " + param_type + " "
|
|
else:
|
|
func_final += "const " + param_type + " &"
|
|
else:
|
|
func_final += "const Variant &"
|
|
|
|
func_final += p
|
|
|
|
if default_params && default_value_indx != -1:
|
|
func_final += " = " + default_value
|
|
|
|
if i + 1 < params.size():
|
|
func_final += ", "
|
|
|
|
func_final += ")"
|
|
|
|
return func_final
|
|
|
|
func transform_method_to_cpp_call(func_raw_data : String, name_prefix : String = "") -> String:
|
|
var func_data : String = func_raw_data
|
|
var func_ret_type : String = "void"
|
|
|
|
var indx : int = func_raw_data.find(" -> ")
|
|
|
|
if indx != -1:
|
|
func_ret_type = func_raw_data.substr(indx + 4)
|
|
func_data = func_raw_data.substr(0, indx)
|
|
|
|
var func_final : String = ""
|
|
|
|
if func_ret_type != "void":
|
|
func_final += "return "
|
|
|
|
indx = func_data.find("(")
|
|
var func_name : String = func_data.substr(0, indx)
|
|
func_final += name_prefix + func_name + "("
|
|
|
|
var func_params : String = func_data.substr(indx + 1, func_data.length() - indx - 2)
|
|
|
|
if func_params != "":
|
|
var params : PoolStringArray = func_params.split(",", false)
|
|
|
|
for i in range(params.size()):
|
|
var p : String = params[i]
|
|
|
|
var default_value_indx : int = p.find("=")
|
|
var default_value : String
|
|
|
|
if default_value_indx != -1:
|
|
default_value = p.substr(default_value_indx + 1).strip_edges()
|
|
p = p.substr(0, default_value_indx).strip_edges()
|
|
|
|
var type_indx : int = p.find(":")
|
|
|
|
if type_indx != -1:
|
|
var param_type : String = p.substr(type_indx + 1).strip_edges()
|
|
p = p.substr(0, type_indx).strip_edges()
|
|
|
|
func_final += p
|
|
|
|
if i + 1 < params.size():
|
|
func_final += ", "
|
|
|
|
func_final += ")"
|
|
|
|
return func_final
|
|
|
|
func transform_method_to_cpp_binding(func_raw_data : String, name_prefix : String) -> String:
|
|
var func_data : String = func_raw_data
|
|
var func_ret_type : String = "void"
|
|
|
|
var indx : int = func_raw_data.find(" -> ")
|
|
|
|
if indx != -1:
|
|
func_ret_type = func_raw_data.substr(indx + 4)
|
|
func_data = func_raw_data.substr(0, indx)
|
|
|
|
var ret_final : String = "ClassDB::bind_method(D_METHOD(\""
|
|
|
|
indx = func_data.find("(")
|
|
var func_name : String = func_data.substr(0, indx)
|
|
ret_final += func_name + "\""
|
|
|
|
var func_params : String = func_data.substr(indx + 1, func_data.length() - indx - 2)
|
|
|
|
var default_values : PoolStringArray = PoolStringArray()
|
|
|
|
if func_params != "":
|
|
var params : PoolStringArray = func_params.split(",", false)
|
|
|
|
for i in range(params.size()):
|
|
ret_final += ", "
|
|
|
|
var p : String = params[i]
|
|
|
|
var default_value_indx : int = p.find("=")
|
|
var default_value : String
|
|
|
|
if default_value_indx != -1:
|
|
default_value = p.substr(default_value_indx + 1).strip_edges()
|
|
p = p.substr(0, default_value_indx).strip_edges()
|
|
default_values.push_back(default_value)
|
|
|
|
var type_indx : int = p.find(":")
|
|
|
|
if type_indx != -1:
|
|
var param_type : String = p.substr(type_indx + 1).strip_edges()
|
|
p = p.substr(0, type_indx).strip_edges()
|
|
|
|
ret_final += "\"" + p + "\""
|
|
|
|
ret_final += "), &" + name_prefix + "::" + func_name
|
|
|
|
for i in range(default_values.size()):
|
|
ret_final += ", " + default_values[i]
|
|
|
|
ret_final += ");"
|
|
|
|
return ret_final
|
|
|
|
func camel_case_scope_data() -> void:
|
|
scope_data = camel_case_name(scope_data)
|
|
|
|
func camel_case_name(cname : String) -> String:
|
|
var ret : String = ""
|
|
|
|
var next_upper : bool = true
|
|
for i in range(cname.length()):
|
|
if cname[i] == "_":
|
|
next_upper = true
|
|
continue
|
|
|
|
if next_upper:
|
|
ret += cname[i].to_upper()
|
|
next_upper = false
|
|
else:
|
|
ret += cname[i]
|
|
|
|
return ret
|
|
|
|
func _to_string():
|
|
return convert_to_string()
|
|
|
|
func parse(contentsstr : String, file_name : String) -> void:
|
|
raw_scope_data = file_name
|
|
scope_data = file_name.get_file().trim_suffix(".gd")
|
|
camel_case_scope_data()
|
|
|
|
var contents : PoolStringArray = split_preprocess_content(contentsstr)
|
|
|
|
for current_index in range(contents.size()):
|
|
var cl : String = contents[current_index]
|
|
|
|
if cl.begins_with("class_name "):
|
|
raw_scope_data = cl
|
|
scope_data = cl.trim_prefix("class_name ")
|
|
continue
|
|
|
|
if cl.begins_with("#"):
|
|
continue
|
|
|
|
var clstripped : String = cl.strip_edges(true, false)
|
|
|
|
if clstripped.begins_with("static func "):
|
|
static_methods.push_back(clstripped.trim_prefix("static func ").trim_suffix(":"))
|
|
|
|
|
|
func split_preprocess_content(contents : String) -> PoolStringArray:
|
|
var ret : PoolStringArray = PoolStringArray()
|
|
|
|
contents = contents.replace("\r\n", "\n")
|
|
|
|
var sp : PoolStringArray = contents.split("\n")
|
|
|
|
var pl : String = ""
|
|
var accum : bool = false
|
|
for i in range(sp.size()):
|
|
var l : String = sp[i]
|
|
l = l.strip_edges(false, true)
|
|
|
|
var lfstrip : String = l.strip_edges(true, false)
|
|
if lfstrip == "":
|
|
continue
|
|
|
|
if lfstrip.begins_with("#"):
|
|
ret.append(lfstrip)
|
|
continue
|
|
|
|
if lfstrip.begins_with("export"):
|
|
var indx = lfstrip.find("var")
|
|
var expstr : String = lfstrip.substr(0, indx)
|
|
|
|
ret.append("#" + expstr)
|
|
l = l.replace(expstr, "")
|
|
|
|
var setget_indx = l.find(" setget ")
|
|
if setget_indx != -1:
|
|
var setget_str : String = l.substr(setget_indx)
|
|
ret.append("#" + setget_str)
|
|
l = l.substr(0, setget_indx).strip_edges(false, true)
|
|
|
|
var hash_symbol_index = l.find("#")
|
|
if hash_symbol_index != -1:
|
|
var comment_str : String = l.substr(hash_symbol_index)
|
|
ret.append(comment_str)
|
|
l = l.substr(0, hash_symbol_index).strip_edges(false, true)
|
|
|
|
if l.ends_with("\\"):
|
|
if !accum:
|
|
accum = true
|
|
pl = l
|
|
else:
|
|
pl += l.substr(0, l.length() - 1).strip_edges()
|
|
else:
|
|
if accum:
|
|
accum = false
|
|
ret.append(pl)
|
|
pl = ""
|
|
else:
|
|
ret.append(l)
|
|
|
|
return ret
|
|
|
|
func get_final_cpp_header_string(file_name : String) -> String:
|
|
var include_guard_name : String = file_name.get_file()
|
|
include_guard_name = include_guard_name.to_upper()
|
|
include_guard_name = include_guard_name.trim_suffix(".GD")
|
|
include_guard_name += "_BIND_H"
|
|
|
|
var s : String = "#ifndef " + include_guard_name + "\n"
|
|
s += "#define " + include_guard_name + "\n"
|
|
s += "\n\n"
|
|
|
|
s += get_cpp_header_string()
|
|
|
|
s += "\n\n"
|
|
s += "#endif"
|
|
s += "\n"
|
|
|
|
s = s.replace(";;", ";")
|
|
|
|
return s
|
|
|
|
func get_final_cpp_impl_string(file_name : String) -> String:
|
|
var include_name : String = file_name.get_file()
|
|
include_name = include_name.to_lower()
|
|
include_name = include_name.trim_suffix(".gd")
|
|
include_name += "_bind.h"
|
|
|
|
var s : String = "\n"
|
|
s += "#include \"" + include_name + "\"\n"
|
|
s += "\n\n"
|
|
|
|
s += get_cpp_impl_string()
|
|
|
|
s += "\n\n"
|
|
|
|
s = s.replace(";;", ";")
|
|
|
|
return s
|
|
|
|
func process_file(file_name : String) -> void:
|
|
var file : File = File.new()
|
|
file.open(file_name, File.READ)
|
|
var contents : String = file.get_as_text()
|
|
file.close()
|
|
|
|
var parser : GDSStaticClassParser = GDSStaticClassParser.new()
|
|
parser.parse(contents, file_name)
|
|
#print(parser)
|
|
#print(parser.get_cpp_header_string(file_name))
|
|
#print(parser.get_cpp_impl_string(file_name))
|
|
|
|
var save_base_file_path : String = file_name.get_base_dir()
|
|
var save_base_file_name : String = file_name.get_file().to_lower().trim_suffix(".gd")
|
|
|
|
var header_file : String = save_base_file_path + "/" + save_base_file_name + "_bind.h"
|
|
var impl_file : String = save_base_file_path + "/" + save_base_file_name + "_bind.cpp"
|
|
|
|
var header_data : String = parser.get_final_cpp_header_string(file_name)
|
|
var impl_data : String = parser.get_final_cpp_impl_string(file_name)
|
|
|
|
file.open(header_file, File.WRITE)
|
|
file.store_string(header_data)
|
|
file.close()
|
|
|
|
file.open(impl_file, File.WRITE)
|
|
file.store_string(impl_data)
|
|
file.close()
|
|
|