summaryrefslogtreecommitdiffstats
path: root/modules/mono/csharp_script.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/mono/csharp_script.cpp')
-rw-r--r--modules/mono/csharp_script.cpp120
1 files changed, 73 insertions, 47 deletions
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index b5c91a8585..078a490b22 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -44,6 +44,10 @@
#include "editor/editor_node.h"
#endif
+#ifdef DEBUG_METHODS_ENABLED
+#include "class_db_api_json.h"
+#endif
+
#include "editor/editor_internal_calls.h"
#include "godotsharp_dirs.h"
#include "mono_gd/gd_mono_class.h"
@@ -98,18 +102,32 @@ Error CSharpLanguage::execute_file(const String &p_path) {
void CSharpLanguage::init() {
+#ifdef DEBUG_METHODS_ENABLED
+ if (OS::get_singleton()->get_cmdline_args().find("--class_db_to_json")) {
+ class_db_api_to_json("user://class_db_api.json", ClassDB::API_CORE);
+#ifdef TOOLS_ENABLED
+ class_db_api_to_json("user://class_db_api_editor.json", ClassDB::API_EDITOR);
+#endif
+ }
+#endif
+
gdmono = memnew(GDMono);
gdmono->initialize();
-#ifndef MONO_GLUE_ENABLED
- WARN_PRINT("This binary is built with `mono_glue=no` and cannot be used for scripting");
-#endif
-
#if defined(TOOLS_ENABLED) && defined(DEBUG_METHODS_ENABLED)
+ // Generate bindings here, before loading assemblies. `initialize_load_assemblies` aborts
+ // the applications if the api assemblies or the main tools assembly is missing, but this
+ // is not a problem for BindingsGenerator as it only needs the tools project editor assembly.
List<String> cmdline_args = OS::get_singleton()->get_cmdline_args();
BindingsGenerator::handle_cmdline_args(cmdline_args);
#endif
+#ifndef MONO_GLUE_ENABLED
+ print_line("Run this binary with `--generate-mono-glue path/to/modules/mono/glue`");
+#endif
+
+ gdmono->initialize_load_assemblies();
+
#ifdef TOOLS_ENABLED
EditorNode::add_init_callback(&_editor_init_callback);
@@ -697,14 +715,6 @@ bool CSharpLanguage::is_assembly_reloading_needed() {
return false; // No assembly to load
}
-#ifdef TOOLS_ENABLED
- if (!gdmono->get_core_api_assembly() && gdmono->metadata_is_api_assembly_invalidated(APIAssembly::API_CORE))
- return false; // The core API assembly to load is invalidated
-
- if (!gdmono->get_editor_api_assembly() && gdmono->metadata_is_api_assembly_invalidated(APIAssembly::API_EDITOR))
- return false; // The editor API assembly to load is invalidated
-#endif
-
return true;
}
@@ -867,17 +877,26 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
script->reload(p_soft_reload);
script->update_exports();
+
+ if (!script->valid) {
+ script->pending_reload_instances.clear();
+ continue;
+ }
} else {
const StringName &class_namespace = script->tied_class_namespace_for_reload;
const StringName &class_name = script->tied_class_name_for_reload;
GDMonoAssembly *project_assembly = gdmono->get_project_assembly();
- GDMonoAssembly *tools_assembly = gdmono->get_tools_assembly();
// Search in project and tools assemblies first as those are the most likely to have the class
GDMonoClass *script_class = (project_assembly ? project_assembly->get_class(class_namespace, class_name) : NULL);
+
+#ifdef TOOLS_ENABLED
if (!script_class) {
+ GDMonoAssembly *tools_assembly = gdmono->get_tools_assembly();
script_class = (tools_assembly ? tools_assembly->get_class(class_namespace, class_name) : NULL);
}
+#endif
+
if (!script_class) {
script_class = gdmono->get_class(class_namespace, class_name);
}
@@ -897,12 +916,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
GDMonoClass *native = GDMonoUtils::get_class_native_base(script_class);
- Ref<CSharpScript> new_script = CSharpScript::create_for_managed_type(script_class, native);
- CRASH_COND(new_script.is_null());
-
- new_script->pending_reload_instances = script->pending_reload_instances;
- new_script->pending_reload_state = script->pending_reload_state;
- script = new_script;
+ CSharpScript::initialize_for_managed_type(script, script_class, native);
}
String native_name = NATIVE_GDMONOCLASS_NAME(script->native);
@@ -953,7 +967,6 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
CRASH_COND(si != NULL);
#endif
// Re-create script instance
-
obj->set_script(script.get_ref_ptr()); // will create the script instance as well
}
}
@@ -1203,7 +1216,9 @@ CSharpLanguage::CSharpLanguage() {
scripts_metadata_invalidated = true;
+#ifdef TOOLS_ENABLED
godotsharp_editor = NULL;
+#endif
}
CSharpLanguage::~CSharpLanguage() {
@@ -2144,7 +2159,6 @@ void CSharpScript::_update_exports_values(Map<StringName, Variant> &values, List
propnames.push_back(E->get());
}
}
-#endif
void CSharpScript::_update_member_info_no_exports() {
@@ -2191,6 +2205,7 @@ void CSharpScript::_update_member_info_no_exports() {
}
}
}
+#endif
bool CSharpScript::_update_exports() {
@@ -2673,35 +2688,46 @@ void CSharpScript::_bind_methods() {
Ref<CSharpScript> CSharpScript::create_for_managed_type(GDMonoClass *p_class, GDMonoClass *p_native) {
- // This method should not fail
+ // This method should not fail, only assertions allowed
CRASH_COND(p_class == NULL);
// TODO OPTIMIZE: Cache the 'CSharpScript' associated with this 'p_class' instead of allocating a new one every time
Ref<CSharpScript> script = memnew(CSharpScript);
- script->name = p_class->get_name();
- script->script_class = p_class;
- script->native = p_native;
+ initialize_for_managed_type(script, p_class, p_native);
- CRASH_COND(script->native == NULL);
+ return script;
+}
- GDMonoClass *base = script->script_class->get_parent_class();
+void CSharpScript::initialize_for_managed_type(Ref<CSharpScript> p_script, GDMonoClass *p_class, GDMonoClass *p_native) {
- if (base != script->native)
- script->base = base;
+ // This method should not fail, only assertions allowed
- script->valid = true;
- script->tool = script->script_class->has_attribute(CACHED_CLASS(ToolAttribute));
+ CRASH_COND(p_class == NULL);
- if (!script->tool) {
- GDMonoClass *nesting_class = script->script_class->get_nesting_class();
- script->tool = nesting_class && nesting_class->has_attribute(CACHED_CLASS(ToolAttribute));
+ p_script->name = p_class->get_name();
+ p_script->script_class = p_class;
+ p_script->native = p_native;
+
+ CRASH_COND(p_script->native == NULL);
+
+ GDMonoClass *base = p_script->script_class->get_parent_class();
+
+ if (base != p_script->native)
+ p_script->base = base;
+
+ p_script->valid = true;
+ p_script->tool = p_script->script_class->has_attribute(CACHED_CLASS(ToolAttribute));
+
+ if (!p_script->tool) {
+ GDMonoClass *nesting_class = p_script->script_class->get_nesting_class();
+ p_script->tool = nesting_class && nesting_class->has_attribute(CACHED_CLASS(ToolAttribute));
}
#if TOOLS_ENABLED
- if (!script->tool) {
- script->tool = script->script_class->get_assembly() == GDMono::get_singleton()->get_tools_assembly();
+ if (!p_script->tool) {
+ p_script->tool = p_script->script_class->get_assembly() == GDMono::get_singleton()->get_tools_assembly();
}
#endif
@@ -2710,10 +2736,10 @@ Ref<CSharpScript> CSharpScript::create_for_managed_type(GDMonoClass *p_class, GD
// Native base methods must be fetched before the current class.
// Not needed if the script class itself is a native class.
- if (script->script_class != script->native) {
- GDMonoClass *native_top = script->native;
+ if (p_script->script_class != p_script->native) {
+ GDMonoClass *native_top = p_script->native;
while (native_top) {
- native_top->fetch_methods_with_godot_api_checks(script->native);
+ native_top->fetch_methods_with_godot_api_checks(p_script->native);
if (native_top == CACHED_CLASS(GodotObject))
break;
@@ -2723,19 +2749,19 @@ Ref<CSharpScript> CSharpScript::create_for_managed_type(GDMonoClass *p_class, GD
}
#endif
- script->script_class->fetch_methods_with_godot_api_checks(script->native);
+ p_script->script_class->fetch_methods_with_godot_api_checks(p_script->native);
// Need to fetch method from base classes as well
- GDMonoClass *top = script->script_class;
- while (top && top != script->native) {
- top->fetch_methods_with_godot_api_checks(script->native);
+ GDMonoClass *top = p_script->script_class;
+ while (top && top != p_script->native) {
+ top->fetch_methods_with_godot_api_checks(p_script->native);
top = top->get_parent_class();
}
- script->load_script_signals(script->script_class, script->native);
- script->_update_member_info_no_exports();
-
- return script;
+ p_script->load_script_signals(p_script->script_class, p_script->native);
+#ifdef TOOLS_ENABLED
+ p_script->_update_member_info_no_exports();
+#endif
}
bool CSharpScript::can_instance() const {