diff options
Diffstat (limited to 'modules/mono/csharp_script.cpp')
-rw-r--r-- | modules/mono/csharp_script.cpp | 360 |
1 files changed, 149 insertions, 211 deletions
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 0b5d3c8dbc..ae25bd3544 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -67,7 +67,6 @@ #ifdef TOOLS_ENABLED static bool _create_project_solution_if_needed() { - String sln_path = GodotSharpDirs::get_project_sln_path(); String csproj_path = GodotSharpDirs::get_project_csproj_path(); @@ -85,28 +84,23 @@ static bool _create_project_solution_if_needed() { CSharpLanguage *CSharpLanguage::singleton = nullptr; String CSharpLanguage::get_name() const { - return "C#"; } String CSharpLanguage::get_type() const { - return "CSharpScript"; } String CSharpLanguage::get_extension() const { - return "cs"; } Error CSharpLanguage::execute_file(const String &p_path) { - // ?? return OK; } void CSharpLanguage::init() { - #ifdef DEBUG_METHODS_ENABLED if (OS::get_singleton()->get_cmdline_args().find("--class-db-json")) { class_db_api_to_json("user://class_db_api.json", ClassDB::API_CORE); @@ -140,7 +134,6 @@ void CSharpLanguage::init() { } void CSharpLanguage::finish() { - if (finalized) return; @@ -184,7 +177,6 @@ void CSharpLanguage::finish() { } void CSharpLanguage::get_reserved_words(List<String> *p_words) const { - static const char *_reserved_words[] = { // Reserved keywords "abstract", @@ -295,7 +287,7 @@ void CSharpLanguage::get_reserved_words(List<String> *p_words) const { "when", "where", "yield", - 0 + nullptr }; const char **w = _reserved_words; @@ -307,13 +299,11 @@ void CSharpLanguage::get_reserved_words(List<String> *p_words) const { } void CSharpLanguage::get_comment_delimiters(List<String> *p_delimiters) const { - p_delimiters->push_back("//"); // single-line comment p_delimiters->push_back("/* */"); // delimited comment } void CSharpLanguage::get_string_delimiters(List<String> *p_delimiters) const { - p_delimiters->push_back("' '"); // character literal p_delimiters->push_back("\" \""); // regular string literal // Verbatim string literals (`@" "`) don't render correctly, so don't highlight them. @@ -321,7 +311,6 @@ void CSharpLanguage::get_string_delimiters(List<String> *p_delimiters) const { } static String get_base_class_name(const String &p_base_class_name, const String p_class_name) { - String base_class = p_base_class_name; if (p_class_name == base_class) { base_class = "Godot." + base_class; @@ -330,7 +319,6 @@ static String get_base_class_name(const String &p_base_class_name, const String } Ref<Script> CSharpLanguage::get_template(const String &p_class_name, const String &p_base_class_name) const { - String script_template = "using " BINDINGS_NAMESPACE ";\n" "using System;\n" "\n" @@ -366,12 +354,10 @@ Ref<Script> CSharpLanguage::get_template(const String &p_class_name, const Strin } bool CSharpLanguage::is_using_templates() { - return true; } void CSharpLanguage::make_template(const String &p_class_name, const String &p_base_class_name, Ref<Script> &p_script) { - String src = p_script->get_source_code(); String base_class_name = get_base_class_name(p_base_class_name, p_class_name); src = src.replace("%BASE%", base_class_name) @@ -381,7 +367,6 @@ void CSharpLanguage::make_template(const String &p_class_name, const String &p_b } String CSharpLanguage::validate_path(const String &p_path) const { - String class_name = p_path.get_file().get_basename(); List<String> keywords; get_reserved_words(&keywords); @@ -392,23 +377,19 @@ String CSharpLanguage::validate_path(const String &p_path) const { } Script *CSharpLanguage::create_script() const { - return memnew(CSharpScript); } bool CSharpLanguage::has_named_classes() const { - return false; } bool CSharpLanguage::supports_builtin_mode() const { - return false; } #ifdef TOOLS_ENABLED static String variant_type_to_managed_name(const String &p_var_type_name) { - if (p_var_type_name.empty()) return "object"; @@ -531,12 +512,10 @@ String CSharpLanguage::_get_indentation() const { } String CSharpLanguage::debug_get_error() const { - return _debug_error; } int CSharpLanguage::debug_get_stack_level_count() const { - if (_debug_parse_err_line >= 0) return 1; @@ -545,7 +524,6 @@ int CSharpLanguage::debug_get_stack_level_count() const { } int CSharpLanguage::debug_get_stack_level_line(int p_level) const { - if (_debug_parse_err_line >= 0) return _debug_parse_err_line; @@ -554,7 +532,6 @@ int CSharpLanguage::debug_get_stack_level_line(int p_level) const { } String CSharpLanguage::debug_get_stack_level_function(int p_level) const { - if (_debug_parse_err_line >= 0) return String(); @@ -563,7 +540,6 @@ String CSharpLanguage::debug_get_stack_level_function(int p_level) const { } String CSharpLanguage::debug_get_stack_level_source(int p_level) const { - if (_debug_parse_err_line >= 0) return _debug_parse_err_file; @@ -572,7 +548,6 @@ String CSharpLanguage::debug_get_stack_level_source(int p_level) 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 static thread_local bool _recursion_flag_ = false; @@ -604,7 +579,6 @@ Vector<ScriptLanguage::StackInfo> CSharpLanguage::debug_get_current_stack_info() #ifdef DEBUG_ENABLED Vector<ScriptLanguage::StackInfo> CSharpLanguage::stack_trace_get_info(MonoObject *p_stack_trace) { - // Printing an error here will result in endless recursion, so we must be careful static thread_local bool _recursion_flag_ = false; if (_recursion_flag_) @@ -678,7 +652,6 @@ void CSharpLanguage::pre_unsafe_unreference(Object *p_obj) { } void CSharpLanguage::frame() { - if (gdmono && gdmono->is_runtime_initialized() && gdmono->get_core_api_assembly() != nullptr) { const Ref<MonoGCHandleRef> &task_scheduler_handle = GDMonoCache::cached_data.task_scheduler_handle; @@ -698,7 +671,6 @@ void CSharpLanguage::frame() { } struct CSharpScriptDepSort { - // must support sorting so inheritance works properly (parent must be reloaded first) bool operator()(const Ref<CSharpScript> &A, const Ref<CSharpScript> &B) const { if (A == B) @@ -718,7 +690,6 @@ struct CSharpScriptDepSort { }; void CSharpLanguage::reload_all_scripts() { - #ifdef GD_MONO_HOT_RELOAD if (is_assembly_reloading_needed()) { GD_MONO_SCOPE_THREAD_ATTACH; @@ -728,7 +699,6 @@ void CSharpLanguage::reload_all_scripts() { } void CSharpLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) { - (void)p_script; // UNUSED CRASH_COND(!Engine::get_singleton()->is_editor_hint()); @@ -747,7 +717,6 @@ void CSharpLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft #ifdef GD_MONO_HOT_RELOAD bool CSharpLanguage::is_assembly_reloading_needed() { - if (!gdmono->is_runtime_initialized()) return false; @@ -782,7 +751,6 @@ bool CSharpLanguage::is_assembly_reloading_needed() { } void CSharpLanguage::reload_assemblies(bool p_soft_reload) { - if (!gdmono->is_runtime_initialized()) return; @@ -850,7 +818,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { to_reload.push_back(script); if (script->get_path().empty()) { - script->tied_class_name_for_reload = script->script_class->get_name(); + script->tied_class_name_for_reload = script->script_class->get_name_for_lookup(); script->tied_class_namespace_for_reload = script->script_class->get_namespace(); } @@ -1173,7 +1141,6 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { #endif void CSharpLanguage::_load_scripts_metadata() { - scripts_metadata.clear(); String scripts_metadata_filename = "scripts_metadata."; @@ -1218,24 +1185,20 @@ void CSharpLanguage::_load_scripts_metadata() { } void CSharpLanguage::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("cs"); } #ifdef TOOLS_ENABLED Error CSharpLanguage::open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) { - return (Error)(int)get_godotsharp_editor()->call("OpenInExternalEditor", p_script, p_line, p_col); } bool CSharpLanguage::overrides_external_editor() { - return get_godotsharp_editor()->call("OverridesExternalEditor"); } #endif void CSharpLanguage::thread_enter() { - #if 0 if (gdmono->is_runtime_initialized()) { GDMonoUtils::attach_current_thread(); @@ -1244,7 +1207,6 @@ void CSharpLanguage::thread_enter() { } void CSharpLanguage::thread_exit() { - #if 0 if (gdmono->is_runtime_initialized()) { GDMonoUtils::detach_current_thread(); @@ -1253,7 +1215,6 @@ void CSharpLanguage::thread_exit() { } bool CSharpLanguage::debug_break_parse(const String &p_file, int p_line, const String &p_error) { - // Not a parser error in our case, but it's still used for other type of errors if (EngineDebugger::is_active() && Thread::get_caller_id() == Thread::get_main_id()) { _debug_parse_err_line = p_line; @@ -1267,7 +1228,6 @@ bool CSharpLanguage::debug_break_parse(const String &p_file, int p_line, const S } bool CSharpLanguage::debug_break(const String &p_error, bool p_allow_continue) { - if (EngineDebugger::is_active() && Thread::get_caller_id() == Thread::get_main_id()) { _debug_parse_err_line = -1; _debug_parse_err_file = ""; @@ -1301,7 +1261,6 @@ void CSharpLanguage::_on_scripts_domain_unloaded() { #ifdef TOOLS_ENABLED void CSharpLanguage::_editor_init_callback() { - register_editor_internal_calls(); // Initialize GodotSharpEditor @@ -1328,13 +1287,11 @@ void CSharpLanguage::_editor_init_callback() { #endif void CSharpLanguage::set_language_index(int p_idx) { - ERR_FAIL_COND(lang_idx != -1); lang_idx = p_idx; } void CSharpLanguage::release_script_gchandle(MonoGCHandleData &p_gchandle) { - if (!p_gchandle.is_released()) { // Do not lock unnecessarily MutexLock lock(get_singleton()->script_gchandle_release_mutex); p_gchandle.release(); @@ -1342,7 +1299,6 @@ void CSharpLanguage::release_script_gchandle(MonoGCHandleData &p_gchandle) { } void CSharpLanguage::release_script_gchandle(MonoObject *p_expected_obj, MonoGCHandleData &p_gchandle) { - uint32_t pinned_gchandle = GDMonoUtils::new_strong_gchandle_pinned(p_expected_obj); // We might lock after this, so pin it if (!p_gchandle.is_released()) { // Do not lock unnecessarily @@ -1363,19 +1319,16 @@ void CSharpLanguage::release_script_gchandle(MonoObject *p_expected_obj, MonoGCH } CSharpLanguage::CSharpLanguage() { - ERR_FAIL_COND_MSG(singleton, "C# singleton already exist."); singleton = this; } CSharpLanguage::~CSharpLanguage() { - finish(); singleton = nullptr; } bool CSharpLanguage::setup_csharp_script_binding(CSharpScriptBinding &r_script_binding, Object *p_object) { - #ifdef DEBUG_ENABLED // I don't trust you if (p_object->get_script_instance()) { @@ -1424,7 +1377,6 @@ bool CSharpLanguage::setup_csharp_script_binding(CSharpScriptBinding &r_script_b } void *CSharpLanguage::alloc_instance_binding_data(Object *p_object) { - MutexLock lock(language_bind_mutex); Map<Object *, CSharpScriptBinding>::Element *match = script_bindings.find(p_object); @@ -1440,12 +1392,10 @@ void *CSharpLanguage::alloc_instance_binding_data(Object *p_object) { } Map<Object *, CSharpScriptBinding>::Element *CSharpLanguage::insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding) { - return script_bindings.insert(p_object, p_script_binding); } void CSharpLanguage::free_instance_binding_data(void *p_data) { - if (GDMono::get_singleton() == nullptr) { #ifdef DEBUG_ENABLED CRASH_COND(!script_bindings.empty()); @@ -1481,7 +1431,6 @@ void CSharpLanguage::free_instance_binding_data(void *p_data) { } void CSharpLanguage::refcount_incremented_instance_binding(Object *p_object) { - Reference *ref_owner = Object::cast_to<Reference>(p_object); #ifdef DEBUG_ENABLED @@ -1517,7 +1466,6 @@ void CSharpLanguage::refcount_incremented_instance_binding(Object *p_object) { } bool CSharpLanguage::refcount_decremented_instance_binding(Object *p_object) { - Reference *ref_owner = Object::cast_to<Reference>(p_object); #ifdef DEBUG_ENABLED @@ -1558,7 +1506,6 @@ bool CSharpLanguage::refcount_decremented_instance_binding(Object *p_object) { } CSharpInstance *CSharpInstance::create_for_managed_type(Object *p_owner, CSharpScript *p_script, const MonoGCHandleData &p_gchandle) { - CSharpInstance *instance = memnew(CSharpInstance(Ref<CSharpScript>(p_script))); Reference *ref = Object::cast_to<Reference>(p_owner); @@ -1576,7 +1523,6 @@ CSharpInstance *CSharpInstance::create_for_managed_type(Object *p_owner, CSharpS } MonoObject *CSharpInstance::get_mono_object() const { - ERR_FAIL_COND_V(gchandle.is_released(), nullptr); return gchandle.get_target(); } @@ -1586,7 +1532,6 @@ Object *CSharpInstance::get_owner() { } bool CSharpInstance::set(const StringName &p_name, const Variant &p_value) { - ERR_FAIL_COND_V(!script.is_valid(), false); GD_MONO_SCOPE_THREAD_ATTACH; @@ -1640,7 +1585,6 @@ bool CSharpInstance::set(const StringName &p_name, const Variant &p_value) { } bool CSharpInstance::get(const StringName &p_name, Variant &r_ret) const { - ERR_FAIL_COND_V(!script.is_valid(), false); GD_MONO_SCOPE_THREAD_ATTACH; @@ -1704,7 +1648,6 @@ bool CSharpInstance::get(const StringName &p_name, Variant &r_ret) const { } void CSharpInstance::get_properties_state_for_reloading(List<Pair<StringName, Variant>> &r_state) { - List<PropertyInfo> pinfo; get_property_list(&pinfo); @@ -1729,7 +1672,6 @@ void CSharpInstance::get_properties_state_for_reloading(List<Pair<StringName, Va } void CSharpInstance::get_event_signals_state_for_reloading(List<Pair<StringName, Array>> &r_state) { - MonoObject *owner_managed = get_mono_object(); ERR_FAIL_NULL(owner_managed); @@ -1760,7 +1702,6 @@ void CSharpInstance::get_event_signals_state_for_reloading(List<Pair<StringName, } void CSharpInstance::get_property_list(List<PropertyInfo> *p_properties) const { - for (Map<StringName, PropertyInfo>::Element *E = script->member_info.front(); E; E = E->next()) { p_properties->push_back(E->value()); } @@ -1797,7 +1738,6 @@ void CSharpInstance::get_property_list(List<PropertyInfo> *p_properties) const { } Variant::Type CSharpInstance::get_property_type(const StringName &p_name, bool *r_is_valid) const { - if (script->member_info.has(p_name)) { if (r_is_valid) *r_is_valid = true; @@ -1811,7 +1751,6 @@ Variant::Type CSharpInstance::get_property_type(const StringName &p_name, bool * } bool CSharpInstance::has_method(const StringName &p_method) const { - if (!script.is_valid()) return false; @@ -1831,7 +1770,6 @@ bool CSharpInstance::has_method(const StringName &p_method) const { } Variant CSharpInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - ERR_FAIL_COND_V(!script.is_valid(), Variant()); GD_MONO_SCOPE_THREAD_ATTACH; @@ -1869,7 +1807,6 @@ Variant CSharpInstance::call(const StringName &p_method, const Variant **p_args, } void CSharpInstance::call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount) { - GD_MONO_SCOPE_THREAD_ATTACH; if (script.is_valid()) { @@ -1882,7 +1819,6 @@ void CSharpInstance::call_multilevel(const StringName &p_method, const Variant * } void CSharpInstance::_call_multilevel(MonoObject *p_mono_object, const StringName &p_method, const Variant **p_args, int p_argcount) { - GD_MONO_ASSERT_THREAD_ATTACHED; GDMonoClass *top = script->script_class; @@ -1900,14 +1836,12 @@ 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) { - // Sorry, the method is the one that controls the call order call_multilevel(p_method, p_args, p_argcount); } bool CSharpInstance::_reference_owner_unsafe() { - #ifdef DEBUG_ENABLED CRASH_COND(!base_ref); CRASH_COND(owner == nullptr); @@ -1929,7 +1863,6 @@ bool CSharpInstance::_reference_owner_unsafe() { } bool CSharpInstance::_unreference_owner_unsafe() { - #ifdef DEBUG_ENABLED CRASH_COND(!base_ref); CRASH_COND(owner == nullptr); @@ -1991,7 +1924,6 @@ MonoObject *CSharpInstance::_internal_new_managed() { } void CSharpInstance::mono_object_disposed(MonoObject *p_obj) { - disconnect_event_signals(); #ifdef DEBUG_ENABLED @@ -2002,7 +1934,6 @@ void CSharpInstance::mono_object_disposed(MonoObject *p_obj) { } void CSharpInstance::mono_object_disposed_baseref(MonoObject *p_obj, bool p_is_finalizer, bool &r_delete_owner, bool &r_remove_script_instance) { - #ifdef DEBUG_ENABLED CRASH_COND(!base_ref); CRASH_COND(gchandle.is_released()); @@ -2063,7 +1994,6 @@ void CSharpInstance::disconnect_event_signals() { } void CSharpInstance::refcount_incremented() { - #ifdef DEBUG_ENABLED CRASH_COND(!base_ref); CRASH_COND(owner == nullptr); @@ -2086,7 +2016,6 @@ void CSharpInstance::refcount_incremented() { } bool CSharpInstance::refcount_decremented() { - #ifdef DEBUG_ENABLED CRASH_COND(!base_ref); CRASH_COND(owner == nullptr); @@ -2156,7 +2085,6 @@ MultiplayerAPI::RPCMode CSharpInstance::get_rset_mode(const StringName &p_variab } void CSharpInstance::notification(int p_notification) { - GD_MONO_SCOPE_THREAD_ATTACH; if (p_notification == Object::NOTIFICATION_PREDELETE) { @@ -2195,7 +2123,6 @@ void CSharpInstance::notification(int p_notification) { } void CSharpInstance::_call_notification(int p_notification) { - GD_MONO_ASSERT_THREAD_ATTACHED; MonoObject *mono_object = get_mono_object(); @@ -2252,12 +2179,10 @@ String CSharpInstance::to_string(bool *r_valid) { } Ref<Script> CSharpInstance::get_script() const { - return script; } ScriptLanguage *CSharpInstance::get_language() { - return CSharpLanguage::get_singleton(); } @@ -2266,7 +2191,6 @@ CSharpInstance::CSharpInstance(const Ref<CSharpScript> &p_script) : } CSharpInstance::~CSharpInstance() { - GD_MONO_SCOPE_THREAD_ATTACH; destructing_script_instance = true; @@ -2348,14 +2272,12 @@ CSharpInstance::~CSharpInstance() { #ifdef TOOLS_ENABLED void CSharpScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) { - placeholders.erase(p_placeholder); } #endif #ifdef TOOLS_ENABLED void CSharpScript::_update_exports_values(Map<StringName, Variant> &values, List<PropertyInfo> &propnames) { - if (base_cache.is_valid()) { base_cache->_update_exports_values(values, propnames); } @@ -2370,7 +2292,6 @@ void CSharpScript::_update_exports_values(Map<StringName, Variant> &values, List } void CSharpScript::_update_member_info_no_exports() { - if (exports_invalidated) { GD_MONO_ASSERT_THREAD_ATTACHED; @@ -2419,60 +2340,69 @@ void CSharpScript::_update_member_info_no_exports() { #endif bool CSharpScript::_update_exports() { - #ifdef TOOLS_ENABLED - if (!Engine::get_singleton()->is_editor_hint()) - return false; - - placeholder_fallback_enabled = true; // until proven otherwise - + bool is_editor = Engine::get_singleton()->is_editor_hint(); + if (is_editor) + placeholder_fallback_enabled = true; // until proven otherwise +#endif if (!valid) return false; bool changed = false; - if (exports_invalidated) { +#ifdef TOOLS_ENABLED + if (exports_invalidated) +#endif + { GD_MONO_SCOPE_THREAD_ATTACH; - exports_invalidated = false; - changed = true; member_info.clear(); - exported_members_cache.clear(); - exported_members_defval_cache.clear(); - // Here we create a temporary managed instance of the class to get the initial values +#ifdef TOOLS_ENABLED + MonoObject *tmp_object = nullptr; + Object *tmp_native = nullptr; + uint32_t tmp_pinned_gchandle = 0; + + if (is_editor) { + exports_invalidated = false; - MonoObject *tmp_object = mono_object_new(mono_domain_get(), script_class->get_mono_ptr()); + exported_members_cache.clear(); + exported_members_defval_cache.clear(); - if (!tmp_object) { - ERR_PRINT("Failed to allocate temporary MonoObject."); - return false; - } + // Here we create a temporary managed instance of the class to get the initial values + tmp_object = mono_object_new(mono_domain_get(), script_class->get_mono_ptr()); - uint32_t tmp_pinned_gchandle = GDMonoUtils::new_strong_gchandle_pinned(tmp_object); // pin it (not sure if needed) + if (!tmp_object) { + ERR_PRINT("Failed to allocate temporary MonoObject."); + return false; + } - GDMonoMethod *ctor = script_class->get_method(CACHED_STRING_NAME(dotctor), 0); + tmp_pinned_gchandle = GDMonoUtils::new_strong_gchandle_pinned(tmp_object); // pin it (not sure if needed) - ERR_FAIL_NULL_V_MSG(ctor, false, - "Cannot construct temporary MonoObject because the class does not define a parameterless constructor: '" + get_path() + "'."); + GDMonoMethod *ctor = script_class->get_method(CACHED_STRING_NAME(dotctor), 0); - MonoException *ctor_exc = nullptr; - ctor->invoke(tmp_object, nullptr, &ctor_exc); + ERR_FAIL_NULL_V_MSG(ctor, false, + "Cannot construct temporary MonoObject because the class does not define a parameterless constructor: '" + get_path() + "'."); - Object *tmp_native = GDMonoMarshal::unbox<Object *>(CACHED_FIELD(GodotObject, ptr)->get_value(tmp_object)); + MonoException *ctor_exc = nullptr; + ctor->invoke(tmp_object, nullptr, &ctor_exc); - if (ctor_exc) { - // TODO: Should we free 'tmp_native' if the exception was thrown after its creation? + tmp_native = GDMonoMarshal::unbox<Object *>(CACHED_FIELD(GodotObject, ptr)->get_value(tmp_object)); - GDMonoUtils::free_gchandle(tmp_pinned_gchandle); - tmp_object = nullptr; + if (ctor_exc) { + // TODO: Should we free 'tmp_native' if the exception was thrown after its creation? - ERR_PRINT("Exception thrown from constructor of temporary MonoObject:"); - GDMonoUtils::debug_print_unhandled_exception(ctor_exc); - return false; + GDMonoUtils::free_gchandle(tmp_pinned_gchandle); + tmp_object = nullptr; + + ERR_PRINT("Exception thrown from constructor of temporary MonoObject:"); + GDMonoUtils::debug_print_unhandled_exception(ctor_exc); + return false; + } } +#endif GDMonoClass *top = script_class; @@ -2488,15 +2418,22 @@ bool CSharpScript::_update_exports() { if (_get_member_export(field, /* inspect export: */ true, prop_info, exported)) { StringName member_name = field->get_name(); + member_info[member_name] = prop_info; + if (exported) { - member_info[member_name] = prop_info; - exported_members_cache.push_front(prop_info); +#ifdef TOOLS_ENABLED + if (is_editor) { + exported_members_cache.push_front(prop_info); - if (tmp_object) { - exported_members_defval_cache[member_name] = GDMonoMarshal::mono_object_to_variant(field->get_value(tmp_object)); + if (tmp_object) { + exported_members_defval_cache[member_name] = GDMonoMarshal::mono_object_to_variant(field->get_value(tmp_object)); + } } - } else { - member_info[member_name] = prop_info; +#endif + +#if defined(TOOLS_ENABLED) || defined(DEBUG_ENABLED) + exported_members_names.insert(member_name); +#endif } } } @@ -2509,22 +2446,28 @@ bool CSharpScript::_update_exports() { if (_get_member_export(property, /* inspect export: */ true, prop_info, exported)) { StringName member_name = property->get_name(); + member_info[member_name] = prop_info; + if (exported) { - member_info[member_name] = prop_info; - exported_members_cache.push_front(prop_info); - - if (tmp_object) { - MonoException *exc = nullptr; - MonoObject *ret = property->get_value(tmp_object, &exc); - if (exc) { - exported_members_defval_cache[member_name] = Variant(); - GDMonoUtils::debug_print_unhandled_exception(exc); - } else { - exported_members_defval_cache[member_name] = GDMonoMarshal::mono_object_to_variant(ret); +#ifdef TOOLS_ENABLED + if (is_editor) { + exported_members_cache.push_front(prop_info); + if (tmp_object) { + MonoException *exc = nullptr; + MonoObject *ret = property->get_value(tmp_object, &exc); + if (exc) { + exported_members_defval_cache[member_name] = Variant(); + GDMonoUtils::debug_print_unhandled_exception(exc); + } else { + exported_members_defval_cache[member_name] = GDMonoMarshal::mono_object_to_variant(ret); + } } } - } else { - member_info[member_name] = prop_info; +#endif + +#if defined(TOOLS_ENABLED) || defined(DEBUG_ENABLED) + exported_members_names.insert(member_name); +#endif } } } @@ -2532,52 +2475,57 @@ bool CSharpScript::_update_exports() { top = top->get_parent_class(); } - // Need to check this here, before disposal - bool base_ref = Object::cast_to<Reference>(tmp_native) != nullptr; +#ifdef TOOLS_ENABLED + if (is_editor) { + // Need to check this here, before disposal + bool base_ref = Object::cast_to<Reference>(tmp_native) != nullptr; - // Dispose the temporary managed instance + // Dispose the temporary managed instance - MonoException *exc = nullptr; - GDMonoUtils::dispose(tmp_object, &exc); + MonoException *exc = nullptr; + GDMonoUtils::dispose(tmp_object, &exc); - if (exc) { - ERR_PRINT("Exception thrown from method Dispose() of temporary MonoObject:"); - GDMonoUtils::debug_print_unhandled_exception(exc); - } + if (exc) { + ERR_PRINT("Exception thrown from method Dispose() of temporary MonoObject:"); + GDMonoUtils::debug_print_unhandled_exception(exc); + } - GDMonoUtils::free_gchandle(tmp_pinned_gchandle); - tmp_object = nullptr; + GDMonoUtils::free_gchandle(tmp_pinned_gchandle); + tmp_object = nullptr; - if (tmp_native && !base_ref) { - Node *node = Object::cast_to<Node>(tmp_native); - if (node && node->is_inside_tree()) { - ERR_PRINT("Temporary instance was added to the scene tree."); - } else { - memdelete(tmp_native); + if (tmp_native && !base_ref) { + Node *node = Object::cast_to<Node>(tmp_native); + if (node && node->is_inside_tree()) { + ERR_PRINT("Temporary instance was added to the scene tree."); + } else { + memdelete(tmp_native); + } } } +#endif } - placeholder_fallback_enabled = false; +#ifdef TOOLS_ENABLED + if (is_editor) { + placeholder_fallback_enabled = false; - if (placeholders.size()) { - // Update placeholders if any - Map<StringName, Variant> values; - List<PropertyInfo> propnames; - _update_exports_values(values, propnames); + if (placeholders.size()) { + // Update placeholders if any + Map<StringName, Variant> values; + List<PropertyInfo> propnames; + _update_exports_values(values, propnames); - for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) { - E->get()->update(propnames, values); + for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) { + E->get()->update(propnames, values); + } } } +#endif return changed; -#endif - return false; } void CSharpScript::load_script_signals(GDMonoClass *p_class, GDMonoClass *p_native_class) { - // no need to load the script's signals more than once if (!signals_invalidated) { return; @@ -2679,13 +2627,11 @@ bool CSharpScript::_get_signal(GDMonoClass *p_class, GDMonoMethod *p_delegate_in return true; } -#ifdef TOOLS_ENABLED /** * Returns false if there was an error, otherwise true. * If there was an error, r_prop_info and r_exported are not assigned any value. */ bool CSharpScript::_get_member_export(IMonoClassMember *p_member, bool p_inspect_export, PropertyInfo &r_prop_info, bool &r_exported) { - GD_MONO_ASSERT_THREAD_ATTACHED; // Goddammit, C++. All I wanted was some nested functions. @@ -2693,8 +2639,10 @@ bool CSharpScript::_get_member_export(IMonoClassMember *p_member, bool p_inspect (m_member->get_enclosing_class()->get_full_name() + "." + (String)m_member->get_name()) if (p_member->is_static()) { +#ifdef TOOLS_ENABLED if (p_member->has_attribute(CACHED_CLASS(ExportAttribute))) ERR_PRINT("Cannot export member because it is static: '" + MEMBER_FULL_QUALIFIED_NAME(p_member) + "'."); +#endif return false; } @@ -2716,13 +2664,17 @@ bool CSharpScript::_get_member_export(IMonoClassMember *p_member, bool p_inspect if (p_member->get_member_type() == IMonoClassMember::MEMBER_TYPE_PROPERTY) { GDMonoProperty *property = static_cast<GDMonoProperty *>(p_member); if (!property->has_getter()) { +#ifdef TOOLS_ENABLED if (exported) ERR_PRINT("Read-only property cannot be exported: '" + MEMBER_FULL_QUALIFIED_NAME(p_member) + "'."); +#endif return false; } if (!property->has_setter()) { +#ifdef TOOLS_ENABLED if (exported) ERR_PRINT("Write-only property (without getter) cannot be exported: '" + MEMBER_FULL_QUALIFIED_NAME(p_member) + "'."); +#endif return false; } } @@ -2736,16 +2688,21 @@ bool CSharpScript::_get_member_export(IMonoClassMember *p_member, bool p_inspect return true; } +#ifdef TOOLS_ENABLED MonoObject *attr = p_member->get_attribute(CACHED_CLASS(ExportAttribute)); +#endif PropertyHint hint = PROPERTY_HINT_NONE; String hint_string; if (variant_type == Variant::NIL && !nil_is_variant) { +#ifdef TOOLS_ENABLED ERR_PRINT("Unknown exported member type: '" + MEMBER_FULL_QUALIFIED_NAME(p_member) + "'."); +#endif return false; } +#ifdef TOOLS_ENABLED int hint_res = _try_get_member_export_hint(p_member, type, variant_type, /* allow_generics: */ true, hint, hint_string); ERR_FAIL_COND_V_MSG(hint_res == -1, false, @@ -2756,6 +2713,7 @@ bool CSharpScript::_get_member_export(IMonoClassMember *p_member, bool p_inspect hint = PropertyHint(CACHED_FIELD(ExportAttribute, hint)->get_int_value(attr)); hint_string = CACHED_FIELD(ExportAttribute, hintString)->get_string_value(attr); } +#endif uint32_t prop_usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE; @@ -2772,8 +2730,8 @@ bool CSharpScript::_get_member_export(IMonoClassMember *p_member, bool p_inspect #undef MEMBER_FULL_QUALIFIED_NAME } +#ifdef TOOLS_ENABLED int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, ManagedType p_type, Variant::Type p_variant_type, bool p_allow_generics, PropertyHint &r_hint, String &r_hint_string) { - if (p_variant_type == Variant::NIL) { // System.Object (Variant) return 1; @@ -2873,7 +2831,6 @@ int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, Manage #endif void CSharpScript::_clear() { - tool = false; valid = false; @@ -2883,7 +2840,6 @@ void CSharpScript::_clear() { } Variant CSharpScript::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - if (unlikely(GDMono::get_singleton() == nullptr)) { // Probably not the best error but eh. r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL; @@ -2915,7 +2871,6 @@ Variant CSharpScript::call(const StringName &p_method, const Variant **p_args, i } void CSharpScript::_resource_path_changed() { - String path = get_path(); if (!path.empty()) { @@ -2924,9 +2879,7 @@ void CSharpScript::_resource_path_changed() { } bool CSharpScript::_get(const StringName &p_name, Variant &r_ret) const { - if (p_name == CSharpLanguage::singleton->string_names._script_source) { - r_ret = get_source_code(); return true; } @@ -2935,9 +2888,7 @@ bool CSharpScript::_get(const StringName &p_name, Variant &r_ret) const { } bool CSharpScript::_set(const StringName &p_name, const Variant &p_value) { - if (p_name == CSharpLanguage::singleton->string_names._script_source) { - set_source_code(p_value); reload(); return true; @@ -2947,17 +2898,14 @@ 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 | PROPERTY_USAGE_INTERNAL)); } void CSharpScript::_bind_methods() { - ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "new", &CSharpScript::_new, MethodInfo("new")); } Ref<CSharpScript> CSharpScript::create_for_managed_type(GDMonoClass *p_class, GDMonoClass *p_native) { - // This method should not fail, only assertions allowed CRASH_COND(p_class == nullptr); @@ -2971,7 +2919,6 @@ Ref<CSharpScript> CSharpScript::create_for_managed_type(GDMonoClass *p_class, GD } void CSharpScript::initialize_for_managed_type(Ref<CSharpScript> p_script, GDMonoClass *p_class, GDMonoClass *p_native) { - // This method should not fail, only assertions allowed CRASH_COND(p_class == nullptr); @@ -3035,7 +2982,6 @@ void CSharpScript::initialize_for_managed_type(Ref<CSharpScript> p_script, GDMon } bool CSharpScript::can_instance() const { - #ifdef TOOLS_ENABLED bool extra_cond = tool || ScriptServer::is_scripting_enabled(); #else @@ -3059,7 +3005,6 @@ bool CSharpScript::can_instance() const { } StringName CSharpScript::get_instance_base_type() const { - if (native) return native->get_name(); else @@ -3067,7 +3012,6 @@ StringName CSharpScript::get_instance_base_type() const { } CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Callable::CallError &r_error) { - GD_MONO_ASSERT_THREAD_ATTACHED; /* STEP 1, CREATE */ @@ -3157,7 +3101,6 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg } Variant CSharpScript::_new(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - if (!valid) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; return Variant(); @@ -3193,7 +3136,6 @@ Variant CSharpScript::_new(const Variant **p_args, int p_argcount, Callable::Cal } ScriptInstance *CSharpScript::instance_create(Object *p_this) { - #ifdef DEBUG_ENABLED CRASH_COND(!valid); #endif @@ -3218,7 +3160,6 @@ ScriptInstance *CSharpScript::instance_create(Object *p_this) { } PlaceHolderScriptInstance *CSharpScript::placeholder_instance_create(Object *p_this) { - #ifdef TOOLS_ENABLED PlaceHolderScriptInstance *si = memnew(PlaceHolderScriptInstance(CSharpLanguage::get_singleton(), Ref<Script>(this), p_this)); placeholders.insert(si); @@ -3230,23 +3171,19 @@ PlaceHolderScriptInstance *CSharpScript::placeholder_instance_create(Object *p_t } bool CSharpScript::instance_has(const Object *p_this) const { - MutexLock lock(CSharpLanguage::get_singleton()->script_instances_mutex); return instances.has((Object *)p_this); } bool CSharpScript::has_source_code() const { - return !source.empty(); } String CSharpScript::get_source_code() const { - return source; } void CSharpScript::set_source_code(const String &p_code) { - if (source == p_code) return; source = p_code; @@ -3256,7 +3193,6 @@ void CSharpScript::set_source_code(const String &p_code) { } void CSharpScript::get_script_method_list(List<MethodInfo> *p_list) const { - if (!script_class) return; @@ -3270,7 +3206,6 @@ void CSharpScript::get_script_method_list(List<MethodInfo> *p_list) const { } bool CSharpScript::has_method(const StringName &p_method) const { - if (!script_class) return false; @@ -3280,7 +3215,6 @@ bool CSharpScript::has_method(const StringName &p_method) const { } MethodInfo CSharpScript::get_method_info(const StringName &p_method) const { - if (!script_class) return MethodInfo(); @@ -3301,7 +3235,6 @@ MethodInfo CSharpScript::get_method_info(const StringName &p_method) const { } Error CSharpScript::reload(bool p_keep_state) { - bool has_instances; { MutexLock lock(CSharpLanguage::get_singleton()->script_instances_mutex); @@ -3323,9 +3256,7 @@ Error CSharpScript::reload(bool p_keep_state) { ERR_FAIL_NULL_V(namespace_, ERR_BUG); ERR_FAIL_NULL_V(class_name, ERR_BUG); GDMonoClass *klass = project_assembly->get_class(namespace_->operator String(), class_name->operator String()); - if (klass) { - bool obj_type = CACHED_CLASS(GodotObject)->is_assignable_from(klass); - ERR_FAIL_COND_V(!obj_type, ERR_BUG); + if (klass && CACHED_CLASS(GodotObject)->is_assignable_from(klass)) { script_class = klass; } } else { @@ -3463,12 +3394,10 @@ Error CSharpScript::reload(bool p_keep_state) { } ScriptLanguage *CSharpScript::get_language() const { - return CSharpLanguage::get_singleton(); } bool CSharpScript::get_property_default_value(const StringName &p_property, Variant &r_value) const { - #ifdef TOOLS_ENABLED const Map<StringName, Variant>::Element *E = exported_members_defval_cache.find(p_property); @@ -3486,7 +3415,6 @@ bool CSharpScript::get_property_default_value(const StringName &p_property, Vari } void CSharpScript::update_exports() { - #ifdef TOOLS_ENABLED _update_exports(); #endif @@ -3497,7 +3425,6 @@ bool CSharpScript::has_script_signal(const StringName &p_signal) const { } void CSharpScript::get_script_signal_list(List<MethodInfo> *r_signals) const { - for (const Map<StringName, Vector<SignalParameter>>::Element *E = _signals.front(); E; E = E->next()) { MethodInfo mi; mi.name = E->key(); @@ -3536,27 +3463,40 @@ void CSharpScript::get_script_signal_list(List<MethodInfo> *r_signals) const { } } -Ref<Script> CSharpScript::get_base_script() const { +bool CSharpScript::inherits_script(const Ref<Script> &p_script) const { + Ref<CSharpScript> cs = p_script; + if (cs.is_null()) { + return false; + } + + if (script_class == nullptr || cs->script_class == nullptr) { + return false; + } + if (script_class == cs->script_class) { + return true; + } + + return cs->script_class->is_assignable_from(script_class); +} + +Ref<Script> CSharpScript::get_base_script() const { // TODO search in metadata file once we have it, not important any way? return Ref<Script>(); } void CSharpScript::get_script_property_list(List<PropertyInfo> *p_list) const { - for (Map<StringName, PropertyInfo>::Element *E = member_info.front(); E; E = E->next()) { p_list->push_back(E->value()); } } int CSharpScript::get_member_line(const StringName &p_member) const { - // TODO omnisharp return -1; } MultiplayerAPI::RPCMode CSharpScript::_member_get_rpc_mode(IMonoClassMember *p_member) const { - if (p_member->has_attribute(CACHED_CLASS(RemoteAttribute))) return MultiplayerAPI::RPC_MODE_REMOTE; if (p_member->has_attribute(CACHED_CLASS(MasterAttribute))) @@ -3628,7 +3568,6 @@ MultiplayerAPI::RPCMode CSharpScript::get_rset_mode(const StringName &p_variable } Error CSharpScript::load_source_code(const String &p_path) { - Error ferr = read_all_file_utf8(p_path, source); ERR_FAIL_COND_V_MSG(ferr != OK, ferr, @@ -3645,12 +3584,10 @@ Error CSharpScript::load_source_code(const String &p_path) { } StringName CSharpScript::get_script_name() const { - return name; } CSharpScript::CSharpScript() { - _clear(); _resource_path_changed(); @@ -3664,17 +3601,25 @@ CSharpScript::CSharpScript() { } CSharpScript::~CSharpScript() { - #ifdef DEBUG_ENABLED MutexLock lock(CSharpLanguage::get_singleton()->script_instances_mutex); CSharpLanguage::get_singleton()->script_list.remove(&this->script_list); #endif } -/*************** RESOURCE ***************/ +void CSharpScript::get_members(Set<StringName> *p_members) { +#if defined(TOOLS_ENABLED) || defined(DEBUG_ENABLED) + if (p_members) { + for (Set<StringName>::Element *E = exported_members_names.front(); E; E = E->next()) { + p_members->insert(E->get()); + } + } +#endif +} -RES ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) { +/*************** RESOURCE ***************/ +RES ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { if (r_error) *r_error = ERR_FILE_CANT_OPEN; @@ -3700,22 +3645,18 @@ RES ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p } void ResourceFormatLoaderCSharpScript::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("cs"); } bool ResourceFormatLoaderCSharpScript::handles_type(const String &p_type) const { - return p_type == "Script" || p_type == CSharpLanguage::get_singleton()->get_type(); } String ResourceFormatLoaderCSharpScript::get_resource_type(const String &p_path) const { - return p_path.get_extension().to_lower() == "cs" ? CSharpLanguage::get_singleton()->get_type() : ""; } Error ResourceFormatSaverCSharpScript::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { - Ref<CSharpScript> sqscr = p_resource; ERR_FAIL_COND_V(sqscr.is_null(), ERR_INVALID_PARAMETER); @@ -3759,19 +3700,16 @@ Error ResourceFormatSaverCSharpScript::save(const String &p_path, const RES &p_r } void ResourceFormatSaverCSharpScript::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const { - if (Object::cast_to<CSharpScript>(p_resource.ptr())) { p_extensions->push_back("cs"); } } bool ResourceFormatSaverCSharpScript::recognize(const RES &p_resource) const { - return Object::cast_to<CSharpScript>(p_resource.ptr()) != nullptr; } CSharpLanguage::StringNameCache::StringNameCache() { - _signal_callback = StaticCString::create("_signal_callback"); _set = StaticCString::create("_set"); _get = StaticCString::create("_get"); |