summaryrefslogtreecommitdiff
path: root/modules/mono
diff options
context:
space:
mode:
Diffstat (limited to 'modules/mono')
-rw-r--r--modules/mono/SCsub4
-rw-r--r--modules/mono/config.py1
-rw-r--r--modules/mono/csharp_script.cpp72
-rw-r--r--modules/mono/csharp_script.h6
-rw-r--r--modules/mono/doc_classes/@C#.xml2
-rw-r--r--modules/mono/doc_classes/CSharpScript.xml2
-rw-r--r--modules/mono/doc_classes/GodotSharp.xml2
-rw-r--r--modules/mono/editor/bindings_generator.cpp111
-rw-r--r--modules/mono/editor/bindings_generator.h9
-rw-r--r--modules/mono/editor/godotsharp_editor.cpp86
-rw-r--r--modules/mono/editor/godotsharp_editor.h8
-rw-r--r--modules/mono/editor/mono_bottom_panel.cpp2
-rw-r--r--modules/mono/editor/monodevelop_instance.cpp2
-rw-r--r--modules/mono/editor/monodevelop_instance.h2
-rw-r--r--modules/mono/glue/builtin_types_glue.h59
-rw-r--r--modules/mono/glue/cs_files/Color.cs26
-rw-r--r--modules/mono/glue/cs_files/DebuggingUtils.cs10
-rw-r--r--modules/mono/glue/cs_files/Mathf.cs2
-rw-r--r--modules/mono/glue/cs_files/Plane.cs2
-rw-r--r--modules/mono/glue/glue_header.h18
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp12
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.cpp31
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.h2
-rw-r--r--modules/mono/mono_gd/gd_mono_class.h2
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.cpp16
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.h1
-rw-r--r--modules/mono/mono_gd/gd_mono_property.cpp2
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp32
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.h12
-rw-r--r--modules/mono/signal_awaiter_utils.cpp2
30 files changed, 399 insertions, 139 deletions
diff --git a/modules/mono/SCsub b/modules/mono/SCsub
index 320bbe7090..aa8626e6da 100644
--- a/modules/mono/SCsub
+++ b/modules/mono/SCsub
@@ -57,10 +57,10 @@ if env['tools']:
vars = Variables()
vars.Add(BoolVariable('mono_glue', 'Build with the mono glue sources', True))
vars.Add(BoolVariable('xbuild_fallback', 'If MSBuild is not found, fallback to xbuild', False))
-vars.Update(env)
+vars.Update(env_mono)
# Glue sources
-if env['mono_glue']:
+if env_mono['mono_glue']:
env_mono.add_source_files(env.modules_sources, 'glue/*.cpp')
else:
env_mono.Append(CPPDEFINES=['MONO_GLUE_DISABLED'])
diff --git a/modules/mono/config.py b/modules/mono/config.py
index b4e6433256..7c1846dcc2 100644
--- a/modules/mono/config.py
+++ b/modules/mono/config.py
@@ -159,6 +159,7 @@ def configure(env):
mono_so_name = ''
tmpenv = Environment()
+ tmpenv.AppendENVPath('PKG_CONFIG_PATH', os.getenv('PKG_CONFIG_PATH'))
tmpenv.ParseConfig('pkg-config monosgen-2 --libs-only-L')
for hint_dir in tmpenv['LIBPATH']:
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 2d7583cc23..0dc0018224 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -176,7 +176,7 @@ void CSharpLanguage::get_reserved_words(List<String> *p_words) const {
"fixed",
"float",
"for",
- "forech",
+ "foreach",
"goto",
"if",
"implicit",
@@ -222,14 +222,17 @@ void CSharpLanguage::get_reserved_words(List<String> *p_words) const {
"ushort",
"using",
"virtual",
- "volatile",
"void",
+ "volatile",
"while",
// Contextual keywords. Not reserved words, but I guess we should include
// them because this seems to be used only for syntax highlighting.
"add",
+ "alias",
"ascending",
+ "async",
+ "await",
"by",
"descending",
"dynamic",
@@ -238,10 +241,10 @@ void CSharpLanguage::get_reserved_words(List<String> *p_words) const {
"get",
"global",
"group",
- "in",
"into",
"join",
"let",
+ "nameof",
"on",
"orderby",
"partial",
@@ -250,6 +253,7 @@ void CSharpLanguage::get_reserved_words(List<String> *p_words) const {
"set",
"value",
"var",
+ "when",
"where",
"yield",
0
@@ -447,9 +451,10 @@ String CSharpLanguage::_get_indentation() const {
Vector<ScriptLanguage::StackInfo> CSharpLanguage::debug_get_current_stack_info() {
+#ifdef DEBUG_ENABLED
// Printing an error here will result in endless recursion, so we must be careful
- if (!gdmono->is_runtime_initialized() && GDMono::get_singleton()->get_editor_tools_assembly())
+ if (!gdmono->is_runtime_initialized() || !GDMono::get_singleton()->get_api_assembly() || !GDMonoUtils::mono_cache.corlib_cache_updated)
return Vector<StackInfo>();
MonoObject *stack_trace = mono_object_new(mono_domain_get(), CACHED_CLASS(System_Diagnostics_StackTrace)->get_mono_ptr());
@@ -463,8 +468,12 @@ Vector<ScriptLanguage::StackInfo> CSharpLanguage::debug_get_current_stack_info()
si = stack_trace_get_info(stack_trace);
return si;
+#else
+ return Vector<StackInfo>();
+#endif
}
+#ifdef DEBUG_ENABLED
Vector<ScriptLanguage::StackInfo> CSharpLanguage::stack_trace_get_info(MonoObject *p_stack_trace) {
// Printing an error here could result in endless recursion, so we must be careful
@@ -503,6 +512,10 @@ Vector<ScriptLanguage::StackInfo> CSharpLanguage::stack_trace_get_info(MonoObjec
return Vector<StackInfo>();
}
+ // TODO
+ // what if the StackFrame method is null (method_decl is empty). should we skip this frame?
+ // can reproduce with a MissingMethodException on internal calls
+
sif.file = GDMonoMarshal::mono_string_to_godot(file_name);
sif.line = file_line_num;
sif.func = GDMonoMarshal::mono_string_to_godot(method_decl);
@@ -510,6 +523,7 @@ Vector<ScriptLanguage::StackInfo> CSharpLanguage::stack_trace_get_info(MonoObjec
return si;
}
+#endif
void CSharpLanguage::frame() {
@@ -937,19 +951,6 @@ void CSharpLanguage::free_instance_binding_data(void *p_data) {
#endif
}
-void CSharpInstance::_ml_call_reversed(MonoObject *p_mono_object, GDMonoClass *p_klass, const StringName &p_method, const Variant **p_args, int p_argcount) {
-
- GDMonoClass *base = p_klass->get_parent_class();
- if (base && base != script->native)
- _ml_call_reversed(p_mono_object, base, p_method, p_args, p_argcount);
-
- GDMonoMethod *method = p_klass->get_method(p_method, p_argcount);
-
- if (method) {
- method->invoke(p_mono_object, p_args);
- }
-}
-
CSharpInstance *CSharpInstance::create_for_managed_type(Object *p_owner, CSharpScript *p_script, const Ref<MonoGCHandle> &p_gchandle) {
CSharpInstance *instance = memnew(CSharpInstance);
@@ -1018,6 +1019,8 @@ bool CSharpInstance::set(const StringName &p_name, const Variant &p_value) {
if (ret && GDMonoMarshal::unbox<MonoBoolean>(ret) == true)
return true;
+
+ break;
}
top = top->get_parent_class();
@@ -1040,7 +1043,7 @@ bool CSharpInstance::get(const StringName &p_name, Variant &r_ret) const {
if (field) {
MonoObject *value = field->get_value(mono_object);
- r_ret = GDMonoMarshal::mono_object_to_variant(value, field->get_type());
+ r_ret = GDMonoMarshal::mono_object_to_variant(value);
return true;
}
@@ -1053,7 +1056,7 @@ bool CSharpInstance::get(const StringName &p_name, Variant &r_ret) const {
r_ret = Variant();
GDMonoUtils::print_unhandled_exception(exc);
} else {
- r_ret = GDMonoMarshal::mono_object_to_variant(value, property->get_type());
+ r_ret = GDMonoMarshal::mono_object_to_variant(value);
}
return true;
}
@@ -1078,6 +1081,8 @@ bool CSharpInstance::get(const StringName &p_name, Variant &r_ret) const {
r_ret = GDMonoMarshal::mono_object_to_variant(ret);
return true;
}
+
+ break;
}
top = top->get_parent_class();
@@ -1129,10 +1134,13 @@ Variant CSharpInstance::call(const StringName &p_method, const Variant **p_args,
MonoObject *mono_object = get_mono_object();
- ERR_FAIL_NULL_V(mono_object, Variant());
+ if (!mono_object) {
+ r_error.error = Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL;
+ ERR_FAIL_V(Variant());
+ }
if (!script.is_valid())
- return Variant();
+ ERR_FAIL_V(Variant());
GDMonoClass *top = script->script_class;
@@ -1142,8 +1150,10 @@ Variant CSharpInstance::call(const StringName &p_method, const Variant **p_args,
if (method) {
MonoObject *return_value = method->invoke(mono_object, p_args);
+ r_error.error = Variant::CallError::CALL_OK;
+
if (return_value) {
- return GDMonoMarshal::mono_object_to_variant(return_value, method->get_return_type());
+ return GDMonoMarshal::mono_object_to_variant(return_value);
} else {
return Variant();
}
@@ -1175,8 +1185,10 @@ void CSharpInstance::_call_multilevel(MonoObject *p_mono_object, const StringNam
while (top && top != script->native) {
GDMonoMethod *method = top->get_method(p_method, p_argcount);
- if (method)
+ if (method) {
method->invoke(p_mono_object, p_args);
+ return;
+ }
top = top->get_parent_class();
}
@@ -1184,13 +1196,9 @@ void CSharpInstance::_call_multilevel(MonoObject *p_mono_object, const StringNam
void CSharpInstance::call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount) {
- if (script.is_valid()) {
- MonoObject *mono_object = get_mono_object();
-
- ERR_FAIL_NULL(mono_object);
+ // Sorry, the method is the one that controls the call order
- _ml_call_reversed(mono_object, script->script_class, p_method, p_args, p_argcount);
- }
+ call_multilevel(p_method, p_args, p_argcount);
}
void CSharpInstance::_reference_owner_unsafe() {
@@ -1537,6 +1545,7 @@ bool CSharpScript::_update_exports() {
return false;
}
+#ifdef TOOLS_ENABLED
bool CSharpScript::_get_member_export(GDMonoClass *p_class, GDMonoClassMember *p_member, PropertyInfo &r_prop_info, bool &r_exported) {
StringName name = p_member->get_name();
@@ -1607,6 +1616,7 @@ bool CSharpScript::_get_member_export(GDMonoClass *p_class, GDMonoClassMember *p
return true;
}
+#endif
void CSharpScript::_clear() {
@@ -1629,7 +1639,7 @@ Variant CSharpScript::call(const StringName &p_method, const Variant **p_args, i
MonoObject *result = method->invoke(NULL, p_args);
if (result) {
- return GDMonoMarshal::mono_object_to_variant(result, method->get_return_type());
+ return GDMonoMarshal::mono_object_to_variant(result);
} else {
return Variant();
}
@@ -1676,7 +1686,7 @@ bool CSharpScript::_set(const StringName &p_name, const Variant &p_value) {
void CSharpScript::_get_property_list(List<PropertyInfo> *p_properties) const {
- p_properties->push_back(PropertyInfo(Variant::STRING, CSharpLanguage::singleton->string_names._script_source, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
+ p_properties->push_back(PropertyInfo(Variant::STRING, CSharpLanguage::singleton->string_names._script_source, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
}
void CSharpScript::_bind_methods() {
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 3ce8a9b64e..f18e339e18 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -105,7 +105,9 @@ class CSharpScript : public Script {
void _clear();
bool _update_exports();
+#ifdef TOOLS_ENABLED
bool _get_member_export(GDMonoClass *p_class, GDMonoClassMember *p_member, PropertyInfo &r_prop_info, bool &r_exported);
+#endif
CSharpInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Variant::CallError &r_error);
Variant _new(const Variant **p_args, int p_argcount, Variant::CallError &r_error);
@@ -170,8 +172,6 @@ class CSharpInstance : public ScriptInstance {
bool base_ref;
bool ref_dying;
- void _ml_call_reversed(MonoObject *p_mono_object, GDMonoClass *klass, const StringName &p_method, const Variant **p_args, int p_argcount);
-
void _reference_owner_unsafe();
void _unreference_owner_unsafe();
@@ -335,7 +335,9 @@ public:
virtual void *alloc_instance_binding_data(Object *p_object);
virtual void free_instance_binding_data(void *p_data);
+#ifdef DEBUG_ENABLED
Vector<StackInfo> stack_trace_get_info(MonoObject *p_stack_trace);
+#endif
CSharpLanguage();
~CSharpLanguage();
diff --git a/modules/mono/doc_classes/@C#.xml b/modules/mono/doc_classes/@C#.xml
index 5fcbf36a2b..0f33c76eb2 100644
--- a/modules/mono/doc_classes/@C#.xml
+++ b/modules/mono/doc_classes/@C#.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="@C#" category="Core" version="3.0-beta">
+<class name="@C#" category="Core" version="3.0-stable">
<brief_description>
</brief_description>
<description>
diff --git a/modules/mono/doc_classes/CSharpScript.xml b/modules/mono/doc_classes/CSharpScript.xml
index 853ef28731..3efe71f1b3 100644
--- a/modules/mono/doc_classes/CSharpScript.xml
+++ b/modules/mono/doc_classes/CSharpScript.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CSharpScript" inherits="Script" category="Core" version="3.0-beta">
+<class name="CSharpScript" inherits="Script" category="Core" version="3.0-stable">
<brief_description>
</brief_description>
<description>
diff --git a/modules/mono/doc_classes/GodotSharp.xml b/modules/mono/doc_classes/GodotSharp.xml
index 2696a0bb4b..1e5edf2a2a 100644
--- a/modules/mono/doc_classes/GodotSharp.xml
+++ b/modules/mono/doc_classes/GodotSharp.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GodotSharp" inherits="Object" category="Core" version="3.0-beta">
+<class name="GodotSharp" inherits="Object" category="Core" version="3.0-stable">
<brief_description>
</brief_description>
<description>
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 800e3b723b..62c7a94755 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -250,8 +250,15 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
const TypeInterface *return_type = _get_type_by_name_or_placeholder(imethod.return_type);
- String im_sig = "IntPtr " CS_PARAM_METHODBIND ", IntPtr " CS_PARAM_INSTANCE;
- String im_unique_sig = imethod.return_type.operator String() + ",IntPtr,IntPtr";
+ 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.operator String() + ",IntPtr,IntPtr";
+ }
+
+ im_sig += "IntPtr " CS_PARAM_INSTANCE;
// Get arguments information
int i = 0;
@@ -263,25 +270,37 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
im_sig += " arg";
im_sig += itos(i + 1);
- im_unique_sig += ",";
- im_unique_sig += get_unique_sig(*arg_type);
+ if (p_itype.is_object_type) {
+ im_unique_sig += ",";
+ im_unique_sig += get_unique_sig(*arg_type);
+ }
i++;
}
- // godot_icall_{argc}_{icallcount}
- String icall_method = ICALL_PREFIX + itos(imethod.arguments.size()) + "_" + itos(method_icalls.size());
+ 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}
+ }
InternalCall im_icall = InternalCall(p_itype.api_type, icall_method, return_type->im_type_out, im_sig, im_unique_sig);
- List<InternalCall>::Element *match = method_icalls.find(im_icall);
+ if (p_itype.is_object_type) {
+ 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());
+ 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());
+ }
} else {
- List<InternalCall>::Element *added = method_icalls.push_back(im_icall);
+ List<InternalCall>::Element *added = builtin_method_icalls.push_back(im_icall);
method_icalls_map.insert(&E->get(), &added->get());
}
}
@@ -525,6 +544,8 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo
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
@@ -616,6 +637,8 @@ 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())
@@ -694,9 +717,9 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
output.push_back(itype.is_singleton ? "static class " : "class ");
output.push_back(itype.proxy_name);
- if (itype.is_singleton || !itype.is_object_type) {
+ if (itype.is_singleton) {
output.push_back("\n");
- } else if (!is_derived_type) {
+ } 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(" : ");
@@ -838,7 +861,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
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 "public virtual void Dispose(bool disposing)\n" OPEN_BLOCK_L2
+ 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);
@@ -929,7 +952,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
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 "public virtual void Dispose(bool disposing)\n" OPEN_BLOCK_L2
+ 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
@@ -1122,10 +1145,14 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
String method_bind_field = "method_bind_" + itos(p_method_bind_count);
- String icall_params = method_bind_field + ", " + sformat(p_itype.cs_in, "this");
String arguments_sig;
String cs_in_statements;
+ String icall_params;
+ if (p_itype.is_object_type)
+ icall_params += method_bind_field + ", ";
+ icall_params += sformat(p_itype.cs_in, "this");
+
List<String> default_args_doc;
// Retrieve information from the arguments
@@ -1200,9 +1227,8 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
// Generate method
{
- if (!p_imethod.is_virtual && !p_imethod.requires_object_call) {
- p_output.push_back(MEMBER_BEGIN "private ");
- p_output.push_back(p_itype.is_singleton ? "static IntPtr " : "IntPtr ");
+ if (p_itype.is_object_type && !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 + " = " CS_CLASS_NATIVECALLS "." ICALL_GET_METHODBIND "(" BINDINGS_NATIVE_NAME_FIELD ", \"");
p_output.push_back(p_imethod.name);
p_output.push_back("\");\n");
@@ -1381,6 +1407,7 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
output.push_back(itos(GDMono::get_singleton()->get_api_editor_hash()) +
"; }\n#endif // TOOLS_ENABLED\n");
output.push_back("void register_generated_icalls() " OPEN_BLOCK);
+ output.push_back("\tgodot_register_header_icalls();");
#define ADD_INTERNAL_CALL_REGISTRATION(m_icall) \
{ \
@@ -1443,6 +1470,9 @@ 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");
@@ -1518,6 +1548,9 @@ 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);
@@ -1811,7 +1844,7 @@ void BindingsGenerator::_populate_object_type_interfaces() {
imethod.return_type = name_cache.type_void;
// Actually, more methods like this may be added in the future,
- // which could actually will return something differnet.
+ // which could actually will return something different.
// Let's put this to notify us if that ever happens.
if (itype.cname != name_cache.type_Object || imethod.name != "free") {
if (verbose_output) {
@@ -2113,36 +2146,34 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
#undef INSERT_STRUCT_TYPE
-#define INSERT_PRIMITIVE_TYPE(m_type) \
- { \
- itype = TypeInterface::create_value_type(String(#m_type)); \
- itype.c_arg_in = "&%s"; \
- itype.c_type_in = #m_type; \
- itype.c_type_out = #m_type; \
- itype.im_type_in = #m_type; \
- itype.im_type_out = #m_type; \
- builtin_types.insert(itype.cname, itype); \
- }
-
- INSERT_PRIMITIVE_TYPE(bool)
- //INSERT_PRIMITIVE_TYPE(int)
+ // bool
+ itype = TypeInterface::create_value_type(String("bool"));
+ itype.c_arg_in = "&%s";
+ // /* MonoBoolean <---> bool
+ itype.c_in = "\t%0 %1_in = (%0)%1;\n";
+ itype.c_out = "\treturn (%0)%1;\n";
+ itype.c_type = "bool";
+ // */
+ itype.c_type_in = "MonoBoolean";
+ itype.c_type_out = itype.c_type_in;
+ itype.im_type_in = itype.name;
+ itype.im_type_out = itype.name;
+ builtin_types.insert(itype.cname, itype);
// int
itype = TypeInterface::create_value_type(String("int"));
itype.c_arg_in = "&%s_in";
- //* ptrcall only supports int64_t and uint64_t
+ // /* ptrcall only supports int64_t and uint64_t
itype.c_in = "\t%0 %1_in = (%0)%1;\n";
itype.c_out = "\treturn (%0)%1;\n";
itype.c_type = "int64_t";
- //*/
- itype.c_type_in = itype.name;
- itype.c_type_out = itype.name;
+ // */
+ itype.c_type_in = "int32_t";
+ itype.c_type_out = itype.c_type_in;
itype.im_type_in = itype.name;
itype.im_type_out = itype.name;
builtin_types.insert(itype.cname, itype);
-#undef INSERT_PRIMITIVE_TYPE
-
// real_t
itype = TypeInterface();
#ifdef REAL_T_IS_DOUBLE
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index 8929b45cce..9b5a9cea88 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -441,6 +441,7 @@ class BindingsGenerator {
Map<StringName, String> extra_members;
List<InternalCall> method_icalls;
+ List<InternalCall> builtin_method_icalls;
Map<const MethodInterface *, const InternalCall *> method_icalls_map;
List<const InternalCall *> generated_icall_funcs;
@@ -503,8 +504,8 @@ class BindingsGenerator {
const TypeInterface *_get_type_by_name_or_null(const StringName &p_cname);
const TypeInterface *_get_type_by_name_or_placeholder(const StringName &p_cname);
- void _default_argument_from_variant(const Variant &p_var, ArgumentInterface &r_iarg);
- void _populate_builtin_type(TypeInterface &r_type, Variant::Type vtype);
+ void _default_argument_from_variant(const Variant &p_val, ArgumentInterface &r_iarg);
+ void _populate_builtin_type(TypeInterface &r_itype, Variant::Type vtype);
void _populate_object_type_interfaces();
void _populate_builtin_type_interfaces();
@@ -513,14 +514,14 @@ class BindingsGenerator {
Error _generate_cs_type(const TypeInterface &itype, const String &p_output_file);
- Error _generate_cs_property(const TypeInterface &p_itype, const PropertyInterface &p_prop_doc, List<String> &p_output);
+ Error _generate_cs_property(const TypeInterface &p_itype, const PropertyInterface &p_iprop, List<String> &p_output);
Error _generate_cs_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, int &p_method_bind_count, List<String> &p_output);
void _generate_global_constants(List<String> &p_output);
Error _generate_glue_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, List<String> &p_output);
- Error _save_file(const String &path, const List<String> &content);
+ Error _save_file(const String &p_path, const List<String> &p_content);
BindingsGenerator() {}
diff --git a/modules/mono/editor/godotsharp_editor.cpp b/modules/mono/editor/godotsharp_editor.cpp
index 9e48da68c1..0ef3adfdd0 100644
--- a/modules/mono/editor/godotsharp_editor.cpp
+++ b/modules/mono/editor/godotsharp_editor.cpp
@@ -112,6 +112,21 @@ void GodotSharpEditor::_remove_create_sln_menu_option() {
bottom_panel_btn->show();
}
+void GodotSharpEditor::_show_about_dialog() {
+
+ bool show_on_start = EDITOR_GET("mono/editor/show_info_on_start");
+ about_dialog_checkbox->set_pressed(show_on_start);
+ about_dialog->popup_centered_minsize();
+}
+
+void GodotSharpEditor::_toggle_about_dialog_on_start(bool p_enabled) {
+
+ bool show_on_start = EDITOR_GET("mono/editor/show_info_on_start");
+ if (show_on_start != p_enabled) {
+ EditorSettings::get_singleton()->set_setting("mono/editor/show_info_on_start", p_enabled);
+ }
+}
+
void GodotSharpEditor::_menu_option_pressed(int p_id) {
switch (p_id) {
@@ -119,15 +134,37 @@ void GodotSharpEditor::_menu_option_pressed(int p_id) {
_create_project_solution();
} break;
+ case MENU_ABOUT_CSHARP: {
+
+ _show_about_dialog();
+ } break;
default:
ERR_FAIL();
}
}
+void GodotSharpEditor::_notification(int p_notification) {
+
+ switch (p_notification) {
+
+ case NOTIFICATION_READY: {
+
+ bool show_info_dialog = EDITOR_GET("mono/editor/show_info_on_start");
+ if (show_info_dialog) {
+ about_dialog->set_exclusive(true);
+ _show_about_dialog();
+ // Once shown a first time, it can be seen again via the Mono menu - it doesn't have to be exclusive then.
+ about_dialog->set_exclusive(false);
+ }
+ }
+ }
+}
+
void GodotSharpEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_create_project_solution"), &GodotSharpEditor::_create_project_solution);
ClassDB::bind_method(D_METHOD("_remove_create_sln_menu_option"), &GodotSharpEditor::_remove_create_sln_menu_option);
+ ClassDB::bind_method(D_METHOD("_toggle_about_dialog_on_start"), &GodotSharpEditor::_toggle_about_dialog_on_start);
ClassDB::bind_method(D_METHOD("_menu_option_pressed", "id"), &GodotSharpEditor::_menu_option_pressed);
}
@@ -210,6 +247,55 @@ GodotSharpEditor::GodotSharpEditor(EditorNode *p_editor) {
menu_button->set_text(TTR("Mono"));
menu_popup = menu_button->get_popup();
+ // TODO: Remove or edit this info dialog once Mono support is no longer in alpha
+ {
+ menu_popup->add_item(TTR("About C# support"), MENU_ABOUT_CSHARP);
+ about_dialog = memnew(AcceptDialog);
+ editor->get_gui_base()->add_child(about_dialog);
+ about_dialog->set_title("Important: C# support is not feature-complete");
+
+ // We don't use set_text() as the default AcceptDialog Label doesn't play well with the TextureRect and CheckBox
+ // we'll add. Instead we add containers and a new autowrapped Label inside.
+
+ // Main VBoxContainer (icon + label on top, checkbox at bottom)
+ VBoxContainer *about_vbc = memnew(VBoxContainer);
+ about_dialog->add_child(about_vbc);
+
+ // HBoxContainer for icon + label
+ HBoxContainer *about_hbc = memnew(HBoxContainer);
+ about_vbc->add_child(about_hbc);
+
+ TextureRect *about_icon = memnew(TextureRect);
+ about_hbc->add_child(about_icon);
+ Ref<Texture> about_icon_tex = about_icon->get_icon("NodeWarning", "EditorIcons");
+ about_icon->set_texture(about_icon_tex);
+
+ Label *about_label = memnew(Label);
+ about_hbc->add_child(about_label);
+ about_label->set_custom_minimum_size(Size2(600, 150) * EDSCALE);
+ about_label->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ about_label->set_autowrap(true);
+ String about_text =
+ String("C# support in Godot Engine is a brand new feature and a work in progress.\n") +
+ "It is at the alpha stage and thus not suitable for use in production.\n\n" +
+ "As of Godot 3.0, C# support is not feature-complete and can crash in some situations. " +
+ "Bugs and usability issues will be addressed gradually over 3.0.x and 3.x releases.\n" +
+ "The main missing feature is the ability to export games using C# assemblies - you will therefore be able to develop and run games in the editor, " +
+ "but not to share them as standalone binaries. This feature is of course high on the priority list and should be available in 3.0.1.\n\n" +
+ "If you experience issues with this Mono build, please report them on Godot's issue tracker with details about your system, Mono version, IDE, etc.:\n\n" +
+ " https://github.com/godotengine/godot/issues\n\n" +
+ "Your critical feedback at this stage will play a great role in shaping the C# support in future releases, so thank you!";
+ about_label->set_text(about_text);
+
+ EDITOR_DEF("mono/editor/show_info_on_start", true);
+
+ // CheckBox in main container
+ about_dialog_checkbox = memnew(CheckBox);
+ about_vbc->add_child(about_dialog_checkbox);
+ about_dialog_checkbox->set_text("Show this warning when starting the editor");
+ about_dialog_checkbox->connect("toggled", this, "_toggle_about_dialog_on_start");
+ }
+
String sln_path = GodotSharpDirs::get_project_sln_path();
String csproj_path = GodotSharpDirs::get_project_csproj_path();
diff --git a/modules/mono/editor/godotsharp_editor.h b/modules/mono/editor/godotsharp_editor.h
index 1b83bae1cd..81c49aec30 100644
--- a/modules/mono/editor/godotsharp_editor.h
+++ b/modules/mono/editor/godotsharp_editor.h
@@ -44,6 +44,8 @@ class GodotSharpEditor : public Node {
PopupMenu *menu_popup;
AcceptDialog *error_dialog;
+ AcceptDialog *about_dialog;
+ CheckBox *about_dialog_checkbox;
ToolButton *bottom_panel_btn;
@@ -54,17 +56,21 @@ class GodotSharpEditor : public Node {
bool _create_project_solution();
void _remove_create_sln_menu_option();
+ void _show_about_dialog();
+ void _toggle_about_dialog_on_start(bool p_enabled);
void _menu_option_pressed(int p_id);
static GodotSharpEditor *singleton;
protected:
+ void _notification(int p_notification);
static void _bind_methods();
public:
enum MenuOptions {
- MENU_CREATE_SLN
+ MENU_CREATE_SLN,
+ MENU_ABOUT_CSHARP,
};
enum ExternalEditor {
diff --git a/modules/mono/editor/mono_bottom_panel.cpp b/modules/mono/editor/mono_bottom_panel.cpp
index 43689548b5..ab62c62616 100644
--- a/modules/mono/editor/mono_bottom_panel.cpp
+++ b/modules/mono/editor/mono_bottom_panel.cpp
@@ -197,7 +197,7 @@ MonoBottomPanel::MonoBottomPanel(EditorNode *p_editor) {
toolbar_hbc->set_h_size_flags(SIZE_EXPAND_FILL);
panel_builds_tab->add_child(toolbar_hbc);
- ToolButton *build_project_btn = memnew(ToolButton);
+ Button *build_project_btn = memnew(Button);
build_project_btn->set_text(TTR("Build Project"));
build_project_btn->set_focus_mode(FOCUS_NONE);
build_project_btn->connect("pressed", this, "_build_project_pressed");
diff --git a/modules/mono/editor/monodevelop_instance.cpp b/modules/mono/editor/monodevelop_instance.cpp
index 0b0b36e1e3..48a285561d 100644
--- a/modules/mono/editor/monodevelop_instance.cpp
+++ b/modules/mono/editor/monodevelop_instance.cpp
@@ -35,6 +35,8 @@
void MonoDevelopInstance::execute(const Vector<String> &p_files) {
+ _GDMONO_SCOPE_DOMAIN_(TOOLS_DOMAIN)
+
ERR_FAIL_NULL(execute_method);
ERR_FAIL_COND(gc_handle.is_null());
diff --git a/modules/mono/editor/monodevelop_instance.h b/modules/mono/editor/monodevelop_instance.h
index 7e8a76b595..552c10a61d 100644
--- a/modules/mono/editor/monodevelop_instance.h
+++ b/modules/mono/editor/monodevelop_instance.h
@@ -43,7 +43,7 @@ class MonoDevelopInstance {
public:
void execute(const Vector<String> &p_files);
- void execute(const String &p_files);
+ void execute(const String &p_file);
MonoDevelopInstance(const String &p_solution);
};
diff --git a/modules/mono/glue/builtin_types_glue.h b/modules/mono/glue/builtin_types_glue.h
new file mode 100644
index 0000000000..460de84b65
--- /dev/null
+++ b/modules/mono/glue/builtin_types_glue.h
@@ -0,0 +1,59 @@
+#ifndef BUILTIN_TYPES_GLUE_H
+#define BUILTIN_TYPES_GLUE_H
+
+#include "core/node_path.h"
+#include "core/rid.h"
+
+#include <mono/metadata/object.h>
+
+#include "../mono_gd/gd_mono_marshal.h"
+
+MonoBoolean godot_icall_NodePath_is_absolute(NodePath *p_ptr) {
+ return (MonoBoolean)p_ptr->is_absolute();
+}
+
+uint32_t godot_icall_NodePath_get_name_count(NodePath *p_ptr) {
+ return p_ptr->get_name_count();
+}
+
+MonoString *godot_icall_NodePath_get_name(NodePath *p_ptr, uint32_t p_idx) {
+ return GDMonoMarshal::mono_string_from_godot(p_ptr->get_name(p_idx));
+}
+
+uint32_t godot_icall_NodePath_get_subname_count(NodePath *p_ptr) {
+ return p_ptr->get_subname_count();
+}
+
+MonoString *godot_icall_NodePath_get_subname(NodePath *p_ptr, uint32_t p_idx) {
+ return GDMonoMarshal::mono_string_from_godot(p_ptr->get_subname(p_idx));
+}
+
+MonoString *godot_icall_NodePath_get_concatenated_subnames(NodePath *p_ptr) {
+ return GDMonoMarshal::mono_string_from_godot(p_ptr->get_concatenated_subnames());
+}
+
+NodePath *godot_icall_NodePath_get_as_property_path(NodePath *p_ptr) {
+ return memnew(NodePath(p_ptr->get_as_property_path()));
+}
+
+MonoBoolean godot_icall_NodePath_is_empty(NodePath *p_ptr) {
+ return (MonoBoolean)p_ptr->is_empty();
+}
+
+uint32_t godot_icall_RID_get_id(RID *p_ptr) {
+ return p_ptr->get_id();
+}
+
+void godot_register_builtin_type_icalls() {
+ mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_get_as_property_path", (void *)godot_icall_NodePath_get_as_property_path);
+ mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_get_concatenated_subnames", (void *)godot_icall_NodePath_get_concatenated_subnames);
+ mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_get_name", (void *)godot_icall_NodePath_get_name);
+ mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_get_name_count", (void *)godot_icall_NodePath_get_name_count);
+ mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_get_subname", (void *)godot_icall_NodePath_get_subname);
+ mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_get_subname_count", (void *)godot_icall_NodePath_get_subname_count);
+ mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_is_absolute", (void *)godot_icall_NodePath_is_absolute);
+ mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_is_empty", (void *)godot_icall_NodePath_is_empty);
+ mono_add_internal_call("Godot.NativeCalls::godot_icall_RID_get_id", (void *)godot_icall_RID_get_id);
+}
+
+#endif // BUILTIN_TYPES_GLUE_H
diff --git a/modules/mono/glue/cs_files/Color.cs b/modules/mono/glue/cs_files/Color.cs
index db0e1fb744..f9e31e9703 100644
--- a/modules/mono/glue/cs_files/Color.cs
+++ b/modules/mono/glue/cs_files/Color.cs
@@ -336,7 +336,7 @@ namespace Godot
this.r = (rgba & 0xFF) / 255.0f;
}
- private static float _parse_col(string str, int ofs)
+ private static int _parse_col(string str, int ofs)
{
int ig = 0;
@@ -415,17 +415,17 @@ namespace Godot
if (alpha)
{
- if ((int)_parse_col(color, 0) < 0)
+ if (_parse_col(color, 0) < 0)
return false;
}
int from = alpha ? 2 : 0;
- if ((int)_parse_col(color, from + 0) < 0)
+ if (_parse_col(color, from + 0) < 0)
return false;
- if ((int)_parse_col(color, from + 2) < 0)
+ if (_parse_col(color, from + 2) < 0)
return false;
- if ((int)_parse_col(color, from + 4) < 0)
+ if (_parse_col(color, from + 4) < 0)
return false;
return true;
@@ -467,10 +467,10 @@ namespace Godot
if (alpha)
{
- a = _parse_col(rgba, 0);
+ a = _parse_col(rgba, 0) / 255f;
if (a < 0)
- throw new ArgumentOutOfRangeException("Invalid color code. Alpha is " + a + " but zero or greater is expected: " + rgba);
+ throw new ArgumentOutOfRangeException("Invalid color code. Alpha part is not valid hexadecimal: " + rgba);
}
else
{
@@ -479,20 +479,20 @@ namespace Godot
int from = alpha ? 2 : 0;
- r = _parse_col(rgba, from + 0);
+ r = _parse_col(rgba, from + 0) / 255f;
if (r < 0)
- throw new ArgumentOutOfRangeException("Invalid color code. Red is " + r + " but zero or greater is expected: " + rgba);
+ throw new ArgumentOutOfRangeException("Invalid color code. Red part is not valid hexadecimal: " + rgba);
- g = _parse_col(rgba, from + 2);
+ g = _parse_col(rgba, from + 2) / 255f;
if (g < 0)
- throw new ArgumentOutOfRangeException("Invalid color code. Green is " + g + " but zero or greater is expected: " + rgba);
+ throw new ArgumentOutOfRangeException("Invalid color code. Green part is not valid hexadecimal: " + rgba);
- b = _parse_col(rgba, from + 4);
+ b = _parse_col(rgba, from + 4) / 255f;
if (b < 0)
- throw new ArgumentOutOfRangeException("Invalid color code. Blue is " + b + " but zero or greater is expected: " + rgba);
+ throw new ArgumentOutOfRangeException("Invalid color code. Blue part is not valid hexadecimal: " + rgba);
}
public static bool operator ==(Color left, Color right)
diff --git a/modules/mono/glue/cs_files/DebuggingUtils.cs b/modules/mono/glue/cs_files/DebuggingUtils.cs
index ced78f658d..ffaaf00837 100644
--- a/modules/mono/glue/cs_files/DebuggingUtils.cs
+++ b/modules/mono/glue/cs_files/DebuggingUtils.cs
@@ -26,10 +26,16 @@ namespace Godot
MethodBase methodBase = frame.GetMethod();
+ if (methodBase == null)
+ {
+ methodDecl = string.Empty;
+ return;
+ }
+
StringBuilder sb = new StringBuilder();
- if (methodBase is MethodInfo methodInfo)
- sb.AppendTypeName(methodInfo.ReturnType);
+ if (methodBase is MethodInfo)
+ sb.AppendTypeName(((MethodInfo)methodBase).ReturnType);
sb.Append(methodBase.DeclaringType.FullName);
sb.Append(".");
diff --git a/modules/mono/glue/cs_files/Mathf.cs b/modules/mono/glue/cs_files/Mathf.cs
index 6951ace4fc..476396e9a3 100644
--- a/modules/mono/glue/cs_files/Mathf.cs
+++ b/modules/mono/glue/cs_files/Mathf.cs
@@ -71,7 +71,7 @@ namespace Godot
public static int Decimals(float step)
{
- return Decimals(step);
+ return Decimals((decimal)step);
}
public static int Decimals(decimal step)
diff --git a/modules/mono/glue/cs_files/Plane.cs b/modules/mono/glue/cs_files/Plane.cs
index 6365e71826..b347c0835a 100644
--- a/modules/mono/glue/cs_files/Plane.cs
+++ b/modules/mono/glue/cs_files/Plane.cs
@@ -91,7 +91,7 @@ namespace Godot
float dist = (normal.Dot(from) - d) / den;
- // This is a ray, before the emiting pos (from) does not exist
+ // This is a ray, before the emitting pos (from) does not exist
if (dist > Mathf.Epsilon)
return new Vector3();
diff --git a/modules/mono/glue/glue_header.h b/modules/mono/glue/glue_header.h
index 32988c5afa..cedc8e9992 100644
--- a/modules/mono/glue/glue_header.h
+++ b/modules/mono/glue/glue_header.h
@@ -28,6 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#include "builtin_types_glue.h"
+
#include "../csharp_script.h"
#include "../mono_gd/gd_mono_class.h"
#include "../mono_gd/gd_mono_internals.h"
@@ -91,12 +93,6 @@ MonoString *godot_icall_NodePath_operator_String(NodePath *p_np) {
return GDMonoMarshal::mono_string_from_godot(p_np->operator String());
}
-MonoArray *godot_icall_String_md5_buffer(MonoString *p_str) {
- Vector<uint8_t> ret = GDMonoMarshal::mono_string_to_godot(p_str).md5_buffer();
- // TODO Check possible Array/Vector<uint8_t> problem?
- return GDMonoMarshal::Array_to_mono_array(Variant(ret));
-}
-
// -- RID --
RID *godot_icall_RID_Ctor(Object *p_from) {
@@ -115,6 +111,12 @@ void godot_icall_RID_Dtor(RID *p_ptr) {
// -- String --
+MonoArray *godot_icall_String_md5_buffer(MonoString *p_str) {
+ Vector<uint8_t> ret = GDMonoMarshal::mono_string_to_godot(p_str).md5_buffer();
+ // TODO Check possible Array/Vector<uint8_t> problem?
+ return GDMonoMarshal::Array_to_mono_array(Variant(ret));
+}
+
MonoString *godot_icall_String_md5_text(MonoString *p_str) {
String ret = GDMonoMarshal::mono_string_to_godot(p_str).md5_text();
return GDMonoMarshal::mono_string_from_godot(ret);
@@ -303,3 +305,7 @@ MonoObject *godot_icall_Godot_weakref(Object *p_obj) {
return GDMonoUtils::create_managed_for_godot_object(CACHED_CLASS(WeakRef), Reference::get_class_static(), Object::cast_to<Object>(wref.ptr()));
}
+
+void godot_register_header_icalls() {
+ godot_register_builtin_type_icalls();
+}
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index 6c07c90f79..f5febd415b 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -696,11 +696,13 @@ bool _GodotSharp::is_domain_loaded() {
return GDMono::get_singleton()->get_scripts_domain() != NULL;
}
-#define ENQUEUE_FOR_DISPOSAL(m_queue, m_inst) \
- m_queue.push_back(m_inst); \
- if (queue_empty) { \
- queue_empty = false; \
- call_deferred("_dispose_callback"); \
+#define ENQUEUE_FOR_DISPOSAL(m_queue, m_inst) \
+ m_queue.push_back(m_inst); \
+ if (queue_empty) { \
+ queue_empty = false; \
+ if (!is_finalizing_domain()) { /* call_deferred may not be safe here */ \
+ call_deferred("_dispose_callback"); \
+ } \
}
void _GodotSharp::queue_dispose(MonoObject *p_mono_object, Object *p_object) {
diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp
index ba56ed6ed5..ef39b8549d 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.cpp
+++ b/modules/mono/mono_gd/gd_mono_assembly.cpp
@@ -116,6 +116,37 @@ MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **asse
}
}
+ String name = mono_assembly_name_get_name(aname);
+ bool has_extension = name.ends_with(".dll");
+
+ if (has_extension ? name == "mscorlib.dll" : name == "mscorlib") {
+ GDMonoAssembly **stored_assembly = GDMono::get_singleton()->get_loaded_assembly(has_extension ? name.get_basename() : name);
+ if (stored_assembly) return (*stored_assembly)->get_assembly();
+
+ String path;
+ MonoAssembly *res = NULL;
+
+ for (int i = 0; i < search_dirs.size(); i++) {
+ const String &search_dir = search_dirs[i];
+
+ if (has_extension) {
+ path = search_dir.plus_file(name);
+ if (FileAccess::exists(path)) {
+ res = _load_assembly_from(name.get_basename(), path);
+ break;
+ }
+ } else {
+ path = search_dir.plus_file(name + ".dll");
+ if (FileAccess::exists(path)) {
+ res = _load_assembly_from(name, path);
+ break;
+ }
+ }
+ }
+
+ if (res) return res;
+ }
+
return NULL;
}
diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h
index 8e7aa701bf..8a5fa19626 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.h
+++ b/modules/mono/mono_gd/gd_mono_assembly.h
@@ -110,7 +110,7 @@ public:
_FORCE_INLINE_ String get_path() const { return path; }
_FORCE_INLINE_ uint64_t get_modified_time() const { return modified_time; }
- GDMonoClass *get_class(const StringName &p_namespace, const StringName &p_class);
+ GDMonoClass *get_class(const StringName &p_namespace, const StringName &p_name);
GDMonoClass *get_class(MonoClass *p_mono_class);
GDMonoClass *get_object_derived_class(const StringName &p_class);
diff --git a/modules/mono/mono_gd/gd_mono_class.h b/modules/mono/mono_gd/gd_mono_class.h
index f5895be144..afccf2fc63 100644
--- a/modules/mono/mono_gd/gd_mono_class.h
+++ b/modules/mono/mono_gd/gd_mono_class.h
@@ -125,7 +125,7 @@ public:
GDMonoMethod *get_method(MonoMethod *p_raw_method);
GDMonoMethod *get_method(MonoMethod *p_raw_method, const StringName &p_name);
GDMonoMethod *get_method(MonoMethod *p_raw_method, const StringName &p_name, int p_params_count);
- GDMonoMethod *get_method_with_desc(const String &p_description, bool p_includes_namespace);
+ GDMonoMethod *get_method_with_desc(const String &p_description, bool p_include_namespace);
GDMonoField *get_field(const StringName &p_name);
const Vector<GDMonoField *> &get_all_fields();
diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp
index 1ec8f41c91..aa1a8e39c7 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.cpp
+++ b/modules/mono/mono_gd/gd_mono_marshal.cpp
@@ -459,11 +459,7 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
type.type_encoding = mono_type_get_type(raw_type);
type.type_class = tclass;
- return mono_object_to_variant(p_obj, type);
-}
-
-Variant mono_object_to_variant(MonoObject *p_obj, const ManagedType &p_type) {
- switch (p_type.type_encoding) {
+ switch (type.type_encoding) {
case MONO_TYPE_BOOLEAN:
return (bool)unbox<MonoBoolean>(p_obj);
@@ -497,7 +493,7 @@ Variant mono_object_to_variant(MonoObject *p_obj, const ManagedType &p_type) {
} break;
case MONO_TYPE_VALUETYPE: {
- GDMonoClass *tclass = p_type.type_class;
+ GDMonoClass *tclass = type.type_class;
if (tclass == CACHED_CLASS(Vector2))
RETURN_UNBOXED_STRUCT(Vector2, p_obj);
@@ -535,7 +531,7 @@ Variant mono_object_to_variant(MonoObject *p_obj, const ManagedType &p_type) {
case MONO_TYPE_ARRAY:
case MONO_TYPE_SZARRAY: {
- MonoArrayType *array_type = mono_type_get_array_type(GDMonoClass::get_raw_type(p_type.type_class));
+ MonoArrayType *array_type = mono_type_get_array_type(GDMonoClass::get_raw_type(type.type_class));
if (array_type->eklass == CACHED_CLASS_RAW(MonoObject))
return mono_array_to_Array((MonoArray *)p_obj);
@@ -566,7 +562,7 @@ Variant mono_object_to_variant(MonoObject *p_obj, const ManagedType &p_type) {
} break;
case MONO_TYPE_CLASS: {
- GDMonoClass *type_class = p_type.type_class;
+ GDMonoClass *type_class = type.type_class;
// GodotObject
if (CACHED_CLASS(GodotObject)->is_assignable_from(type_class)) {
@@ -586,14 +582,14 @@ Variant mono_object_to_variant(MonoObject *p_obj, const ManagedType &p_type) {
} break;
case MONO_TYPE_GENERICINST: {
- if (CACHED_RAW_MONO_CLASS(Dictionary) == p_type.type_class->get_mono_ptr()) {
+ if (CACHED_RAW_MONO_CLASS(Dictionary) == type.type_class->get_mono_ptr()) {
return mono_object_to_Dictionary(p_obj);
}
} break;
}
ERR_EXPLAIN(String() + "Attempted to convert an unmarshallable managed type to Variant. Name: \'" +
- p_type.type_class->get_name() + "\' Encoding: " + itos(p_type.type_encoding));
+ type.type_class->get_name() + "\' Encoding: " + itos(type.type_encoding));
ERR_FAIL_V(Variant());
}
diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h
index 727b9fa230..6572408ab5 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.h
+++ b/modules/mono/mono_gd/gd_mono_marshal.h
@@ -102,7 +102,6 @@ _FORCE_INLINE_ MonoObject *variant_to_mono_object(Variant p_var) {
}
Variant mono_object_to_variant(MonoObject *p_obj);
-Variant mono_object_to_variant(MonoObject *p_obj, const ManagedType &p_type);
// Array
diff --git a/modules/mono/mono_gd/gd_mono_property.cpp b/modules/mono/mono_gd/gd_mono_property.cpp
index bc5a1d3a39..0fe527b199 100644
--- a/modules/mono/mono_gd/gd_mono_property.cpp
+++ b/modules/mono/mono_gd/gd_mono_property.cpp
@@ -139,7 +139,7 @@ bool GDMonoProperty::has_setter() {
}
void GDMonoProperty::set_value(MonoObject *p_object, MonoObject *p_value, MonoObject **r_exc) {
- MonoMethod *prop_method = mono_property_get_get_method(mono_property);
+ MonoMethod *prop_method = mono_property_get_set_method(mono_property);
MonoArray *params = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), 1);
mono_array_set(params, MonoObject *, 0, p_value);
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index 4aa2c007c2..a2f0819a72 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -44,10 +44,13 @@ namespace GDMonoUtils {
MonoCache mono_cache;
-#define CACHE_AND_CHECK(m_var, m_val) \
- { \
- m_var = m_val; \
- if (!m_var) ERR_PRINT("Mono Cache: Member " #m_var " is null. This is really bad!"); \
+#define CACHE_AND_CHECK(m_var, m_val) \
+ { \
+ m_var = m_val; \
+ if (!m_var) { \
+ ERR_EXPLAIN("Mono Cache: Member " #m_var " is null"); \
+ ERR_FAIL(); \
+ } \
}
#define CACHE_CLASS_AND_CHECK(m_class, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.class_##m_class, m_val)
@@ -133,6 +136,12 @@ void MonoCache::clear_members() {
task_scheduler_handle = Ref<MonoGCHandle>();
}
+void MonoCache::cleanup() {
+
+ corlib_cache_updated = false;
+ godot_api_cache_updated = false;
+}
+
#define GODOT_API_CLASS(m_class) (GDMono::get_singleton()->get_api_assembly()->get_class(BINDINGS_NAMESPACE, #m_class))
void update_corlib_cache() {
@@ -158,6 +167,8 @@ void update_corlib_cache() {
CACHE_METHOD_AND_CHECK(System_Diagnostics_StackTrace, ctor_bool, CACHED_CLASS(System_Diagnostics_StackTrace)->get_method_with_desc("System.Diagnostics.StackTrace:.ctor(bool)", true));
CACHE_METHOD_AND_CHECK(System_Diagnostics_StackTrace, ctor_Exception_bool, CACHED_CLASS(System_Diagnostics_StackTrace)->get_method_with_desc("System.Diagnostics.StackTrace:.ctor(System.Exception,bool)", true));
#endif
+
+ mono_cache.corlib_cache_updated = true;
}
void update_godot_api_cache() {
@@ -173,7 +184,7 @@ void update_godot_api_cache() {
CACHE_CLASS_AND_CHECK(Color, GODOT_API_CLASS(Color));
CACHE_CLASS_AND_CHECK(Plane, GODOT_API_CLASS(Plane));
CACHE_CLASS_AND_CHECK(NodePath, GODOT_API_CLASS(NodePath));
- CACHE_CLASS_AND_CHECK(RID, GODOT_API_CLASS(NodePath));
+ CACHE_CLASS_AND_CHECK(RID, GODOT_API_CLASS(RID));
CACHE_CLASS_AND_CHECK(GodotObject, GODOT_API_CLASS(Object));
CACHE_CLASS_AND_CHECK(GodotReference, GODOT_API_CLASS(Reference));
CACHE_CLASS_AND_CHECK(Node, GODOT_API_CLASS(Node));
@@ -231,6 +242,8 @@ void update_godot_api_cache() {
MonoObject *task_scheduler = mono_object_new(SCRIPTS_DOMAIN, GODOT_API_CLASS(GodotTaskScheduler)->get_mono_ptr());
mono_runtime_object_init(task_scheduler);
mono_cache.task_scheduler_handle = MonoGCHandle::create_strong(task_scheduler);
+
+ mono_cache.corlib_cache_updated = true;
}
void clear_cache() {
@@ -399,9 +412,12 @@ void print_unhandled_exception(MonoObject *p_exc) {
print_unhandled_exception(p_exc, false);
}
-void print_unhandled_exception(MonoObject *p_exc, bool p_fail_silently) {
+void print_unhandled_exception(MonoObject *p_exc, bool p_recursion_caution) {
mono_print_unhandled_exception(p_exc);
#ifdef DEBUG_ENABLED
+ if (!ScriptDebugger::get_singleton())
+ return;
+
GDMonoClass *st_klass = CACHED_CLASS(System_Diagnostics_StackTrace);
MonoObject *stack_trace = mono_object_new(mono_domain_get(), st_klass->get_mono_ptr());
@@ -414,7 +430,7 @@ void print_unhandled_exception(MonoObject *p_exc, bool p_fail_silently) {
if (unexpected_exc != NULL) {
mono_print_unhandled_exception(unexpected_exc);
- if (p_fail_silently) {
+ if (p_recursion_caution) {
// Called from CSharpLanguage::get_current_stack_info,
// so printing an error here could result in endless recursion
OS::get_singleton()->printerr("Mono: Method GDMonoUtils::print_unhandled_exception failed");
@@ -425,7 +441,7 @@ void print_unhandled_exception(MonoObject *p_exc, bool p_fail_silently) {
}
Vector<ScriptLanguage::StackInfo> si;
- if (stack_trace != NULL)
+ if (stack_trace != NULL && !p_recursion_caution)
si = CSharpLanguage::get_singleton()->stack_trace_get_info(stack_trace);
String file = si.size() ? si[0].file : __FILE__;
diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h
index 1acc547993..259da46c31 100644
--- a/modules/mono/mono_gd/gd_mono_utils.h
+++ b/modules/mono/mono_gd/gd_mono_utils.h
@@ -43,7 +43,7 @@ namespace GDMonoUtils {
typedef MonoObject *(*MarshalUtils_DictToArrays)(MonoObject *, MonoArray **, MonoArray **, MonoObject **);
typedef MonoObject *(*MarshalUtils_ArraysToDict)(MonoArray *, MonoArray *, MonoObject **);
-typedef MonoObject *(*SignalAwaiter_SignalCallback)(MonoObject *, MonoArray **, MonoObject **);
+typedef MonoObject *(*SignalAwaiter_SignalCallback)(MonoObject *, MonoArray *, MonoObject **);
typedef MonoObject *(*SignalAwaiter_FailureCallback)(MonoObject *, MonoObject **);
typedef MonoObject *(*GodotTaskScheduler_Activate)(MonoObject *, MonoObject **);
typedef MonoArray *(*StackTrace_GetFrames)(MonoObject *, MonoObject **);
@@ -129,10 +129,16 @@ struct MonoCache {
Ref<MonoGCHandle> task_scheduler_handle;
+ bool corlib_cache_updated;
+ bool godot_api_cache_updated;
+
void clear_members();
- void cleanup() {}
+ void cleanup();
MonoCache() {
+ corlib_cache_updated = false;
+ godot_api_cache_updated = false;
+
clear_members();
}
};
@@ -177,7 +183,7 @@ MonoDomain *create_domain(const String &p_friendly_name);
String get_exception_name_and_message(MonoObject *p_ex);
void print_unhandled_exception(MonoObject *p_exc);
-void print_unhandled_exception(MonoObject *p_exc, bool p_fail_silently);
+void print_unhandled_exception(MonoObject *p_exc, bool p_recursion_caution);
} // namespace GDMonoUtils
diff --git a/modules/mono/signal_awaiter_utils.cpp b/modules/mono/signal_awaiter_utils.cpp
index 2671e9a970..b9d8520ac9 100644
--- a/modules/mono/signal_awaiter_utils.cpp
+++ b/modules/mono/signal_awaiter_utils.cpp
@@ -102,7 +102,7 @@ Variant SignalAwaiterHandle::_signal_callback(const Variant **p_args, int p_argc
GDMonoUtils::SignalAwaiter_SignalCallback thunk = CACHED_METHOD_THUNK(SignalAwaiter, SignalCallback);
MonoObject *ex = NULL;
- thunk(get_target(), &signal_args, &ex);
+ thunk(get_target(), signal_args, &ex);
if (ex) {
mono_print_unhandled_exception(ex);