diff options
-rw-r--r-- | compat.py | 29 | ||||
-rw-r--r-- | editor/SCsub | 14 | ||||
-rw-r--r-- | editor/editor_settings.cpp | 2 | ||||
-rw-r--r-- | modules/mono/csharp_script.cpp | 78 | ||||
-rw-r--r-- | modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs | 2 | ||||
-rw-r--r-- | modules/mono/editor/godotsharp_builds.cpp | 6 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono.cpp | 34 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono.h | 2 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_assembly.cpp | 97 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_assembly.h | 8 | ||||
-rw-r--r-- | modules/mono/mono_reg_utils.py | 6 | ||||
-rw-r--r-- | platform/osx/detect.py | 2 |
12 files changed, 184 insertions, 96 deletions
@@ -14,6 +14,17 @@ if sys.version_info < (3,): return x def iteritems(d): return d.iteritems() + def escape_string(s): + if isinstance(s, unicode): + s = s.encode('ascii') + result = '' + for c in s: + if not (32 <= ord(c) < 127) or c in ('\\', '"'): + result += '\\%03o' % ord(c) + else: + result += c + return result + else: def isbasestring(s): return isinstance(s, (str, bytes)) @@ -29,3 +40,21 @@ else: return codecs.utf_8_encode(x)[0] def iteritems(d): return iter(d.items()) + def charcode_to_c_escapes(c): + rev_result = [] + while c >= 256: + c, low = (c // 256, c % 256) + rev_result.append('\\%03o' % low) + rev_result.append('\\%03o' % c) + return ''.join(reversed(rev_result)) + def escape_string(s): + result = '' + if isinstance(s, str): + s = s.encode('utf-8') + for c in s: + if not(32 <= c < 127) or c in (ord('\\'), ord('"')): + result += charcode_to_c_escapes(c) + else: + result += chr(c) + return result + diff --git a/editor/SCsub b/editor/SCsub index 11cdb471a8..e44b4e4bb2 100644 --- a/editor/SCsub +++ b/editor/SCsub @@ -4,18 +4,8 @@ Import('env') env.editor_sources = [] import os -from compat import encode_utf8, byte_to_str, open_utf8 - -def escape_string(s, encoding='ascii'): - if isinstance(s, unicode): - s = s.encode(encoding) - result = '' - for c in s: - if not (32 <= ord(c) < 127) or c in ('\\', '"'): - result += '\\%03o' % ord(c) - else: - result += c - return result +from compat import encode_utf8, byte_to_str, open_utf8, escape_string + def make_certs_header(target, source, env): diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 84b0917c78..b532bb793a 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -1225,8 +1225,6 @@ void EditorSettings::_bind_methods() { ClassDB::bind_method(D_METHOD("set_initial_value", "name", "value"), &EditorSettings::set_initial_value); - ClassDB::bind_method(D_METHOD("set_favorite_dirs", "dirs"), &EditorSettings::set_favorite_dirs); - ADD_SIGNAL(MethodInfo("settings_changed")); } diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 5301ea72b4..7de90dfbc3 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -1201,8 +1201,6 @@ bool CSharpScript::_update_exports() { exported_members_cache.clear(); exported_members_defval_cache.clear(); - const Vector<GDMonoField *> &fields = script_class->get_all_fields(); - // We are creating a temporary new instance of the class here to get the default value // TODO Workaround. Should be replaced with IL opcodes analysis @@ -1226,36 +1224,47 @@ bool CSharpScript::_update_exports() { return false; } - for (int i = 0; i < fields.size(); i++) { - GDMonoField *field = fields[i]; + GDMonoClass *top = script_class; - if (field->is_static() || field->get_visibility() != GDMono::PUBLIC) - continue; + while (top && top != native) { + const Vector<GDMonoField *> &fields = top->get_all_fields(); + + for (int i = 0; i < fields.size(); i++) { + GDMonoField *field = fields[i]; + + if (field->is_static() || field->get_visibility() != GDMono::PUBLIC) + continue; + + String name = field->get_name(); + StringName cname = name; - String name = field->get_name(); - StringName cname = name; + if (member_info.has(cname)) + continue; - Variant::Type type = GDMonoMarshal::managed_to_variant_type(field->get_type()); + Variant::Type type = GDMonoMarshal::managed_to_variant_type(field->get_type()); - if (field->has_attribute(CACHED_CLASS(ExportAttribute))) { - MonoObject *attr = field->get_attribute(CACHED_CLASS(ExportAttribute)); + if (field->has_attribute(CACHED_CLASS(ExportAttribute))) { + MonoObject *attr = field->get_attribute(CACHED_CLASS(ExportAttribute)); - // Field has Export attribute - int hint = CACHED_FIELD(ExportAttribute, hint)->get_int_value(attr); - String hint_string = CACHED_FIELD(ExportAttribute, hint_string)->get_string_value(attr); - int usage = CACHED_FIELD(ExportAttribute, usage)->get_int_value(attr); + // Field has Export attribute + int hint = CACHED_FIELD(ExportAttribute, hint)->get_int_value(attr); + String hint_string = CACHED_FIELD(ExportAttribute, hint_string)->get_string_value(attr); + int usage = CACHED_FIELD(ExportAttribute, usage)->get_int_value(attr); - PropertyInfo prop_info = PropertyInfo(type, name, PropertyHint(hint), hint_string, PropertyUsageFlags(usage)); + PropertyInfo prop_info = PropertyInfo(type, name, PropertyHint(hint), hint_string, PropertyUsageFlags(usage)); - member_info[cname] = prop_info; - exported_members_cache.push_back(prop_info); + member_info[cname] = prop_info; + exported_members_cache.push_back(prop_info); - if (tmp_object) { - exported_members_defval_cache[cname] = GDMonoMarshal::mono_object_to_variant(field->get_value(tmp_object)); + if (tmp_object) { + exported_members_defval_cache[cname] = GDMonoMarshal::mono_object_to_variant(field->get_value(tmp_object)); + } + } else { + member_info[cname] = PropertyInfo(type, name, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_SCRIPT_VARIABLE); } - } else { - member_info[cname] = PropertyInfo(type, name, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_SCRIPT_VARIABLE); } + + top = top->get_parent_class(); } } @@ -1795,6 +1804,31 @@ RES ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p #endif script->set_path(p_original_path); + +#ifndef TOOLS_ENABLED + +#ifdef DEBUG_ENABLED + // User is responsible for thread attach/detach + ERR_EXPLAIN("Thread is not attached"); + CRASH_COND(mono_domain_get() == NULL); +#endif + +#else + if (Engine::get_singleton()->is_editor_hint() && mono_domain_get() == NULL) { + + CRASH_COND(Thread::get_caller_id() == Thread::get_main_id()); + + // Thread is not attached, but we will make an exception in this case + // because this may be called by one of the editor's worker threads. + // Attach this thread temporarily to reload the script. + + MonoThread *mono_thread = mono_thread_attach(SCRIPTS_DOMAIN); + CRASH_COND(mono_thread == NULL); + script->reload(); + mono_thread_detach(mono_thread); + + } else // just reload it normally +#endif script->reload(); if (r_error) diff --git a/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs b/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs index 329b6d2008..5544233eb7 100644 --- a/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs +++ b/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs @@ -106,7 +106,7 @@ namespace GodotSharpTools.Build private string BuildArguments(string loggerAssemblyPath, string loggerOutputDir, string[] customProperties) { - string arguments = string.Format("{0} /v:normal /t:Build /p:{1} /l:{2},{3};{4}", + string arguments = string.Format(@"""{0}"" /v:normal /t:Build ""/p:{1}"" ""/l:{2},{3};{4}""", solution, "Configuration=" + config, typeof(GodotBuildLogger).FullName, diff --git a/modules/mono/editor/godotsharp_builds.cpp b/modules/mono/editor/godotsharp_builds.cpp index b7e3fb0a32..1bad8a3f85 100644 --- a/modules/mono/editor/godotsharp_builds.cpp +++ b/modules/mono/editor/godotsharp_builds.cpp @@ -59,7 +59,7 @@ String _find_build_engine_on_unix(const String &p_name) { "/opt/novell/mono/bin/" }; - for (int i = 0; i < sizeof(locations) / sizeof(char); i++) { + for (int i = 0; i < sizeof(locations) / sizeof(const char *); i++) { String location = locations[i]; if (FileAccess::exists(location + p_name)) { @@ -461,6 +461,10 @@ void GodotSharpBuilds::BuildProcess::start(bool p_blocking) { if (p_blocking) { exited = true; exit_code = klass->get_field("exitCode")->get_int_value(mono_object); + + if (exit_code != 0 && OS::get_singleton()->is_stdout_verbose()) + OS::get_singleton()->print(String("MSBuild finished with exit code " + itos(exit_code) + "\n").utf8()); + build_tab->on_build_exit(exit_code == 0 ? MonoBuildTab::RESULT_SUCCESS : MonoBuildTab::RESULT_ERROR); } else { build_instance = MonoGCHandle::create_strong(mono_object); diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index d0b5b12d4b..2c88832998 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -266,6 +266,13 @@ void GDMono::add_assembly(uint32_t p_domain_id, GDMonoAssembly *p_assembly) { assemblies[p_domain_id][p_assembly->get_name()] = p_assembly; } +GDMonoAssembly **GDMono::get_loaded_assembly(const String &p_name) { + + MonoDomain *domain = mono_domain_get(); + uint32_t domain_id = domain ? mono_domain_get_id(domain) : 0; + return assemblies[domain_id].getptr(p_name); +} + bool GDMono::_load_assembly(const String &p_name, GDMonoAssembly **r_assembly) { CRASH_COND(!r_assembly); @@ -278,34 +285,17 @@ bool GDMono::_load_assembly(const String &p_name, GDMonoAssembly **r_assembly) { MonoAssembly *assembly = mono_assembly_load_full(aname, NULL, &status, false); mono_assembly_name_free(aname); - if (!assembly) - return false; + ERR_FAIL_NULL_V(assembly, false); uint32_t domain_id = mono_domain_get_id(mono_domain_get()); GDMonoAssembly **stored_assembly = assemblies[domain_id].getptr(p_name); - if (stored_assembly) { - // Loaded by our preload hook (status is not initialized when returning from a preload hook) - ERR_FAIL_COND_V((*stored_assembly)->get_assembly() != assembly, false); - *r_assembly = *stored_assembly; - } else { - ERR_FAIL_COND_V(status != MONO_IMAGE_OK, false); - - MonoImage *assembly_image = mono_assembly_get_image(assembly); - ERR_FAIL_NULL_V(assembly_image, false); - - const char *path = mono_image_get_filename(assembly_image); - - *r_assembly = memnew(GDMonoAssembly(p_name, path)); - Error error = (*r_assembly)->wrapper_for_image(assembly_image); + ERR_FAIL_COND_V(status != MONO_IMAGE_OK, false); + ERR_FAIL_COND_V(stored_assembly == NULL, false); - if (error != OK) { - memdelete(*r_assembly); - *r_assembly = NULL; - ERR_FAIL_V(false); - } - } + ERR_FAIL_COND_V((*stored_assembly)->get_assembly() != assembly, false); + *r_assembly = *stored_assembly; if (OS::get_singleton()->is_stdout_verbose()) OS::get_singleton()->print(String("Mono: Assembly " + p_name + " loaded from path: " + (*r_assembly)->get_path() + "\n").utf8()); diff --git a/modules/mono/mono_gd/gd_mono.h b/modules/mono/mono_gd/gd_mono.h index ab96d575e6..b188c0730a 100644 --- a/modules/mono/mono_gd/gd_mono.h +++ b/modules/mono/mono_gd/gd_mono.h @@ -122,7 +122,9 @@ public: static GDMono *get_singleton() { return singleton; } + // Do not use these, unless you know what you're doing void add_assembly(uint32_t p_domain_id, GDMonoAssembly *p_assembly); + GDMonoAssembly **get_loaded_assembly(const String &p_name); _FORCE_INLINE_ bool is_runtime_initialized() const { return runtime_initialized; } _FORCE_INLINE_ bool is_finalizing_scripts_domain() const { return finalizing_scripts_domain; } diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp index a98537b9e1..a623b34b68 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.cpp +++ b/modules/mono/mono_gd/gd_mono_assembly.cpp @@ -39,28 +39,60 @@ #include "../godotsharp_dirs.h" #include "gd_mono_class.h" -MonoAssembly *gdmono_load_assembly_from(const String &p_name, const String &p_path) { +bool GDMonoAssembly::no_search = false; +Vector<String> GDMonoAssembly::search_dirs; - MonoDomain *domain = mono_domain_get(); +MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_data) { - GDMonoAssembly *assembly = memnew(GDMonoAssembly(p_name, p_path)); - Error err = assembly->load(domain); - ERR_FAIL_COND_V(err != OK, NULL); + (void)user_data; // UNUSED - GDMono::get_singleton()->add_assembly(mono_domain_get_id(domain), assembly); + String name = mono_assembly_name_get_name(aname); + bool has_extension = name.ends_with(".dll") || name.ends_with(".exe"); - return assembly->get_assembly(); -} + if (no_search) + return NULL; -MonoAssembly *gdmono_MonoAssemblyPreLoad(MonoAssemblyName *aname, char **assemblies_path, void *user_data) { + no_search = true; // Avoid the recursion madness - (void)user_data; // UNUSED + GDMonoAssembly **loaded_asm = GDMono::get_singleton()->get_loaded_assembly(has_extension ? name.get_basename() : name); + if (loaded_asm) + return (*loaded_asm)->get_assembly(); + + String path; + MonoAssembly *res = NULL; + + for (int i = 0; i < search_dirs.size(); i++) { + const String &search_dir = search_dirs[i]; - MonoAssembly *assembly_loaded = mono_assembly_loaded(aname); - if (assembly_loaded) // Already loaded - return assembly_loaded; + 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; + } + + path = search_dir.plus_file(name + ".exe"); + if (FileAccess::exists(path)) { + res = _load_assembly_from(name, path); + break; + } + } + } - static Vector<String> search_dirs; + no_search = false; + + return res; +} + +MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data) { + + (void)user_data; // UNUSED if (search_dirs.empty()) { search_dirs.push_back(GodotSharpDirs::get_res_temp_assemblies_dir()); @@ -80,35 +112,32 @@ MonoAssembly *gdmono_MonoAssemblyPreLoad(MonoAssemblyName *aname, char **assembl } } - String name = mono_assembly_name_get_name(aname); - bool has_extension = name.ends_with(".dll") || name.ends_with(".exe"); + return NULL; +} - String path; +MonoAssembly *GDMonoAssembly::_load_assembly_from(const String &p_name, const String &p_path) { - for (int i = 0; i < search_dirs.size(); i++) { - const String &search_dir = search_dirs[i]; + GDMonoAssembly *assembly = memnew(GDMonoAssembly(p_name, p_path)); - if (has_extension) { - path = search_dir.plus_file(name); - if (FileAccess::exists(path)) - return gdmono_load_assembly_from(name.get_basename(), path); - } else { - path = search_dir.plus_file(name + ".dll"); - if (FileAccess::exists(path)) - return gdmono_load_assembly_from(name, path); + MonoDomain *domain = mono_domain_get(); - path = search_dir.plus_file(name + ".exe"); - if (FileAccess::exists(path)) - return gdmono_load_assembly_from(name, path); - } + Error err = assembly->load(domain); + + if (err != OK) { + memdelete(assembly); + ERR_FAIL_V(NULL); } - return NULL; + GDMono::get_singleton()->add_assembly(domain ? mono_domain_get_id(domain) : 0, assembly); + + return assembly->get_assembly(); } void GDMonoAssembly::initialize() { - mono_install_assembly_preload_hook(&gdmono_MonoAssemblyPreLoad, NULL); + // TODO refonly as well? + mono_install_assembly_preload_hook(&GDMonoAssembly::_preload_hook, NULL); + mono_install_assembly_search_hook(&GDMonoAssembly::_search_hook, NULL); } Error GDMonoAssembly::load(MonoDomain *p_domain) { @@ -153,7 +182,7 @@ no_pdb: ERR_FAIL_COND_V(status != MONO_IMAGE_OK || assembly == NULL, ERR_FILE_CANT_OPEN); - if (mono_image_get_entry_point(image)) { + if (p_domain && mono_image_get_entry_point(image)) { // TODO should this be removed? do we want to call main? what other effects does this have? mono_jit_exec(p_domain, assembly, 0, NULL); } diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h index 89e091549c..710b674622 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.h +++ b/modules/mono/mono_gd/gd_mono_assembly.h @@ -86,6 +86,14 @@ class GDMonoAssembly { Vector<uint8_t> pdb_data; #endif + static bool no_search; + static Vector<String> search_dirs; + + static MonoAssembly *_search_hook(MonoAssemblyName *aname, void *user_data); + static MonoAssembly *_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data); + + static MonoAssembly *_load_assembly_from(const String &p_name, const String &p_path); + friend class GDMono; static void initialize(); diff --git a/modules/mono/mono_reg_utils.py b/modules/mono/mono_reg_utils.py index 6f1620ff49..e9988625f5 100644 --- a/modules/mono/mono_reg_utils.py +++ b/modules/mono/mono_reg_utils.py @@ -1,7 +1,11 @@ import os if os.name == 'nt': - import _winreg as winreg + import sys + if sys.version_info < (3,): + import _winreg as winreg + else: + import winreg def _reg_open_key(key, subkey): diff --git a/platform/osx/detect.py b/platform/osx/detect.py index f66c3f00da..31032659b6 100644 --- a/platform/osx/detect.py +++ b/platform/osx/detect.py @@ -62,7 +62,7 @@ def configure(env): ## Compiler configuration - if (not os.environ.has_key("OSXCROSS_ROOT")): # regular native build + if "OSXCROSS_ROOT" not in os.environ: # regular native build if (env["bits"] == "fat"): env.Append(CCFLAGS=['-arch', 'i386', '-arch', 'x86_64']) env.Append(LINKFLAGS=['-arch', 'i386', '-arch', 'x86_64']) |