|
@@ -48,7 +48,7 @@
|
|
|
#include "csharp_project.h"
|
|
|
#include "net_solution.h"
|
|
|
|
|
|
-#define CS_INDENT " "
|
|
|
+#define CS_INDENT " " // 4 whitespaces
|
|
|
|
|
|
#define INDENT1 CS_INDENT
|
|
|
#define INDENT2 INDENT1 INDENT1
|
|
@@ -68,23 +68,18 @@
|
|
|
#define CLOSE_BLOCK_L3 INDENT3 CLOSE_BLOCK
|
|
|
#define CLOSE_BLOCK_L4 INDENT4 CLOSE_BLOCK
|
|
|
|
|
|
-#define LOCAL_RET "ret"
|
|
|
-
|
|
|
#define CS_FIELD_MEMORYOWN "memoryOwn"
|
|
|
#define CS_PARAM_METHODBIND "method"
|
|
|
#define CS_PARAM_INSTANCE "ptr"
|
|
|
#define CS_SMETHOD_GETINSTANCE "GetPtr"
|
|
|
-#define CS_FIELD_SINGLETON "instance"
|
|
|
-#define CS_PROP_SINGLETON "Instance"
|
|
|
-#define CS_CLASS_SIGNALAWAITER "SignalAwaiter"
|
|
|
#define CS_METHOD_CALL "Call"
|
|
|
|
|
|
#define GLUE_HEADER_FILE "glue_header.h"
|
|
|
#define ICALL_PREFIX "godot_icall_"
|
|
|
#define SINGLETON_ICALL_SUFFIX "_get_singleton"
|
|
|
-#define ICALL_GET_METHODBIND ICALL_PREFIX "ClassDB_get_method"
|
|
|
-#define ICALL_CONNECT_SIGNAL_AWAITER ICALL_PREFIX "Object_connect_signal_awaiter"
|
|
|
-#define ICALL_OBJECT_DTOR ICALL_PREFIX "Object_Dtor"
|
|
|
+#define ICALL_GET_METHODBIND ICALL_PREFIX "Object_ClassDB_get_method"
|
|
|
+
|
|
|
+#define C_LOCAL_RET "ret"
|
|
|
#define C_LOCAL_PTRCALL_ARGS "call_args"
|
|
|
#define C_MACRO_OBJECT_CONSTRUCT "GODOTSHARP_INSTANCE_OBJECT"
|
|
|
|
|
@@ -101,7 +96,7 @@
|
|
|
#define C_METHOD_MONOARRAY_TO(m_type) C_NS_MONOMARSHAL "::mono_array_to_" #m_type
|
|
|
#define C_METHOD_MONOARRAY_FROM(m_type) C_NS_MONOMARSHAL "::" #m_type "_to_mono_array"
|
|
|
|
|
|
-#define BINDINGS_GENERATOR_VERSION UINT32_C(2)
|
|
|
+#define BINDINGS_GENERATOR_VERSION UINT32_C(3)
|
|
|
|
|
|
const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN = "\t%0 %1_in = %1;\n";
|
|
|
|
|
@@ -196,48 +191,6 @@ String BindingsGenerator::_determine_enum_prefix(const EnumInterface &p_ienum) {
|
|
|
return front->get().name.substr(0, candidate_len);
|
|
|
}
|
|
|
|
|
|
-void BindingsGenerator::_generate_header_icalls() {
|
|
|
-
|
|
|
- core_custom_icalls.clear();
|
|
|
-
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_GET_METHODBIND, "IntPtr", "string type, string method"));
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_OBJECT_DTOR, "void", "object obj, IntPtr ptr"));
|
|
|
-
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_CONNECT_SIGNAL_AWAITER, "Error",
|
|
|
- "IntPtr source, string signal, IntPtr target, " CS_CLASS_SIGNALAWAITER " awaiter"));
|
|
|
-
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "NodePath_Ctor", "IntPtr", "string path"));
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "NodePath_Dtor", "void", "IntPtr ptr"));
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "NodePath_operator_String", "string", "IntPtr ptr"));
|
|
|
-
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "RID_Ctor", "IntPtr", "IntPtr from"));
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "RID_Dtor", "void", "IntPtr ptr"));
|
|
|
-
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "String_md5_buffer", "byte[]", "string str"));
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "String_md5_text", "string", "string str"));
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "String_rfind", "int", "string str, string what, int from"));
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "String_rfindn", "int", "string str, string what, int from"));
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "String_sha256_buffer", "byte[]", "string str"));
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "String_sha256_text", "string", "string str"));
|
|
|
-
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_bytes2var", "object", "byte[] bytes"));
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_convert", "object", "object what, int type"));
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_hash", "int", "object var"));
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_instance_from_id", "Object", "int instance_id"));
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_print", "void", "object[] what"));
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_printerr", "void", "object[] what"));
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_printraw", "void", "object[] what"));
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_prints", "void", "object[] what"));
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_printt", "void", "object[] what"));
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_seed", "void", "int seed"));
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_str", "string", "object[] what"));
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_str2var", "object", "string str"));
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_type_exists", "bool", "string type"));
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_var2bytes", "byte[]", "object what"));
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_var2str", "string", "object var"));
|
|
|
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_weakref", "WeakRef", "IntPtr obj"));
|
|
|
-}
|
|
|
-
|
|
|
void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
|
|
|
|
|
|
for (const List<MethodInterface>::Element *E = p_itype.methods.front(); E; E = E->next()) {
|
|
@@ -248,13 +201,8 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
|
|
|
|
|
|
const TypeInterface *return_type = _get_type_or_placeholder(imethod.return_type);
|
|
|
|
|
|
- String im_sig;
|
|
|
- String im_unique_sig;
|
|
|
-
|
|
|
- if (p_itype.is_object_type) {
|
|
|
- im_sig += "IntPtr " CS_PARAM_METHODBIND ", ";
|
|
|
- im_unique_sig += imethod.return_type.cname.operator String() + ",IntPtr,IntPtr";
|
|
|
- }
|
|
|
+ String im_sig = "IntPtr " CS_PARAM_METHODBIND ", ";
|
|
|
+ String im_unique_sig = imethod.return_type.cname.operator String() + ",IntPtr,IntPtr";
|
|
|
|
|
|
im_sig += "IntPtr " CS_PARAM_INSTANCE;
|
|
|
|
|
@@ -268,37 +216,28 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
|
|
|
im_sig += " arg";
|
|
|
im_sig += itos(i + 1);
|
|
|
|
|
|
- if (p_itype.is_object_type) {
|
|
|
- im_unique_sig += ",";
|
|
|
- im_unique_sig += get_unique_sig(*arg_type);
|
|
|
- }
|
|
|
+ im_unique_sig += ",";
|
|
|
+ im_unique_sig += get_unique_sig(*arg_type);
|
|
|
|
|
|
i++;
|
|
|
}
|
|
|
|
|
|
+ // godot_icall_{argc}_{icallcount}
|
|
|
String icall_method = ICALL_PREFIX;
|
|
|
-
|
|
|
- if (p_itype.is_object_type) {
|
|
|
- icall_method += itos(imethod.arguments.size()) + "_" + itos(method_icalls.size()); // godot_icall_{argc}_{icallcount}
|
|
|
- } else {
|
|
|
- icall_method += p_itype.name + "_" + imethod.name; // godot_icall_{Type}_{method}
|
|
|
- }
|
|
|
+ icall_method += itos(imethod.arguments.size());
|
|
|
+ icall_method += "_";
|
|
|
+ icall_method += itos(method_icalls.size());
|
|
|
|
|
|
InternalCall im_icall = InternalCall(p_itype.api_type, icall_method, return_type->im_type_out, im_sig, im_unique_sig);
|
|
|
|
|
|
- if (p_itype.is_object_type) {
|
|
|
- List<InternalCall>::Element *match = method_icalls.find(im_icall);
|
|
|
+ List<InternalCall>::Element *match = method_icalls.find(im_icall);
|
|
|
|
|
|
- if (match) {
|
|
|
- if (p_itype.api_type != ClassDB::API_EDITOR)
|
|
|
- match->get().editor_only = false;
|
|
|
- method_icalls_map.insert(&E->get(), &match->get());
|
|
|
- } else {
|
|
|
- List<InternalCall>::Element *added = method_icalls.push_back(im_icall);
|
|
|
- method_icalls_map.insert(&E->get(), &added->get());
|
|
|
- }
|
|
|
+ if (match) {
|
|
|
+ if (p_itype.api_type != ClassDB::API_EDITOR)
|
|
|
+ match->get().editor_only = false;
|
|
|
+ method_icalls_map.insert(&E->get(), &match->get());
|
|
|
} else {
|
|
|
- List<InternalCall>::Element *added = builtin_method_icalls.push_back(im_icall);
|
|
|
+ List<InternalCall>::Element *added = method_icalls.push_back(im_icall);
|
|
|
method_icalls_map.insert(&E->get(), &added->get());
|
|
|
}
|
|
|
}
|
|
@@ -483,20 +422,6 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo
|
|
|
compile_items.push_back(output_file);
|
|
|
}
|
|
|
|
|
|
-#define GENERATE_BUILTIN_TYPE(m_name) \
|
|
|
- { \
|
|
|
- String output_file = path_join(core_dir, #m_name ".cs"); \
|
|
|
- Error err = _generate_cs_type(builtin_types[#m_name], output_file); \
|
|
|
- if (err != OK) \
|
|
|
- return err; \
|
|
|
- compile_items.push_back(output_file); \
|
|
|
- }
|
|
|
-
|
|
|
- GENERATE_BUILTIN_TYPE(NodePath);
|
|
|
- GENERATE_BUILTIN_TYPE(RID);
|
|
|
-
|
|
|
-#undef GENERATE_BUILTIN_TYPE
|
|
|
-
|
|
|
// Generate sources from compressed files
|
|
|
|
|
|
Map<String, CompressedFile> compressed_files;
|
|
@@ -537,29 +462,26 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo
|
|
|
cs_icalls_content.push_back("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
|
|
|
cs_icalls_content.push_back(INDENT1 "internal static class " BINDINGS_CLASS_NATIVECALLS "\n" INDENT1 OPEN_BLOCK);
|
|
|
|
|
|
- cs_icalls_content.push_back(INDENT2 "internal static ulong godot_api_hash = ");
|
|
|
+ cs_icalls_content.push_back(MEMBER_BEGIN "internal static ulong godot_api_hash = ");
|
|
|
cs_icalls_content.push_back(String::num_uint64(GDMono::get_singleton()->get_api_core_hash()) + ";\n");
|
|
|
- cs_icalls_content.push_back(INDENT2 "internal static uint bindings_version = ");
|
|
|
+ cs_icalls_content.push_back(MEMBER_BEGIN "internal static uint bindings_version = ");
|
|
|
cs_icalls_content.push_back(String::num_uint64(BINDINGS_GENERATOR_VERSION) + ";\n");
|
|
|
- cs_icalls_content.push_back(INDENT2 "internal static uint cs_glue_version = ");
|
|
|
+ cs_icalls_content.push_back(MEMBER_BEGIN "internal static uint cs_glue_version = ");
|
|
|
cs_icalls_content.push_back(String::num_uint64(CS_GLUE_VERSION) + ";\n");
|
|
|
- cs_icalls_content.push_back("\n");
|
|
|
|
|
|
-#define ADD_INTERNAL_CALL(m_icall) \
|
|
|
- if (!m_icall.editor_only) { \
|
|
|
- cs_icalls_content.push_back(INDENT2 "[MethodImpl(MethodImplOptions.InternalCall)]\n"); \
|
|
|
- cs_icalls_content.push_back(INDENT2 "internal extern static "); \
|
|
|
- cs_icalls_content.push_back(m_icall.im_type_out + " "); \
|
|
|
- cs_icalls_content.push_back(m_icall.name + "("); \
|
|
|
- cs_icalls_content.push_back(m_icall.im_sig + ");\n"); \
|
|
|
+#define ADD_INTERNAL_CALL(m_icall) \
|
|
|
+ if (!m_icall.editor_only) { \
|
|
|
+ cs_icalls_content.push_back(MEMBER_BEGIN "[MethodImpl(MethodImplOptions.InternalCall)]\n"); \
|
|
|
+ cs_icalls_content.push_back(INDENT2 "internal extern static "); \
|
|
|
+ cs_icalls_content.push_back(m_icall.im_type_out + " "); \
|
|
|
+ cs_icalls_content.push_back(m_icall.name + "("); \
|
|
|
+ cs_icalls_content.push_back(m_icall.im_sig + ");\n"); \
|
|
|
}
|
|
|
|
|
|
for (const List<InternalCall>::Element *E = core_custom_icalls.front(); E; E = E->next())
|
|
|
ADD_INTERNAL_CALL(E->get());
|
|
|
for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next())
|
|
|
ADD_INTERNAL_CALL(E->get());
|
|
|
- for (const List<InternalCall>::Element *E = builtin_method_icalls.front(); E; E = E->next())
|
|
|
- ADD_INTERNAL_CALL(E->get());
|
|
|
|
|
|
#undef ADD_INTERNAL_CALL
|
|
|
|
|
@@ -658,8 +580,6 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir,
|
|
|
cs_icalls_content.push_back(m_icall.im_sig + ");\n"); \
|
|
|
}
|
|
|
|
|
|
- // No need to add builtin_method_icalls. Builtin types are core only
|
|
|
-
|
|
|
for (const List<InternalCall>::Element *E = editor_custom_icalls.front(); E; E = E->next())
|
|
|
ADD_INTERNAL_CALL(E->get());
|
|
|
for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next())
|
|
@@ -693,18 +613,34 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir,
|
|
|
return OK;
|
|
|
}
|
|
|
|
|
|
-// TODO: there are constants that hide inherited members. must explicitly use `new` to avoid warnings
|
|
|
-// e.g.: warning CS0108: 'SpriteBase3D.FLAG_MAX' hides inherited member 'GeometryInstance.FLAG_MAX'. Use the new keyword if hiding was intended.
|
|
|
+// FIXME: There are some members that hide other inherited members.
|
|
|
+// - In the case of both members being the same kind, the new one must be declared
|
|
|
+// explicitly as `new` to avoid the warning (and we must print a message about it).
|
|
|
+// - In the case of both members being of a different kind, then the new one must
|
|
|
+// be renamed to avoid the name collision (and we must print a warning about it).
|
|
|
+// - Csc warning e.g.:
|
|
|
+// ObjectType/LineEdit.cs(140,38): warning CS0108: 'LineEdit.FocusMode' hides inherited member 'Control.FocusMode'. Use the new keyword if hiding was intended.
|
|
|
Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const String &p_output_file) {
|
|
|
|
|
|
+ CRASH_COND(!itype.is_object_type);
|
|
|
+
|
|
|
bool is_derived_type = itype.base_name != StringName();
|
|
|
|
|
|
+ if (!is_derived_type) {
|
|
|
+ // Some Godot.Object assertions
|
|
|
+ CRASH_COND(itype.cname != name_cache.type_Object);
|
|
|
+ CRASH_COND(!itype.is_instantiable);
|
|
|
+ CRASH_COND(itype.api_type != ClassDB::API_CORE);
|
|
|
+ CRASH_COND(itype.is_reference);
|
|
|
+ CRASH_COND(itype.is_singleton);
|
|
|
+ }
|
|
|
+
|
|
|
List<InternalCall> &custom_icalls = itype.api_type == ClassDB::API_EDITOR ? editor_custom_icalls : core_custom_icalls;
|
|
|
|
|
|
if (verbose_output)
|
|
|
OS::get_singleton()->print(String("Generating " + itype.proxy_name + ".cs...\n").utf8());
|
|
|
|
|
|
- String ctor_method(ICALL_PREFIX + itype.proxy_name + "_Ctor");
|
|
|
+ String ctor_method(ICALL_PREFIX + itype.proxy_name + "_Ctor"); // Used only for derived types
|
|
|
|
|
|
List<String> output;
|
|
|
|
|
@@ -733,28 +669,24 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
|
|
|
}
|
|
|
|
|
|
output.push_back(INDENT1 "public ");
|
|
|
- if (itype.is_object_type) {
|
|
|
- if (itype.is_singleton) {
|
|
|
- output.push_back("static partial class ");
|
|
|
- } else {
|
|
|
- output.push_back(itype.is_instantiable ? "partial class " : "abstract partial class ");
|
|
|
- }
|
|
|
+ if (itype.is_singleton) {
|
|
|
+ output.push_back("static partial class ");
|
|
|
} else {
|
|
|
- output.push_back("partial class ");
|
|
|
+ output.push_back(itype.is_instantiable ? "partial class " : "abstract partial class ");
|
|
|
}
|
|
|
output.push_back(itype.proxy_name);
|
|
|
|
|
|
if (itype.is_singleton) {
|
|
|
output.push_back("\n");
|
|
|
- } else if (!is_derived_type || !itype.is_object_type /* assuming only object types inherit */) {
|
|
|
- output.push_back(" : IDisposable\n");
|
|
|
- } else if (obj_types.has(itype.base_name)) {
|
|
|
- output.push_back(" : ");
|
|
|
- output.push_back(obj_types[itype.base_name].proxy_name);
|
|
|
- output.push_back("\n");
|
|
|
- } else {
|
|
|
- ERR_PRINTS("Base type '" + itype.base_name.operator String() + "' does not exist, for class " + itype.name);
|
|
|
- return ERR_INVALID_DATA;
|
|
|
+ } else if (is_derived_type) {
|
|
|
+ if (obj_types.has(itype.base_name)) {
|
|
|
+ output.push_back(" : ");
|
|
|
+ output.push_back(obj_types[itype.base_name].proxy_name);
|
|
|
+ output.push_back("\n");
|
|
|
+ } else {
|
|
|
+ ERR_PRINTS("Base type '" + itype.base_name.operator String() + "' does not exist, for class " + itype.name);
|
|
|
+ return ERR_INVALID_DATA;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
output.push_back(INDENT1 "{");
|
|
@@ -851,9 +783,6 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
|
|
|
output.push_back(INDENT2 CLOSE_BLOCK);
|
|
|
}
|
|
|
|
|
|
- if (itype.enums.size())
|
|
|
- output.push_back("\n");
|
|
|
-
|
|
|
// Add properties
|
|
|
|
|
|
for (const List<PropertyInterface>::Element *E = itype.properties.front(); E; E = E->next()) {
|
|
@@ -865,43 +794,9 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
|
|
|
ERR_FAIL_V(prop_err);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- if (class_doc->properties.size())
|
|
|
- output.push_back("\n");
|
|
|
}
|
|
|
|
|
|
- if (!itype.is_object_type) {
|
|
|
- output.push_back(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \"" + itype.name + "\";\n");
|
|
|
- output.push_back(MEMBER_BEGIN "private bool disposed = false;\n");
|
|
|
- output.push_back(MEMBER_BEGIN "internal IntPtr " BINDINGS_PTR_FIELD ";\n");
|
|
|
-
|
|
|
- output.push_back(MEMBER_BEGIN "internal static IntPtr " CS_SMETHOD_GETINSTANCE "(");
|
|
|
- output.push_back(itype.proxy_name);
|
|
|
- output.push_back(" instance)\n" OPEN_BLOCK_L2 "return instance == null ? IntPtr.Zero : instance." BINDINGS_PTR_FIELD ";\n" CLOSE_BLOCK_L2);
|
|
|
-
|
|
|
- // Add Destructor
|
|
|
- output.push_back(MEMBER_BEGIN "~");
|
|
|
- output.push_back(itype.proxy_name);
|
|
|
- output.push_back("()\n" OPEN_BLOCK_L2 "Dispose(false);\n" CLOSE_BLOCK_L2);
|
|
|
-
|
|
|
- // Add the Dispose from IDisposable
|
|
|
- output.push_back(MEMBER_BEGIN "public void Dispose()\n" OPEN_BLOCK_L2 "Dispose(true);\n" INDENT3 "GC.SuppressFinalize(this);\n" CLOSE_BLOCK_L2);
|
|
|
-
|
|
|
- // Add the virtual Dispose
|
|
|
- output.push_back(MEMBER_BEGIN "protected virtual void Dispose(bool disposing)\n" OPEN_BLOCK_L2
|
|
|
- "if (disposed) return;\n" INDENT3
|
|
|
- "if (" BINDINGS_PTR_FIELD " != IntPtr.Zero)\n" OPEN_BLOCK_L3 "NativeCalls.godot_icall_");
|
|
|
- output.push_back(itype.proxy_name);
|
|
|
- output.push_back("_Dtor(" BINDINGS_PTR_FIELD ");\n" INDENT5 BINDINGS_PTR_FIELD " = IntPtr.Zero;\n" CLOSE_BLOCK_L3 INDENT3
|
|
|
- "GC.SuppressFinalize(this);\n" INDENT3 "disposed = true;\n" CLOSE_BLOCK_L2);
|
|
|
-
|
|
|
- output.push_back(MEMBER_BEGIN "internal ");
|
|
|
- output.push_back(itype.proxy_name);
|
|
|
- output.push_back("(IntPtr " BINDINGS_PTR_FIELD ")\n" OPEN_BLOCK_L2 "this." BINDINGS_PTR_FIELD " = " BINDINGS_PTR_FIELD ";\n" CLOSE_BLOCK_L2);
|
|
|
-
|
|
|
- output.push_back(MEMBER_BEGIN "public IntPtr NativeInstance\n" OPEN_BLOCK_L2
|
|
|
- "get { return " BINDINGS_PTR_FIELD "; }\n" CLOSE_BLOCK_L2);
|
|
|
- } else if (itype.is_singleton) {
|
|
|
+ if (itype.is_singleton) {
|
|
|
// Add the type name and the singleton pointer as static fields
|
|
|
|
|
|
output.push_back(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \"");
|
|
@@ -913,21 +808,13 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
|
|
|
output.push_back("." ICALL_PREFIX);
|
|
|
output.push_back(itype.name);
|
|
|
output.push_back(SINGLETON_ICALL_SUFFIX "();\n");
|
|
|
- } else {
|
|
|
+ } else if (is_derived_type) {
|
|
|
// Add member fields
|
|
|
|
|
|
output.push_back(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \"");
|
|
|
output.push_back(itype.name);
|
|
|
output.push_back("\";\n");
|
|
|
|
|
|
- // Only the base class stores the pointer to the native object
|
|
|
- // This pointer is expected to be and must be of type Object*
|
|
|
- if (!is_derived_type) {
|
|
|
- output.push_back(MEMBER_BEGIN "private bool disposed = false;\n");
|
|
|
- output.push_back(INDENT2 "internal IntPtr " BINDINGS_PTR_FIELD ";\n");
|
|
|
- output.push_back(INDENT2 "internal bool " CS_FIELD_MEMORYOWN ";\n");
|
|
|
- }
|
|
|
-
|
|
|
// Add default constructor
|
|
|
if (itype.is_instantiable) {
|
|
|
output.push_back(MEMBER_BEGIN "public ");
|
|
@@ -952,67 +839,9 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
|
|
|
// Add.. em.. trick constructor. Sort of.
|
|
|
output.push_back(MEMBER_BEGIN "internal ");
|
|
|
output.push_back(itype.proxy_name);
|
|
|
- if (is_derived_type) {
|
|
|
- output.push_back("(bool " CS_FIELD_MEMORYOWN ") : base(" CS_FIELD_MEMORYOWN ") {}\n");
|
|
|
- } else {
|
|
|
- output.push_back("(bool " CS_FIELD_MEMORYOWN ")\n" OPEN_BLOCK_L2
|
|
|
- "this." CS_FIELD_MEMORYOWN " = " CS_FIELD_MEMORYOWN ";\n" CLOSE_BLOCK_L2);
|
|
|
- }
|
|
|
-
|
|
|
- // Add methods
|
|
|
-
|
|
|
- if (!is_derived_type) {
|
|
|
- output.push_back(MEMBER_BEGIN "public IntPtr NativeInstance\n" OPEN_BLOCK_L2
|
|
|
- "get { return " BINDINGS_PTR_FIELD "; }\n" CLOSE_BLOCK_L2);
|
|
|
-
|
|
|
- output.push_back(MEMBER_BEGIN "internal static IntPtr " CS_SMETHOD_GETINSTANCE "(Object instance)\n" OPEN_BLOCK_L2
|
|
|
- "return instance == null ? IntPtr.Zero : instance." BINDINGS_PTR_FIELD ";\n" CLOSE_BLOCK_L2);
|
|
|
- }
|
|
|
-
|
|
|
- if (!is_derived_type) {
|
|
|
- // Add destructor
|
|
|
- output.push_back(MEMBER_BEGIN "~");
|
|
|
- output.push_back(itype.proxy_name);
|
|
|
- output.push_back("()\n" OPEN_BLOCK_L2 "Dispose(false);\n" CLOSE_BLOCK_L2);
|
|
|
-
|
|
|
- // Add the Dispose from IDisposable
|
|
|
- output.push_back(MEMBER_BEGIN "public void Dispose()\n" OPEN_BLOCK_L2 "Dispose(true);\n" INDENT3 "GC.SuppressFinalize(this);\n" CLOSE_BLOCK_L2);
|
|
|
-
|
|
|
- // Add the virtual Dispose
|
|
|
- output.push_back(MEMBER_BEGIN "protected virtual void Dispose(bool disposing)\n" OPEN_BLOCK_L2
|
|
|
- "if (disposed) return;\n" INDENT3
|
|
|
- "if (" BINDINGS_PTR_FIELD " != IntPtr.Zero)\n" OPEN_BLOCK_L3
|
|
|
- "if (" CS_FIELD_MEMORYOWN ")\n" OPEN_BLOCK_L4 CS_FIELD_MEMORYOWN
|
|
|
- " = false;\n" INDENT5 BINDINGS_CLASS_NATIVECALLS "." ICALL_OBJECT_DTOR
|
|
|
- "(this, " BINDINGS_PTR_FIELD ");\n" CLOSE_BLOCK_L4 CLOSE_BLOCK_L3 INDENT3
|
|
|
- "this." BINDINGS_PTR_FIELD " = IntPtr.Zero;\n" INDENT3
|
|
|
- "GC.SuppressFinalize(this);\n" INDENT3 "disposed = true;\n" CLOSE_BLOCK_L2);
|
|
|
-
|
|
|
- Map<StringName, TypeInterface>::Element *array_itype = builtin_types.find(name_cache.type_Array);
|
|
|
-
|
|
|
- if (!array_itype) {
|
|
|
- ERR_PRINT("BUG: Array type interface not found!");
|
|
|
- return ERR_BUG;
|
|
|
- }
|
|
|
-
|
|
|
- OrderedHashMap<StringName, TypeInterface>::Element object_itype = obj_types.find("Object");
|
|
|
-
|
|
|
- if (!object_itype) {
|
|
|
- ERR_PRINT("BUG: Object type interface not found!");
|
|
|
- return ERR_BUG;
|
|
|
- }
|
|
|
-
|
|
|
- output.push_back(MEMBER_BEGIN "public " CS_CLASS_SIGNALAWAITER " ToSignal(");
|
|
|
- output.push_back(object_itype.get().cs_type);
|
|
|
- output.push_back(" source, string signal)\n" OPEN_BLOCK_L2
|
|
|
- "return new " CS_CLASS_SIGNALAWAITER "(source, signal, this);\n" CLOSE_BLOCK_L2);
|
|
|
- }
|
|
|
+ output.push_back("(bool " CS_FIELD_MEMORYOWN ") : base(" CS_FIELD_MEMORYOWN ") {}\n");
|
|
|
}
|
|
|
|
|
|
- Map<StringName, String>::Element *extra_member = extra_members.find(itype.cname);
|
|
|
- if (extra_member)
|
|
|
- output.push_back(extra_member->get());
|
|
|
-
|
|
|
int method_bind_count = 0;
|
|
|
for (const List<MethodInterface>::Element *E = itype.methods.front(); E; E = E->next()) {
|
|
|
const MethodInterface &imethod = E->get();
|
|
@@ -1030,7 +859,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
|
|
|
custom_icalls.push_back(singleton_icall);
|
|
|
}
|
|
|
|
|
|
- if (itype.is_instantiable) {
|
|
|
+ if (is_derived_type && itype.is_instantiable) {
|
|
|
InternalCall ctor_icall = InternalCall(itype.api_type, ctor_method, "IntPtr", itype.proxy_name + " obj");
|
|
|
|
|
|
if (!find_icall_by_name(ctor_icall.name, custom_icalls))
|
|
@@ -1178,9 +1007,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
|
|
|
String arguments_sig;
|
|
|
String cs_in_statements;
|
|
|
|
|
|
- String icall_params;
|
|
|
- if (p_itype.is_object_type)
|
|
|
- icall_params += method_bind_field + ", ";
|
|
|
+ String icall_params = method_bind_field + ", ";
|
|
|
icall_params += sformat(p_itype.cs_in, "this");
|
|
|
|
|
|
List<String> default_args_doc;
|
|
@@ -1257,9 +1084,9 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
|
|
|
|
|
|
// Generate method
|
|
|
{
|
|
|
- if (p_itype.is_object_type && !p_imethod.is_virtual && !p_imethod.requires_object_call) {
|
|
|
+ if (!p_imethod.is_virtual && !p_imethod.requires_object_call) {
|
|
|
p_output.push_back(MEMBER_BEGIN "private static IntPtr ");
|
|
|
- p_output.push_back(method_bind_field + " = " BINDINGS_CLASS_NATIVECALLS "." ICALL_GET_METHODBIND "(" BINDINGS_NATIVE_NAME_FIELD ", \"");
|
|
|
+ p_output.push_back(method_bind_field + " = Object." ICALL_GET_METHODBIND "(" BINDINGS_NATIVE_NAME_FIELD ", \"");
|
|
|
p_output.push_back(p_imethod.name);
|
|
|
p_output.push_back("\");\n");
|
|
|
}
|
|
@@ -1372,19 +1199,31 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
|
|
|
|
|
|
List<String> output;
|
|
|
|
|
|
- output.push_back("#include \"" GLUE_HEADER_FILE "\"\n"
|
|
|
- "\n");
|
|
|
+ output.push_back("/* THIS FILE IS GENERATED DO NOT EDIT */\n");
|
|
|
+ output.push_back("#include \"" GLUE_HEADER_FILE "\"\n");
|
|
|
+ output.push_back("\n#ifdef MONO_GLUE_ENABLED\n");
|
|
|
|
|
|
generated_icall_funcs.clear();
|
|
|
|
|
|
for (OrderedHashMap<StringName, TypeInterface>::Element type_elem = obj_types.front(); type_elem; type_elem = type_elem.next()) {
|
|
|
const TypeInterface &itype = type_elem.get();
|
|
|
|
|
|
+ bool is_derived_type = itype.base_name != StringName();
|
|
|
+
|
|
|
+ if (!is_derived_type) {
|
|
|
+ // Some Object assertions
|
|
|
+ CRASH_COND(itype.cname != name_cache.type_Object);
|
|
|
+ CRASH_COND(!itype.is_instantiable);
|
|
|
+ CRASH_COND(itype.api_type != ClassDB::API_CORE);
|
|
|
+ CRASH_COND(itype.is_reference);
|
|
|
+ CRASH_COND(itype.is_singleton);
|
|
|
+ }
|
|
|
+
|
|
|
List<InternalCall> &custom_icalls = itype.api_type == ClassDB::API_EDITOR ? editor_custom_icalls : core_custom_icalls;
|
|
|
|
|
|
OS::get_singleton()->print(String("Generating " + itype.name + "...\n").utf8());
|
|
|
|
|
|
- String ctor_method(ICALL_PREFIX + itype.proxy_name + "_Ctor");
|
|
|
+ String ctor_method(ICALL_PREFIX + itype.proxy_name + "_Ctor"); // Used only for derived types
|
|
|
|
|
|
for (const List<MethodInterface>::Element *E = itype.methods.front(); E; E = E->next()) {
|
|
|
const MethodInterface &imethod = E->get();
|
|
@@ -1409,7 +1248,7 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
|
|
|
output.push_back("\");\n" CLOSE_BLOCK "\n");
|
|
|
}
|
|
|
|
|
|
- if (itype.is_instantiable) {
|
|
|
+ if (is_derived_type && itype.is_instantiable) {
|
|
|
InternalCall ctor_icall = InternalCall(itype.api_type, ctor_method, "IntPtr", itype.proxy_name + " obj");
|
|
|
|
|
|
if (!find_icall_by_name(ctor_icall.name, custom_icalls))
|
|
@@ -1426,7 +1265,7 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- output.push_back("namespace GodotSharpBindings\n" OPEN_BLOCK);
|
|
|
+ output.push_back("namespace GodotSharpBindings\n" OPEN_BLOCK "\n");
|
|
|
|
|
|
output.push_back("uint64_t get_core_api_hash() { return ");
|
|
|
output.push_back(String::num_uint64(GDMono::get_singleton()->get_api_core_hash()) + "; }\n");
|
|
@@ -1441,8 +1280,8 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
|
|
|
output.push_back("uint32_t get_cs_glue_version() { return ");
|
|
|
output.push_back(String::num_uint64(CS_GLUE_VERSION) + "; }\n");
|
|
|
|
|
|
- output.push_back("void register_generated_icalls() " OPEN_BLOCK);
|
|
|
- output.push_back("\tgodot_register_header_icalls();");
|
|
|
+ output.push_back("\nvoid register_generated_icalls() " OPEN_BLOCK);
|
|
|
+ output.push_back("\tgodot_register_glue_header_icalls();\n");
|
|
|
|
|
|
#define ADD_INTERNAL_CALL_REGISTRATION(m_icall) \
|
|
|
{ \
|
|
@@ -1505,12 +1344,11 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
|
|
|
output.push_back("#endif\n");
|
|
|
}
|
|
|
|
|
|
- for (const List<InternalCall>::Element *E = builtin_method_icalls.front(); E; E = E->next())
|
|
|
- ADD_INTERNAL_CALL_REGISTRATION(E->get());
|
|
|
-
|
|
|
#undef ADD_INTERNAL_CALL_REGISTRATION
|
|
|
|
|
|
- output.push_back(CLOSE_BLOCK "}\n");
|
|
|
+ output.push_back(CLOSE_BLOCK "\n} // namespace GodotSharpBindings\n");
|
|
|
+
|
|
|
+ output.push_back("\n#endif // MONO_GLUE_ENABLED\n");
|
|
|
|
|
|
Error save_err = _save_file(path_join(p_output_dir, "mono_glue.gen.cpp"), output);
|
|
|
if (save_err != OK)
|
|
@@ -1591,9 +1429,6 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
|
|
|
i++;
|
|
|
}
|
|
|
|
|
|
- if (!p_itype.is_object_type)
|
|
|
- return OK; // no auto-generated icall functions for builtin types
|
|
|
-
|
|
|
const Map<const MethodInterface *, const InternalCall *>::Element *match = method_icalls_map.find(&p_imethod);
|
|
|
ERR_FAIL_NULL_V(match, ERR_BUG);
|
|
|
|
|
@@ -1628,7 +1463,7 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
|
|
|
}
|
|
|
|
|
|
p_output.push_back("\t" + ptrcall_return_type);
|
|
|
- p_output.push_back(" " LOCAL_RET);
|
|
|
+ p_output.push_back(" " C_LOCAL_RET);
|
|
|
p_output.push_back(initialization + ";\n");
|
|
|
p_output.push_back("\tERR_FAIL_NULL_V(" CS_PARAM_INSTANCE);
|
|
|
p_output.push_back(fail_ret);
|
|
@@ -1678,7 +1513,7 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
|
|
|
p_output.push_back("\tVariant::CallError vcall_error;\n\t");
|
|
|
|
|
|
if (!ret_void)
|
|
|
- p_output.push_back(LOCAL_RET " = ");
|
|
|
+ p_output.push_back(C_LOCAL_RET " = ");
|
|
|
|
|
|
p_output.push_back(CS_PARAM_METHODBIND "->call(" CS_PARAM_INSTANCE ", ");
|
|
|
p_output.push_back(p_imethod.arguments.size() ? "(const Variant**)" C_LOCAL_PTRCALL_ARGS ".ptr()" : "NULL");
|
|
@@ -1686,14 +1521,14 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
|
|
|
} else {
|
|
|
p_output.push_back("\t" CS_PARAM_METHODBIND "->ptrcall(" CS_PARAM_INSTANCE ", ");
|
|
|
p_output.push_back(p_imethod.arguments.size() ? C_LOCAL_PTRCALL_ARGS ", " : "NULL, ");
|
|
|
- p_output.push_back(!ret_void ? "&" LOCAL_RET ");\n" : "NULL);\n");
|
|
|
+ p_output.push_back(!ret_void ? "&" C_LOCAL_RET ");\n" : "NULL);\n");
|
|
|
}
|
|
|
|
|
|
if (!ret_void) {
|
|
|
if (return_type->c_out.empty())
|
|
|
- p_output.push_back("\treturn " LOCAL_RET ";\n");
|
|
|
+ p_output.push_back("\treturn " C_LOCAL_RET ";\n");
|
|
|
else
|
|
|
- p_output.push_back(sformat(return_type->c_out, return_type->c_type_out, LOCAL_RET, return_type->name));
|
|
|
+ p_output.push_back(sformat(return_type->c_out, return_type->c_type_out, C_LOCAL_RET, return_type->name));
|
|
|
}
|
|
|
|
|
|
p_output.push_back(CLOSE_BLOCK "\n");
|
|
@@ -1752,9 +1587,6 @@ const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_or_placehol
|
|
|
return &placeholder_types.insert(placeholder.cname, placeholder)->get();
|
|
|
}
|
|
|
|
|
|
-static void _create_constant_interface_from(const StringName &p_constant, const DocData::ClassDoc &p_classdoc) {
|
|
|
-}
|
|
|
-
|
|
|
void BindingsGenerator::_populate_object_type_interfaces() {
|
|
|
|
|
|
obj_types.clear();
|
|
@@ -1889,9 +1721,6 @@ void BindingsGenerator::_populate_object_type_interfaces() {
|
|
|
if (virtual_method_list.find(method_info)) {
|
|
|
// A virtual method without the virtual flag. This is a special case.
|
|
|
|
|
|
- // This type of method can only be found in Object derived types.
|
|
|
- ERR_FAIL_COND(!itype.is_object_type);
|
|
|
-
|
|
|
// There is no method bind, so let's fallback to Godot's object.Call(string, params)
|
|
|
imethod.requires_object_call = true;
|
|
|
|
|
@@ -2273,13 +2102,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
|
|
|
itype.cs_out = "return new %1(%0);";
|
|
|
itype.im_type_in = "IntPtr";
|
|
|
itype.im_type_out = "IntPtr";
|
|
|
- _populate_builtin_type(itype, Variant::NODE_PATH);
|
|
|
- extra_members.insert(itype.cname, MEMBER_BEGIN "public NodePath() : this(string.Empty) {}\n" MEMBER_BEGIN "public NodePath(string path)\n" OPEN_BLOCK_L2
|
|
|
- "this." BINDINGS_PTR_FIELD " = NativeCalls.godot_icall_NodePath_Ctor(path);\n" CLOSE_BLOCK_L2
|
|
|
- MEMBER_BEGIN "public static implicit operator NodePath(string from)\n" OPEN_BLOCK_L2 "return new NodePath(from);\n" CLOSE_BLOCK_L2
|
|
|
- MEMBER_BEGIN "public static implicit operator string(NodePath from)\n" OPEN_BLOCK_L2
|
|
|
- "return NativeCalls." ICALL_PREFIX "NodePath_operator_String(NodePath." CS_SMETHOD_GETINSTANCE "(from));\n" CLOSE_BLOCK_L2
|
|
|
- MEMBER_BEGIN "public override string ToString()\n" OPEN_BLOCK_L2 "return (string)this;\n" CLOSE_BLOCK_L2);
|
|
|
builtin_types.insert(itype.cname, itype);
|
|
|
|
|
|
// RID
|
|
@@ -2296,9 +2118,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
|
|
|
itype.cs_out = "return new %1(%0);";
|
|
|
itype.im_type_in = "IntPtr";
|
|
|
itype.im_type_out = "IntPtr";
|
|
|
- _populate_builtin_type(itype, Variant::_RID);
|
|
|
- extra_members.insert(itype.cname, MEMBER_BEGIN "internal RID()\n" OPEN_BLOCK_L2
|
|
|
- "this." BINDINGS_PTR_FIELD " = IntPtr.Zero;\n" CLOSE_BLOCK_L2);
|
|
|
builtin_types.insert(itype.cname, itype);
|
|
|
|
|
|
// Variant
|
|
@@ -2413,60 +2232,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
|
|
|
builtin_types.insert(itype.cname, itype);
|
|
|
}
|
|
|
|
|
|
-void BindingsGenerator::_populate_builtin_type(TypeInterface &r_itype, Variant::Type vtype) {
|
|
|
-
|
|
|
- Variant::CallError cerror;
|
|
|
- Variant v = Variant::construct(vtype, NULL, 0, cerror);
|
|
|
-
|
|
|
- List<MethodInfo> method_list;
|
|
|
- v.get_method_list(&method_list);
|
|
|
- method_list.sort();
|
|
|
-
|
|
|
- for (List<MethodInfo>::Element *E = method_list.front(); E; E = E->next()) {
|
|
|
- MethodInfo &mi = E->get();
|
|
|
- MethodInterface imethod;
|
|
|
-
|
|
|
- imethod.name = mi.name;
|
|
|
- imethod.cname = imethod.name;
|
|
|
- imethod.proxy_name = escape_csharp_keyword(snake_to_pascal_case(mi.name));
|
|
|
-
|
|
|
- for (int i = 0; i < mi.arguments.size(); i++) {
|
|
|
- ArgumentInterface iarg;
|
|
|
- PropertyInfo pi = mi.arguments[i];
|
|
|
-
|
|
|
- iarg.name = pi.name;
|
|
|
-
|
|
|
- if (pi.type == Variant::NIL)
|
|
|
- iarg.type.cname = name_cache.type_Variant;
|
|
|
- else
|
|
|
- iarg.type.cname = Variant::get_type_name(pi.type);
|
|
|
-
|
|
|
- if ((mi.default_arguments.size() - mi.arguments.size() + i) >= 0)
|
|
|
- _default_argument_from_variant(Variant::construct(pi.type, NULL, 0, cerror), iarg);
|
|
|
-
|
|
|
- imethod.add_argument(iarg);
|
|
|
- }
|
|
|
-
|
|
|
- if (mi.return_val.type == Variant::NIL) {
|
|
|
- if (mi.return_val.name != "")
|
|
|
- imethod.return_type.cname = name_cache.type_Variant;
|
|
|
- } else {
|
|
|
- imethod.return_type.cname = Variant::get_type_name(mi.return_val.type);
|
|
|
- }
|
|
|
-
|
|
|
- if (r_itype.class_doc) {
|
|
|
- for (int i = 0; i < r_itype.class_doc->methods.size(); i++) {
|
|
|
- if (r_itype.class_doc->methods[i].name == imethod.name) {
|
|
|
- imethod.method_doc = &r_itype.class_doc->methods[i];
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- r_itype.methods.push_back(imethod);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
void BindingsGenerator::_populate_global_constants() {
|
|
|
|
|
|
int global_constants_count = GlobalConstants::get_global_constant_count();
|
|
@@ -2564,15 +2329,13 @@ void BindingsGenerator::initialize() {
|
|
|
|
|
|
_populate_global_constants();
|
|
|
|
|
|
- // Populate internal calls (after populating type interfaces and global constants)
|
|
|
+ // Generate internal calls (after populating type interfaces and global constants)
|
|
|
|
|
|
- _generate_header_icalls();
|
|
|
+ core_custom_icalls.clear();
|
|
|
+ editor_custom_icalls.clear();
|
|
|
|
|
|
for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next())
|
|
|
_generate_method_icalls(E.get());
|
|
|
-
|
|
|
- _generate_method_icalls(builtin_types["NodePath"]);
|
|
|
- _generate_method_icalls(builtin_types["RID"]);
|
|
|
}
|
|
|
|
|
|
void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) {
|