diff options
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/gdscript/editor/gdscript_highlighter.cpp | 44 | ||||
| -rw-r--r-- | modules/gdscript/gdscript_editor.cpp | 30 | ||||
| -rw-r--r-- | modules/gdscript/gdscript_parser.cpp | 2 | ||||
| -rw-r--r-- | modules/gdscript/gdscript_tokenizer.cpp | 2 | ||||
| -rw-r--r-- | modules/gdscript/language_server/gdscript_text_document.cpp | 4 | ||||
| -rw-r--r-- | modules/gdscript/tests/test_gdscript.cpp | 2 | ||||
| -rw-r--r-- | modules/mobile_vr/mobile_vr_interface.h | 8 | ||||
| -rw-r--r-- | modules/mono/csharp_script.cpp | 195 | ||||
| -rw-r--r-- | modules/mono/csharp_script.h | 17 | ||||
| -rw-r--r-- | modules/mono/glue/base_object_glue.cpp | 10 | ||||
| -rw-r--r-- | modules/mono/mono_gd/gd_mono_internals.cpp | 7 | ||||
| -rw-r--r-- | modules/mono/mono_gd/gd_mono_utils.cpp | 19 |
12 files changed, 168 insertions, 172 deletions
diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index ed8b0a4690..3441233811 100644 --- a/modules/gdscript/editor/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -449,13 +449,13 @@ void GDScriptSyntaxHighlighter::_update_cache() { color_region_cache.clear(); font_color = text_edit->get_theme_color(SNAME("font_color")); - symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color"); - function_color = EDITOR_GET("text_editor/highlighting/function_color"); - number_color = EDITOR_GET("text_editor/highlighting/number_color"); - member_color = EDITOR_GET("text_editor/highlighting/member_variable_color"); + symbol_color = EDITOR_GET("text_editor/theme/highlighting/symbol_color"); + function_color = EDITOR_GET("text_editor/theme/highlighting/function_color"); + number_color = EDITOR_GET("text_editor/theme/highlighting/number_color"); + member_color = EDITOR_GET("text_editor/theme/highlighting/member_variable_color"); /* Engine types. */ - const Color types_color = EDITOR_GET("text_editor/highlighting/engine_type_color"); + const Color types_color = EDITOR_GET("text_editor/theme/highlighting/engine_type_color"); List<StringName> types; ClassDB::get_class_list(&types); for (const StringName &E : types) { @@ -467,7 +467,7 @@ void GDScriptSyntaxHighlighter::_update_cache() { } /* User types. */ - const Color usertype_color = EDITOR_GET("text_editor/highlighting/user_type_color"); + const Color usertype_color = EDITOR_GET("text_editor/theme/highlighting/user_type_color"); List<StringName> global_classes; ScriptServer::get_global_class_list(&global_classes); for (const StringName &E : global_classes) { @@ -486,7 +486,7 @@ void GDScriptSyntaxHighlighter::_update_cache() { const GDScriptLanguage *gdscript = GDScriptLanguage::get_singleton(); /* Core types. */ - const Color basetype_color = EDITOR_GET("text_editor/highlighting/base_type_color"); + const Color basetype_color = EDITOR_GET("text_editor/theme/highlighting/base_type_color"); List<String> core_types; gdscript->get_core_type_words(&core_types); for (const String &E : core_types) { @@ -494,8 +494,8 @@ void GDScriptSyntaxHighlighter::_update_cache() { } /* Reserved words. */ - const Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color"); - const Color control_flow_keyword_color = EDITOR_GET("text_editor/highlighting/control_flow_keyword_color"); + const Color keyword_color = EDITOR_GET("text_editor/theme/highlighting/keyword_color"); + const Color control_flow_keyword_color = EDITOR_GET("text_editor/theme/highlighting/control_flow_keyword_color"); List<String> keyword_list; gdscript->get_reserved_words(&keyword_list); for (const String &E : keyword_list) { @@ -507,7 +507,7 @@ void GDScriptSyntaxHighlighter::_update_cache() { } /* Comments */ - const Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color"); + const Color comment_color = EDITOR_GET("text_editor/theme/highlighting/comment_color"); List<String> comments; gdscript->get_comment_delimiters(&comments); for (const String &comment : comments) { @@ -517,7 +517,7 @@ void GDScriptSyntaxHighlighter::_update_cache() { } /* Strings */ - const Color string_color = EDITOR_GET("text_editor/highlighting/string_color"); + const Color string_color = EDITOR_GET("text_editor/theme/highlighting/string_color"); List<String> strings; gdscript->get_string_delimiters(&strings); for (const String &string : strings) { @@ -529,7 +529,7 @@ void GDScriptSyntaxHighlighter::_update_cache() { const Ref<Script> script = _get_edited_resource(); if (script.is_valid()) { /* Member types. */ - const Color member_variable_color = EDITOR_GET("text_editor/highlighting/member_variable_color"); + const Color member_variable_color = EDITOR_GET("text_editor/theme/highlighting/member_variable_color"); StringName instance_base = script->get_instance_base_type(); if (instance_base != StringName()) { List<PropertyInfo> plist; @@ -566,28 +566,28 @@ void GDScriptSyntaxHighlighter::_update_cache() { annotation_color = Color(0.8, 0.5, 0.25); } - EDITOR_DEF("text_editor/highlighting/gdscript/function_definition_color", function_definition_color); - EDITOR_DEF("text_editor/highlighting/gdscript/node_path_color", node_path_color); - EDITOR_DEF("text_editor/highlighting/gdscript/annotation_color", annotation_color); + EDITOR_DEF("text_editor/theme/highlighting/gdscript/function_definition_color", function_definition_color); + EDITOR_DEF("text_editor/theme/highlighting/gdscript/node_path_color", node_path_color); + EDITOR_DEF("text_editor/theme/highlighting/gdscript/annotation_color", annotation_color); if (text_edit_color_theme == "Default" || godot_2_theme) { EditorSettings::get_singleton()->set_initial_value( - "text_editor/highlighting/gdscript/function_definition_color", + "text_editor/theme/highlighting/gdscript/function_definition_color", function_definition_color, true); EditorSettings::get_singleton()->set_initial_value( - "text_editor/highlighting/gdscript/node_path_color", + "text_editor/theme/highlighting/gdscript/node_path_color", node_path_color, true); EditorSettings::get_singleton()->set_initial_value( - "text_editor/highlighting/gdscript/annotation_color", + "text_editor/theme/highlighting/gdscript/annotation_color", annotation_color, true); } - function_definition_color = EDITOR_GET("text_editor/highlighting/gdscript/function_definition_color"); - node_path_color = EDITOR_GET("text_editor/highlighting/gdscript/node_path_color"); - annotation_color = EDITOR_GET("text_editor/highlighting/gdscript/annotation_color"); - type_color = EDITOR_GET("text_editor/highlighting/base_type_color"); + function_definition_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/function_definition_color"); + node_path_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/node_path_color"); + annotation_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/annotation_color"); + type_color = EDITOR_GET("text_editor/theme/highlighting/base_type_color"); } void GDScriptSyntaxHighlighter::add_color_region(const String &p_start_key, const String &p_end_key, const Color &p_color, bool p_line_only) { diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 2e570d5a5b..73661855b4 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -623,11 +623,11 @@ static String _make_arguments_hint(const GDScriptParser::FunctionNode *p_functio } static void _get_directory_contents(EditorFileSystemDirectory *p_dir, Map<String, ScriptCodeCompletionOption> &r_list) { - const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\""; + const String quote_style = EDITOR_GET("text_editor/completion/use_single_quotes") ? "'" : "\""; for (int i = 0; i < p_dir->get_file_count(); i++) { ScriptCodeCompletionOption option(p_dir->get_file_path(i), ScriptCodeCompletionOption::KIND_FILE_PATH); - option.insert_text = quote_style + option.display + quote_style; + option.insert_text = option.display.quote(quote_style); r_list.insert(option.display, option); } @@ -641,20 +641,20 @@ static void _find_annotation_arguments(const GDScriptParser::AnnotationNode *p_a if (p_argument == 3 || p_argument == 4) { // Slider hint. ScriptCodeCompletionOption slider1("or_greater", ScriptCodeCompletionOption::KIND_PLAIN_TEXT); - slider1.insert_text = p_quote_style + slider1.display + p_quote_style; + slider1.insert_text = slider1.display.quote(p_quote_style); r_result.insert(slider1.display, slider1); ScriptCodeCompletionOption slider2("or_lesser", ScriptCodeCompletionOption::KIND_PLAIN_TEXT); - slider2.insert_text = p_quote_style + slider2.display + p_quote_style; + slider2.insert_text = slider2.display.quote(p_quote_style); r_result.insert(slider2.display, slider2); } } else if (p_annotation->name == "@export_exp_easing") { if (p_argument == 0 || p_argument == 1) { // Easing hint. ScriptCodeCompletionOption hint1("attenuation", ScriptCodeCompletionOption::KIND_PLAIN_TEXT); - hint1.insert_text = p_quote_style + hint1.display + p_quote_style; + hint1.insert_text = hint1.display.quote(p_quote_style); r_result.insert(hint1.display, hint1); ScriptCodeCompletionOption hint2("inout", ScriptCodeCompletionOption::KIND_PLAIN_TEXT); - hint2.insert_text = p_quote_style + hint2.display + p_quote_style; + hint2.insert_text = hint2.display.quote(p_quote_style); r_result.insert(hint2.display, hint2); } } else if (p_annotation->name == "@export_node_path") { @@ -2192,7 +2192,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c Variant base = p_base.value; GDScriptParser::DataType base_type = p_base.type; - const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\""; + const String quote_style = EDITOR_GET("text_editor/completion/use_single_quotes") ? "'" : "\""; while (base_type.is_set() && !base_type.is_variant()) { switch (base_type.kind) { @@ -2254,7 +2254,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c } String name = s.get_slice("/", 1); ScriptCodeCompletionOption option("/root/" + name, ScriptCodeCompletionOption::KIND_NODE_PATH); - option.insert_text = quote_style + option.display + quote_style; + option.insert_text = option.display.quote(quote_style); r_result.insert(option.display, option); } } @@ -2270,7 +2270,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c } String name = s.get_slice("/", 1); ScriptCodeCompletionOption option(name, ScriptCodeCompletionOption::KIND_CONSTANT); - option.insert_text = quote_style + option.display + quote_style; + option.insert_text = option.display.quote(quote_style); r_result.insert(option.display, option); } } @@ -2305,8 +2305,6 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c } static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, const GDScriptParser::Node *p_call, int p_argidx, Map<String, ScriptCodeCompletionOption> &r_result, bool &r_forced, String &r_arghint) { - const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\""; - if (p_call->type == GDScriptParser::Node::PRELOAD) { if (p_argidx == 0 && bool(EditorSettings::get_singleton()->get("text_editor/completion/complete_file_paths"))) { _get_directory_contents(EditorFileSystem::get_singleton()->get_filesystem(), r_result); @@ -2382,7 +2380,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c } ::Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path, Object *p_owner, List<ScriptCodeCompletionOption> *r_options, bool &r_forced, String &r_call_hint) { - const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\""; + const String quote_style = EDITOR_GET("text_editor/completion/use_single_quotes") ? "'" : "\""; GDScriptParser parser; GDScriptAnalyzer analyzer(&parser); @@ -2671,8 +2669,8 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c Map<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); for (Map<StringName, ProjectSettings::AutoloadInfo>::Element *E = autoloads.front(); E; E = E->next()) { - String name = E->key(); - ScriptCodeCompletionOption option(quote_style + "/root/" + name + quote_style, ScriptCodeCompletionOption::KIND_NODE_PATH); + String path = "/root/" + E->key(); + ScriptCodeCompletionOption option(path.quote(quote_style), ScriptCodeCompletionOption::KIND_NODE_PATH); options.insert(option.display, option); } } @@ -2705,10 +2703,10 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path String GDScriptLanguage::_get_indentation() const { #ifdef TOOLS_ENABLED if (Engine::get_singleton()->is_editor_hint()) { - bool use_space_indentation = EDITOR_DEF("text_editor/indent/type", false); + bool use_space_indentation = EDITOR_DEF("text_editor/behavior/indent/type", false); if (use_space_indentation) { - int indent_size = EDITOR_DEF("text_editor/indent/size", 4); + int indent_size = EDITOR_DEF("text_editor/behavior/indent/size", 4); String space_indent = ""; for (int i = 0; i < indent_size; i++) { diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index a21167ad95..8c3bb1ea57 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -337,7 +337,7 @@ Error GDScriptParser::parse(const String &p_source_code, const String &p_script_ int tab_size = 4; #ifdef TOOLS_ENABLED if (EditorSettings::get_singleton()) { - tab_size = EditorSettings::get_singleton()->get_setting("text_editor/indent/size"); + tab_size = EditorSettings::get_singleton()->get_setting("text_editor/behavior/indent/size"); } #endif // TOOLS_ENABLED diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index 3f14156dfa..d4a098811a 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -1440,7 +1440,7 @@ GDScriptTokenizer::Token GDScriptTokenizer::scan() { GDScriptTokenizer::GDScriptTokenizer() { #ifdef TOOLS_ENABLED if (EditorSettings::get_singleton()) { - tab_size = EditorSettings::get_singleton()->get_setting("text_editor/indent/size"); + tab_size = EditorSettings::get_singleton()->get_setting("text_editor/behavior/indent/size"); } #endif // TOOLS_ENABLED } diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp index 9574c765bc..03b1e3fa44 100644 --- a/modules/gdscript/language_server/gdscript_text_document.cpp +++ b/modules/gdscript/language_server/gdscript_text_document.cpp @@ -291,8 +291,8 @@ Dictionary GDScriptTextDocument::resolve(const Dictionary &p_params) { } } else if (item.kind == lsp::CompletionItemKind::Event) { if (params.context.triggerKind == lsp::CompletionTriggerKind::TriggerCharacter && (params.context.triggerCharacter == "(")) { - const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\""; - item.insertText = quote_style + item.label + quote_style; + const String quote_style = EDITOR_GET("text_editor/completion/use_single_quotes") ? "'" : "\""; + item.insertText = item.label.quote(quote_style); } } diff --git a/modules/gdscript/tests/test_gdscript.cpp b/modules/gdscript/tests/test_gdscript.cpp index 52e9d92223..e54f055f2b 100644 --- a/modules/gdscript/tests/test_gdscript.cpp +++ b/modules/gdscript/tests/test_gdscript.cpp @@ -56,7 +56,7 @@ static void test_tokenizer(const String &p_code, const Vector<String> &p_lines) int tab_size = 4; #ifdef TOOLS_ENABLED if (EditorSettings::get_singleton()) { - tab_size = EditorSettings::get_singleton()->get_setting("text_editor/indent/size"); + tab_size = EditorSettings::get_singleton()->get_setting("text_editor/behavior/indent/size"); } #endif // TOOLS_ENABLED String tab = String(" ").repeat(tab_size); diff --git a/modules/mobile_vr/mobile_vr_interface.h b/modules/mobile_vr/mobile_vr_interface.h index 29ce0f92c8..0c05dc1ebb 100644 --- a/modules/mobile_vr/mobile_vr_interface.h +++ b/modules/mobile_vr/mobile_vr_interface.h @@ -86,20 +86,20 @@ private: Vector3 mag_next_max; ///@TODO a few support functions for trackers, most are math related and should likely be moved elsewhere - float floor_decimals(float p_value, float p_decimals) { + float floor_decimals(const float p_value, const float p_decimals) { float power_of_10 = pow(10.0f, p_decimals); return floor(p_value * power_of_10) / power_of_10; }; - Vector3 floor_decimals(const Vector3 &p_vector, float p_decimals) { + Vector3 floor_decimals(const Vector3 &p_vector, const float p_decimals) { return Vector3(floor_decimals(p_vector.x, p_decimals), floor_decimals(p_vector.y, p_decimals), floor_decimals(p_vector.z, p_decimals)); }; - Vector3 low_pass(const Vector3 &p_vector, const Vector3 &p_last_vector, float p_factor) { + Vector3 low_pass(const Vector3 &p_vector, const Vector3 &p_last_vector, const float p_factor) { return p_vector + (p_factor * (p_last_vector - p_vector)); }; - Vector3 scrub(const Vector3 &p_vector, const Vector3 &p_last_vector, float p_decimals, float p_factor) { + Vector3 scrub(const Vector3 &p_vector, const Vector3 &p_last_vector, const float p_decimals, const float p_factor) { return low_pass(floor_decimals(p_vector, p_decimals), p_last_vector, p_factor); }; diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 520262c0eb..1f7f1390ea 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -82,6 +82,12 @@ static bool _create_project_solution_if_needed() { CSharpLanguage *CSharpLanguage::singleton = nullptr; +GDNativeInstanceBindingCallbacks CSharpLanguage::_instance_binding_callbacks = { + &_instance_binding_create_callback, + &_instance_binding_free_callback, + &_instance_binding_reference_callback +}; + String CSharpLanguage::get_name() const { return "C#"; } @@ -542,10 +548,10 @@ String CSharpLanguage::make_function(const String &, const String &, const Packe String CSharpLanguage::_get_indentation() const { #ifdef TOOLS_ENABLED if (Engine::get_singleton()->is_editor_hint()) { - bool use_space_indentation = EDITOR_DEF("text_editor/indent/type", 0); + bool use_space_indentation = EDITOR_DEF("text_editor/behavior/indent/type", 0); if (use_space_indentation) { - int indent_size = EDITOR_DEF("text_editor/indent/size", 4); + int indent_size = EDITOR_DEF("text_editor/behavior/indent/size", 4); String space_indent = ""; for (int i = 0; i < indent_size; i++) { @@ -1444,46 +1450,46 @@ bool CSharpLanguage::setup_csharp_script_binding(CSharpScriptBinding &r_script_b return true; } -void *CSharpLanguage::alloc_instance_binding_data(Object *p_object) { - MutexLock lock(language_bind_mutex); +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::_instance_binding_create_callback(void *, void *p_instance) { + CSharpLanguage *csharp_lang = CSharpLanguage::get_singleton(); - Map<Object *, CSharpScriptBinding>::Element *match = script_bindings.find(p_object); + MutexLock lock(csharp_lang->language_bind_mutex); + + Map<Object *, CSharpScriptBinding>::Element *match = csharp_lang->script_bindings.find((Object *)p_instance); if (match) { return (void *)match; } CSharpScriptBinding script_binding; - if (!setup_csharp_script_binding(script_binding, p_object)) { - return nullptr; - } - - return (void *)insert_script_binding(p_object, script_binding); + return (void *)csharp_lang->insert_script_binding((Object *)p_instance, script_binding); } -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::_instance_binding_free_callback(void *, void *, void *p_binding) { + CSharpLanguage *csharp_lang = CSharpLanguage::get_singleton(); -void CSharpLanguage::free_instance_binding_data(void *p_data) { if (GDMono::get_singleton() == nullptr) { #ifdef DEBUG_ENABLED - CRASH_COND(!script_bindings.is_empty()); + CRASH_COND(!csharp_lang->script_bindings.is_empty()); #endif // Mono runtime finalized, all the gchandle bindings were already released return; } - if (finalizing) { + if (csharp_lang->finalizing) { return; // inside CSharpLanguage::finish(), all the gchandle bindings are released there } GD_MONO_ASSERT_THREAD_ATTACHED; { - MutexLock lock(language_bind_mutex); + MutexLock lock(csharp_lang->language_bind_mutex); - Map<Object *, CSharpScriptBinding>::Element *data = (Map<Object *, CSharpScriptBinding>::Element *)p_data; + Map<Object *, CSharpScriptBinding>::Element *data = (Map<Object *, CSharpScriptBinding>::Element *)p_binding; CSharpScriptBinding &script_binding = data->value(); @@ -1497,92 +1503,110 @@ void CSharpLanguage::free_instance_binding_data(void *p_data) { script_binding.gchandle.release(); } - script_bindings.erase(data); + csharp_lang->script_bindings.erase(data); } } -void CSharpLanguage::refcount_incremented_instance_binding(Object *p_object) { -#if 0 - RefCounted *rc_owner = Object::cast_to<RefCounted>(p_object); +GDNativeBool CSharpLanguage::_instance_binding_reference_callback(void *p_token, void *p_binding, GDNativeBool p_reference) { + CRASH_COND(!p_binding); + + CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)p_binding)->get(); + + RefCounted *rc_owner = Object::cast_to<RefCounted>(script_binding.owner); #ifdef DEBUG_ENABLED CRASH_COND(!rc_owner); - CRASH_COND(!p_object->has_script_instance_binding(get_language_index())); #endif - void *data = p_object->get_script_instance_binding(get_language_index()); - CRASH_COND(!data); - - CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get(); MonoGCHandleData &gchandle = script_binding.gchandle; + int refcount = rc_owner->reference_get_count(); + if (!script_binding.inited) { - return; + return refcount == 0; } - if (rc_owner->reference_get_count() > 1 && gchandle.is_weak()) { // The managed side also holds a reference, hence 1 instead of 0 - GD_MONO_SCOPE_THREAD_ATTACH; + if (p_reference) { + // Refcount incremented + if (refcount > 1 && gchandle.is_weak()) { // The managed side also holds a reference, hence 1 instead of 0 + GD_MONO_SCOPE_THREAD_ATTACH; - // The reference count was increased after the managed side was the only one referencing our owner. - // This means the owner is being referenced again by the unmanaged side, - // so the owner must hold the managed side alive again to avoid it from being GCed. + // The reference count was increased after the managed side was the only one referencing our owner. + // This means the owner is being referenced again by the unmanaged side, + // so the owner must hold the managed side alive again to avoid it from being GCed. + + MonoObject *target = gchandle.get_target(); + if (!target) { + return false; // Called after the managed side was collected, so nothing to do here + } - MonoObject *target = gchandle.get_target(); - if (!target) { - return; // Called after the managed side was collected, so nothing to do here + // Release the current weak handle and replace it with a strong handle. + MonoGCHandleData strong_gchandle = MonoGCHandleData::new_strong_handle(target); + gchandle.release(); + gchandle = strong_gchandle; } - // Release the current weak handle and replace it with a strong handle. - MonoGCHandleData strong_gchandle = MonoGCHandleData::new_strong_handle(target); - gchandle.release(); - gchandle = strong_gchandle; - } -#endif -} + return false; + } else { + // Refcount decremented + if (refcount == 1 && !gchandle.is_released() && !gchandle.is_weak()) { // The managed side also holds a reference, hence 1 instead of 0 + GD_MONO_SCOPE_THREAD_ATTACH; -bool CSharpLanguage::refcount_decremented_instance_binding(Object *p_object) { -#if 0 - RefCounted *rc_owner = Object::cast_to<RefCounted>(p_object); + // If owner owner is no longer referenced by the unmanaged side, + // the managed instance takes responsibility of deleting the owner when GCed. -#ifdef DEBUG_ENABLED - CRASH_COND(!rc_owner); - CRASH_COND(!p_object->has_script_instance_binding(get_language_index())); -#endif + MonoObject *target = gchandle.get_target(); + if (!target) { + return refcount == 0; // Called after the managed side was collected, so nothing to do here + } - void *data = p_object->get_script_instance_binding(get_language_index()); - CRASH_COND(!data); + // Release the current strong handle and replace it with a weak handle. + MonoGCHandleData weak_gchandle = MonoGCHandleData::new_weak_handle(target); + gchandle.release(); + gchandle = weak_gchandle; - CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get(); - MonoGCHandleData &gchandle = script_binding.gchandle; - - int refcount = rc_owner->reference_get_count(); + return false; + } - if (!script_binding.inited) { return refcount == 0; } +} - if (refcount == 1 && !gchandle.is_released() && !gchandle.is_weak()) { // The managed side also holds a reference, hence 1 instead of 0 - GD_MONO_SCOPE_THREAD_ATTACH; +void *CSharpLanguage::get_instance_binding(Object *p_object) { + void *binding = p_object->get_instance_binding(get_singleton(), &_instance_binding_callbacks); - // If owner owner is no longer referenced by the unmanaged side, - // the managed instance takes responsibility of deleting the owner when GCed. + // Initially this was in `_instance_binding_create_callback`. However, after the new instance + // binding re-write it was resulting in a deadlock in `_instance_binding_reference`, as + // `setup_csharp_script_binding` may call `reference()`. It was moved here outside to fix that. - MonoObject *target = gchandle.get_target(); - if (!target) { - return refcount == 0; // Called after the managed side was collected, so nothing to do here - } + if (binding) { + CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)binding)->value(); - // Release the current strong handle and replace it with a weak handle. - MonoGCHandleData weak_gchandle = MonoGCHandleData::new_weak_handle(target); - gchandle.release(); - gchandle = weak_gchandle; + if (!script_binding.inited) { + MutexLock lock(CSharpLanguage::get_singleton()->get_language_bind_mutex()); - return false; + if (!script_binding.inited) { // Another thread may have set it up + CSharpLanguage::get_singleton()->setup_csharp_script_binding(script_binding, p_object); + } + } } - return refcount == 0; + return binding; +} + +void *CSharpLanguage::get_existing_instance_binding(Object *p_object) { +#ifdef DEBUG_ENABLED + CRASH_COND(p_object->has_instance_binding(p_object)); #endif - return false; + return p_object->get_instance_binding(get_singleton(), &_instance_binding_callbacks); +} + +void CSharpLanguage::set_instance_binding(Object *p_object, void *p_binding) { + p_object->set_instance_binding(get_singleton(), p_binding, &_instance_binding_callbacks); +} + +bool CSharpLanguage::has_instance_binding(Object *p_object) { + return p_object->has_instance_binding(get_singleton()); } CSharpInstance *CSharpInstance::create_for_managed_type(Object *p_owner, CSharpScript *p_script, const MonoGCHandleData &p_gchandle) { @@ -2260,29 +2284,16 @@ CSharpInstance::~CSharpInstance() { // Otherwise, the unsafe reference debug checks will incorrectly detect a bug. bool die = _unreference_owner_unsafe(); CRASH_COND(die); // `owner_keep_alive` holds a reference, so it can't die -#if 0 - void *data = owner->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index()); - + void *data = CSharpLanguage::get_instance_binding(owner); CRASH_COND(data == nullptr); - CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get(); - - if (!script_binding.inited) { - MutexLock lock(CSharpLanguage::get_singleton()->get_language_bind_mutex()); - - if (!script_binding.inited) { // Other thread may have set it up - // Already had a binding that needs to be setup - CSharpLanguage::get_singleton()->setup_csharp_script_binding(script_binding, owner); - CRASH_COND(!script_binding.inited); - } - } + CRASH_COND(!script_binding.inited); #ifdef DEBUG_ENABLED // The "instance binding" holds a reference so the refcount should be at least 2 before `scope_keep_owner_alive` goes out of scope CRASH_COND(rc_owner->reference_get_count() <= 1); #endif -#endif } if (script.is_valid() && owner) { @@ -3100,10 +3111,10 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg // Hold it alive. Important if we have to dispose a script instance binding before creating the CSharpInstance. ref = Ref<RefCounted>(static_cast<RefCounted *>(p_owner)); } -#if 0 + // If the object had a script instance binding, dispose it before adding the CSharpInstance - if (p_owner->has_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index())) { - void *data = p_owner->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index()); + if (CSharpLanguage::has_instance_binding(p_owner)) { + void *data = CSharpLanguage::get_existing_instance_binding(p_owner); CRASH_COND(data == nullptr); CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get(); @@ -3122,7 +3133,7 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg script_binding.inited = false; } } -#endif + CSharpInstance *instance = memnew(CSharpInstance(Ref<CSharpScript>(this))); instance->base_ref_counted = p_is_ref_counted; instance->owner = p_owner; @@ -3192,7 +3203,7 @@ Variant CSharpScript::_new(const Variant **p_args, int p_argcount, Callable::Cal CSharpInstance *instance = _create_instance(p_args, p_argcount, owner, r != nullptr, r_error); if (!instance) { if (ref.is_null()) { - memdelete(owner); //no owner, sorry + memdelete(owner); // no owner, sorry } return Variant(); } diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index da6b60aee2..4552f376d0 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -401,7 +401,18 @@ class CSharpLanguage : public ScriptLanguage { static void _editor_init_callback(); #endif + static void *_instance_binding_create_callback(void *p_token, void *p_instance); + static void _instance_binding_free_callback(void *p_token, void *p_instance, void *p_binding); + static GDNativeBool _instance_binding_reference_callback(void *p_token, void *p_binding, GDNativeBool p_reference); + + static GDNativeInstanceBindingCallbacks _instance_binding_callbacks; + public: + static void *get_instance_binding(Object *p_object); + static void *get_existing_instance_binding(Object *p_object); + static void set_instance_binding(Object *p_object, void *p_binding); + static bool has_instance_binding(Object *p_object); + StringNameCache string_names; const Mutex &get_language_bind_mutex() { return language_bind_mutex; } @@ -507,12 +518,6 @@ public: void thread_enter() override; void thread_exit() override; - // Don't use these. I'm watching you - void *alloc_instance_binding_data(Object *p_object) override; - void free_instance_binding_data(void *p_data) override; - void refcount_incremented_instance_binding(Object *p_object) override; - bool refcount_decremented_instance_binding(Object *p_object) override; - Map<Object *, CSharpScriptBinding>::Element *insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding); bool setup_csharp_script_binding(CSharpScriptBinding &r_script_binding, Object *p_object); diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp index a99dff8432..6c5503a3bd 100644 --- a/modules/mono/glue/base_object_glue.cpp +++ b/modules/mono/glue/base_object_glue.cpp @@ -64,8 +64,8 @@ void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr) { return; } } -#if 0 - void *data = p_ptr->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index()); + + void *data = CSharpLanguage::get_existing_instance_binding(p_ptr); if (data) { CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get(); @@ -76,7 +76,6 @@ void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr) { } } } -#endif } void godot_icall_RefCounted_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoolean p_is_finalizer) { @@ -85,7 +84,7 @@ void godot_icall_RefCounted_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoole // This is only called with RefCounted derived classes CRASH_COND(!Object::cast_to<RefCounted>(p_ptr)); #endif -#if 0 + RefCounted *rc = static_cast<RefCounted *>(p_ptr); if (rc->get_script_instance()) { @@ -113,7 +112,7 @@ void godot_icall_RefCounted_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoole if (rc->unreference()) { memdelete(rc); } else { - void *data = rc->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index()); + void *data = CSharpLanguage::get_existing_instance_binding(rc); if (data) { CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get(); @@ -125,7 +124,6 @@ void godot_icall_RefCounted_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoole } } } -#endif } void godot_icall_Object_ConnectEventSignals(Object *p_ptr) { diff --git a/modules/mono/mono_gd/gd_mono_internals.cpp b/modules/mono/mono_gd/gd_mono_internals.cpp index d6545d50ec..60047545c4 100644 --- a/modules/mono/mono_gd/gd_mono_internals.cpp +++ b/modules/mono/mono_gd/gd_mono_internals.cpp @@ -45,7 +45,7 @@ namespace GDMonoInternals { void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) { // This method should not fail -#if 0 + CRASH_COND(!unmanaged); // All mono objects created from the managed world (e.g.: 'new Player()') @@ -89,12 +89,12 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) { } // The object was just created, no script instance binding should have been attached - CRASH_COND(unmanaged->has_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index())); + CRASH_COND(CSharpLanguage::has_instance_binding(unmanaged)); void *data = (void *)CSharpLanguage::get_singleton()->insert_script_binding(unmanaged, script_binding); // Should be thread safe because the object was just created and nothing else should be referencing it - unmanaged->set_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index(), data); + CSharpLanguage::set_instance_binding(unmanaged, data); return; } @@ -108,7 +108,6 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) { CSharpInstance *csharp_instance = CSharpInstance::create_for_managed_type(unmanaged, script.ptr(), gchandle); unmanaged->set_script_and_instance(script, csharp_instance); -#endif } void unhandled_exception(MonoException *p_exc) { diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp index 080398c997..13939bd014 100644 --- a/modules/mono/mono_gd/gd_mono_utils.cpp +++ b/modules/mono/mono_gd/gd_mono_utils.cpp @@ -54,7 +54,6 @@ namespace GDMonoUtils { MonoObject *unmanaged_get_managed(Object *unmanaged) { -#if 0 if (!unmanaged) { return nullptr; } @@ -69,22 +68,10 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) { // If the owner does not have a CSharpInstance... - void *data = unmanaged->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index()); - + void *data = CSharpLanguage::get_instance_binding(unmanaged); ERR_FAIL_NULL_V(data, nullptr); - CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->value(); - - if (!script_binding.inited) { - MutexLock lock(CSharpLanguage::get_singleton()->get_language_bind_mutex()); - - if (!script_binding.inited) { // Other thread may have set it up - // Already had a binding that needs to be setup - CSharpLanguage::get_singleton()->setup_csharp_script_binding(script_binding, unmanaged); - - ERR_FAIL_COND_V(!script_binding.inited, nullptr); - } - } + ERR_FAIL_COND_V(!script_binding.inited, nullptr); MonoGCHandleData &gchandle = script_binding.gchandle; @@ -121,8 +108,6 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) { } return mono_object; -#endif - return nullptr; } void set_main_thread(MonoThread *p_thread) { |
