diff options
30 files changed, 394 insertions, 152 deletions
diff --git a/core/color.cpp b/core/color.cpp index 7278b5c4e..36afe5e00 100644 --- a/core/color.cpp +++ b/core/color.cpp @@ -396,7 +396,7 @@ String Color::to_html(bool p_alpha) const { txt += _to_hex(g); txt += _to_hex(b); if (p_alpha) - txt = _to_hex(a) + txt; + txt += _to_hex(a); return txt; } diff --git a/core/script_debugger_local.cpp b/core/script_debugger_local.cpp index 57463a662..0da377453 100644 --- a/core/script_debugger_local.cpp +++ b/core/script_debugger_local.cpp @@ -294,6 +294,11 @@ void ScriptDebuggerLocal::send_message(const String &p_message, const Array &p_a print_line("MESSAGE: '" + p_message + "' - " + String(Variant(p_args))); } +void ScriptDebuggerLocal::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type, const Vector<ScriptLanguage::StackInfo> &p_stack_info) { + + print_line("ERROR: '" + (p_descr.empty() ? p_err : p_descr) + "'"); +} + ScriptDebuggerLocal::ScriptDebuggerLocal() { profiling = false; diff --git a/core/script_debugger_local.h b/core/script_debugger_local.h index c93120331..c87bc90bb 100644 --- a/core/script_debugger_local.h +++ b/core/script_debugger_local.h @@ -44,6 +44,7 @@ class ScriptDebuggerLocal : public ScriptDebugger { public: void debug(ScriptLanguage *p_script, bool p_can_continue); virtual void send_message(const String &p_message, const Array &p_args); + virtual void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type, const Vector<ScriptLanguage::StackInfo> &p_stack_info); virtual bool is_profiling() const { return profiling; } virtual void add_profiling_frame_data(const StringName &p_name, const Array &p_data) {} diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp index e3dc8eb53..a297bb738 100644 --- a/core/script_debugger_remote.cpp +++ b/core/script_debugger_remote.cpp @@ -432,22 +432,6 @@ void ScriptDebuggerRemote::_err_handler(void *ud, const char *p_func, const char if (p_type == ERR_HANDLER_SCRIPT) return; //ignore script errors, those go through debugger - ScriptDebuggerRemote *sdr = (ScriptDebuggerRemote *)ud; - - OutputError oe; - oe.error = p_err; - oe.error_descr = p_descr; - oe.source_file = p_file; - oe.source_line = p_line; - oe.source_func = p_func; - oe.warning = p_type == ERR_HANDLER_WARNING; - uint64_t time = OS::get_singleton()->get_ticks_msec(); - oe.hr = time / 3600000; - oe.min = (time / 60000) % 60; - oe.sec = (time / 1000) % 60; - oe.msec = time % 1000; - Array cstack; - Vector<ScriptLanguage::StackInfo> si; for (int i = 0; i < ScriptServer::get_language_count(); i++) { @@ -456,32 +440,8 @@ void ScriptDebuggerRemote::_err_handler(void *ud, const char *p_func, const char break; } - cstack.resize(si.size() * 2); - for (int i = 0; i < si.size(); i++) { - String path; - int line = 0; - if (si[i].script.is_valid()) { - path = si[i].script->get_path(); - line = si[i].line; - } - cstack[i * 2 + 0] = path; - cstack[i * 2 + 1] = line; - } - - oe.callstack = cstack; - - sdr->mutex->lock(); - - if (!sdr->locking && sdr->tcp_client->is_connected_to_host()) { - - if (sdr->errors.size() >= sdr->max_errors_per_frame) { - sdr->n_errors_dropped++; - } else { - sdr->errors.push_back(oe); - } - } - - sdr->mutex->unlock(); + ScriptDebuggerRemote *sdr = (ScriptDebuggerRemote *)ud; + sdr->send_error(p_func, p_file, p_line, p_err, p_descr, p_type, si); } bool ScriptDebuggerRemote::_parse_live_edit(const Array &p_command) { @@ -928,6 +888,45 @@ void ScriptDebuggerRemote::send_message(const String &p_message, const Array &p_ mutex->unlock(); } +void ScriptDebuggerRemote::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type, const Vector<ScriptLanguage::StackInfo> &p_stack_info) { + + OutputError oe; + oe.error = p_err; + oe.error_descr = p_descr; + oe.source_file = p_file; + oe.source_line = p_line; + oe.source_func = p_func; + oe.warning = p_type == ERR_HANDLER_WARNING; + uint64_t time = OS::get_singleton()->get_ticks_msec(); + oe.hr = time / 3600000; + oe.min = (time / 60000) % 60; + oe.sec = (time / 1000) % 60; + oe.msec = time % 1000; + Array cstack; + + cstack.resize(p_stack_info.size() * 3); + for (int i = 0; i < p_stack_info.size(); i++) { + cstack[i * 3 + 0] = p_stack_info[i].file; + cstack[i * 3 + 1] = p_stack_info[i].func; + cstack[i * 3 + 2] = p_stack_info[i].line; + } + + oe.callstack = cstack; + + mutex->lock(); + + if (!locking && tcp_client->is_connected_to_host()) { + + if (errors.size() >= max_errors_per_frame) { + n_errors_dropped++; + } else { + errors.push_back(oe); + } + } + + mutex->unlock(); +} + void ScriptDebuggerRemote::_print_handler(void *p_this, const String &p_string, bool p_error) { ScriptDebuggerRemote *sdr = (ScriptDebuggerRemote *)p_this; diff --git a/core/script_debugger_remote.h b/core/script_debugger_remote.h index 924d5de2c..2c4e29f17 100644 --- a/core/script_debugger_remote.h +++ b/core/script_debugger_remote.h @@ -157,6 +157,7 @@ public: virtual void request_quit(); virtual void send_message(const String &p_message, const Array &p_args); + virtual void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type, const Vector<ScriptLanguage::StackInfo> &p_stack_info); virtual void set_request_scene_tree_message_func(RequestSceneTreeMessageFunc p_func, void *p_udata); virtual void set_live_edit_funcs(LiveEditFuncs *p_funcs); diff --git a/core/script_language.h b/core/script_language.h index 6bf2129f9..66614a293 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -254,7 +254,8 @@ public: virtual String debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems = -1, int p_max_depth = -1) = 0; struct StackInfo { - Ref<Script> script; + String file; + String func; int line; }; @@ -391,6 +392,7 @@ public: ScriptLanguage *get_break_language() const; virtual void send_message(const String &p_message, const Array &p_args) = 0; + virtual void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type, const Vector<ScriptLanguage::StackInfo> &p_stack_info) = 0; virtual bool is_remote() const { return false; } virtual void request_quit() {} diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml index 680e008ff..214f78afa 100644 --- a/doc/classes/Control.xml +++ b/doc/classes/Control.xml @@ -632,7 +632,7 @@ Distance between the node's top edge and its parent container, based on [member anchor_top]. </member> <member name="mouse_filter" type="int" setter="set_mouse_filter" getter="get_mouse_filter" enum="Control.MouseFilter"> - Controls whether the control will be able to receive mouse button input events through [Control._gui_input] and how these events should be handled. Use one of the [code]MOUSE_FILTER_*[/code] constants. See the constants to learn what each does. + Controls whether the control will be able to receive mouse button input events through [method _gui_input] and how these events should be handled. Use one of the [code]MOUSE_FILTER_*[/code] constants. See the constants to learn what each does. </member> <member name="rect_clip_content" type="bool" setter="set_clip_contents" getter="is_clipping_contents"> </member> @@ -697,12 +697,12 @@ </signal> <signal name="mouse_entered"> <description> - Emitted when the mouse enters the control's [code]Rect[/code] area. + Emitted when the mouse enters the control's [code]Rect[/code] area, provided its [member mouse_filter] lets the event reach it. </description> </signal> <signal name="mouse_exited"> <description> - Emitted when the mouse leaves the control's [code]Rect[/code] area. + Emitted when the mouse leaves the control's [code]Rect[/code] area, provided its [member mouse_filter] lets the event reach it. </description> </signal> <signal name="resized"> @@ -870,13 +870,13 @@ Tells the parent [Container] to align the node with its end, either the bottom or the right edge. It doesn't work with the fill or expand size flags. Use with [member size_flags_horizontal] and [member size_flags_vertical]. </constant> <constant name="MOUSE_FILTER_STOP" value="0" enum="MouseFilter"> - The control will receive mouse button input events through [method Control._gui_input] if clicked on. These events are automatically marked as handled and they will not propogate further to other controls. + The control will receive mouse button input events through [method _gui_input] if clicked on. These events are automatically marked as handled and they will not propagate further to other controls. </constant> <constant name="MOUSE_FILTER_PASS" value="1" enum="MouseFilter"> - The control will receive mouse button input events through [method Control._gui_input] if clicked on. If this control does not handle the event, the parent control (if any) will be considered for a mouse click, and so on until there is no more parent control to potentially handle it. Even if no control handled it at all, the event will still be handled automatically. + The control will receive mouse button input events through [method _gui_input] if clicked on. If this control does not handle the event, the parent control (if any) will be considered for a mouse click, and so on until there is no more parent control to potentially handle it. Even if no control handled it at all, the event will still be handled automatically. </constant> <constant name="MOUSE_FILTER_IGNORE" value="2" enum="MouseFilter"> - The control will not receive mouse button input events through [method Control._gui_input] and will not block other controls from receiving these events. These events will also not be handled automatically. + The control will not receive mouse button input events through [method _gui_input] and will not block other controls from receiving these events. These events will also not be handled automatically. </constant> <constant name="GROW_DIRECTION_BEGIN" value="0" enum="GrowDirection"> </constant> diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml index 174b62fde..da6ecebcb 100644 --- a/doc/classes/EditorSettings.xml +++ b/doc/classes/EditorSettings.xml @@ -126,6 +126,8 @@ </argument> <argument index="1" name="value" type="Variant"> </argument> + <argument index="2" name="update_current" type="bool"> + </argument> <description> </description> </method> diff --git a/doc/classes/Label.xml b/doc/classes/Label.xml index 089b81164..bfc130634 100644 --- a/doc/classes/Label.xml +++ b/doc/classes/Label.xml @@ -5,6 +5,7 @@ </brief_description> <description> Label displays plain text on the screen. It gives you control over the horizontal and vertical alignment, and can wrap the text inside the node's bounding rectangle. It doesn't support bold, italics or other formatting. For that, use [RichTextLabel] instead. + Note that contrarily to most other [Control]s, Label's [member Control.mouse_filter] defaults to MOUSE_FILTER_IGNORE (i.e. it doesn't react to mouse input events). </description> <tutorials> </tutorials> diff --git a/doc/classes/VehicleBody.xml b/doc/classes/VehicleBody.xml index 77916a7e9..4256ddd67 100644 --- a/doc/classes/VehicleBody.xml +++ b/doc/classes/VehicleBody.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VehicleBody" inherits="PhysicsBody" category="Core" version="3.0-beta"> +<class name="VehicleBody" inherits="RigidBody" category="Core" version="3.0-beta"> <brief_description> </brief_description> <description> @@ -9,27 +9,12 @@ <demos> </demos> <methods> - <method name="get_linear_velocity" qualifiers="const"> - <return type="Vector3"> - </return> - <description> - Returns the VehicleBody's velocity vector. To get the absolute speed in scalar value, get the length of the return vector in pixels/second. Example: - [codeblock] - # vehicle is an instance of VehicleBody - var speed = vehicle.get_linear_velocity().length() - [/codeblock] - </description> - </method> </methods> <members> <member name="brake" type="float" setter="set_brake" getter="get_brake"> </member> <member name="engine_force" type="float" setter="set_engine_force" getter="get_engine_force"> </member> - <member name="friction" type="float" setter="set_friction" getter="get_friction"> - </member> - <member name="mass" type="float" setter="set_mass" getter="get_mass"> - </member> <member name="steering" type="float" setter="set_steering" getter="get_steering"> </member> </members> diff --git a/drivers/gles3/shaders/effect_blur.glsl b/drivers/gles3/shaders/effect_blur.glsl index b5f98a124..c8567b4d5 100644 --- a/drivers/gles3/shaders/effect_blur.glsl +++ b/drivers/gles3/shaders/effect_blur.glsl @@ -214,7 +214,7 @@ void main() { vec4 color_accum = vec4(0.0); - float max_accum=0; + float max_accum=0.0; for(int i=0;i<dof_kernel_size;i++) { diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 7081bb925..d3e3269c4 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -992,7 +992,7 @@ void EditorSettings::raise_order(const String &p_setting) { props[p_setting].order = ++last_order; } -void EditorSettings::set_initial_value(const StringName &p_setting, const Variant &p_value, bool update_current) { +void EditorSettings::set_initial_value(const StringName &p_setting, const Variant &p_value, bool p_update_current) { _THREAD_SAFE_METHOD_ @@ -1000,7 +1000,7 @@ void EditorSettings::set_initial_value(const StringName &p_setting, const Varian return; props[p_setting].initial = p_value; props[p_setting].has_default_value = true; - if (update_current) { + if (p_update_current) { set(p_setting, p_value); } } @@ -1436,7 +1436,7 @@ void EditorSettings::_bind_methods() { ClassDB::bind_method(D_METHOD("set_setting", "name", "value"), &EditorSettings::set_setting); ClassDB::bind_method(D_METHOD("get_setting", "name"), &EditorSettings::get_setting); ClassDB::bind_method(D_METHOD("erase", "property"), &EditorSettings::erase); - ClassDB::bind_method(D_METHOD("set_initial_value", "name", "value"), &EditorSettings::set_initial_value); + ClassDB::bind_method(D_METHOD("set_initial_value", "name", "value", "update_current"), &EditorSettings::set_initial_value); ClassDB::bind_method(D_METHOD("property_can_revert", "name"), &EditorSettings::property_can_revert); ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &EditorSettings::property_get_revert); ClassDB::bind_method(D_METHOD("add_property_info", "info"), &EditorSettings::_add_property_info_bind); diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 51954a24d..f99768400 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -313,24 +313,22 @@ void ScriptEditor::_goto_script_line2(int p_line) { void ScriptEditor::_goto_script_line(REF p_script, int p_line) { - editor->push_item(p_script.ptr()); + Ref<Script> script = Object::cast_to<Script>(*p_script); + if (!script.is_null() && script->get_path().is_resource_file()) { + if (edit(p_script, p_line, 0)) { + editor->push_item(p_script.ptr()); - if (bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor"))) { - - Ref<Script> script = Object::cast_to<Script>(*p_script); - if (!script.is_null() && script->get_path().is_resource_file()) - edit(p_script, p_line, 0); - } - - int selected = tab_container->get_current_tab(); - if (selected < 0 || selected >= tab_container->get_child_count()) - return; + int selected = tab_container->get_current_tab(); + if (selected < 0 || selected >= tab_container->get_child_count()) + return; - ScriptEditorBase *current = Object::cast_to<ScriptEditorBase>(tab_container->get_child(selected)); - if (!current) - return; + ScriptEditorBase *current = Object::cast_to<ScriptEditorBase>(tab_container->get_child(selected)); + if (!current) + return; - current->goto_line(p_line, true); + current->goto_line(p_line, true); + } + } } void ScriptEditor::_update_history_arrows() { diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index f1f1dd040..cee356b93 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -307,7 +307,7 @@ void ScriptCreateDialog::_browse_path(bool browse_parent) { is_browsing_parent = browse_parent; - file_browse->set_mode(EditorFileDialog::MODE_OPEN_FILE); + file_browse->set_mode(EditorFileDialog::MODE_SAVE_FILE); file_browse->set_disable_overwrite_warning(true); file_browse->clear_filters(); List<String> extensions; diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index cbf2687d7..629b5b63f 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -1616,30 +1616,33 @@ void ScriptEditorDebugger::_error_selected(int p_idx) { error_stack->clear(); Array st = error_list->get_item_metadata(p_idx); - for (int i = 0; i < st.size(); i += 2) { + for (int i = 0; i < st.size(); i += 3) { String script = st[i]; - int line = st[i + 1]; + String func = st[i + 1]; + int line = st[i + 2]; Array md; md.push_back(st[i]); md.push_back(st[i + 1]); + md.push_back(st[i + 2]); - String str = script.get_file() + ":" + itos(line); + String str = func + " in " + script.get_file() + ":line " + itos(line); error_stack->add_item(str); error_stack->set_item_metadata(error_stack->get_item_count() - 1, md); - error_stack->set_item_tooltip(error_stack->get_item_count() - 1, TTR("File:") + " " + String(st[i]) + "\n" + TTR("Line:") + " " + itos(line)); + error_stack->set_item_tooltip(error_stack->get_item_count() - 1, + TTR("File:") + " " + script + "\n" + TTR("Function:") + " " + func + "\n" + TTR("Line:") + " " + itos(line)); } } void ScriptEditorDebugger::_error_stack_selected(int p_idx) { Array arr = error_stack->get_item_metadata(p_idx); - if (arr.size() != 2) + if (arr.size() != 3) return; Ref<Script> s = ResourceLoader::load(arr[0]); - emit_signal("goto_script_line", s, int(arr[1]) - 1); + emit_signal("goto_script_line", s, int(arr[2]) - 1); } void ScriptEditorDebugger::set_hide_on_stop(bool p_hide) { diff --git a/modules/gdnative/pluginscript/pluginscript_language.cpp b/modules/gdnative/pluginscript/pluginscript_language.cpp index 2405afc67..2751d73ca 100644 --- a/modules/gdnative/pluginscript/pluginscript_language.cpp +++ b/modules/gdnative/pluginscript/pluginscript_language.cpp @@ -168,7 +168,7 @@ Error PluginScriptLanguage::complete_code(const String &p_code, const String &p_ for (int i = 0; i < options.size(); i++) { r_options->push_back(String(options[i])); } - Error err = *(Error *)tmp; + Error err = *(Error *)&tmp; return err; } return ERR_UNAVAILABLE; diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index b5bbaa6dc..9566e3b32 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -349,7 +349,9 @@ public: csi.resize(_debug_call_stack_pos); for (int i = 0; i < _debug_call_stack_pos; i++) { csi[_debug_call_stack_pos - i - 1].line = _call_stack[i].line ? *_call_stack[i].line : 0; - csi[_debug_call_stack_pos - i - 1].script = Ref<GDScript>(_call_stack[i].function->get_script()); + if (_call_stack[i].function) + csi[_debug_call_stack_pos - i - 1].func = _call_stack[i].function->get_name(); + csi[_debug_call_stack_pos - i - 1].file = _call_stack[i].function->get_script()->get_path(); } return csi; } diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 949c63605..2d7583cc2 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -445,6 +445,72 @@ String CSharpLanguage::_get_indentation() const { return "\t"; } +Vector<ScriptLanguage::StackInfo> CSharpLanguage::debug_get_current_stack_info() { + + // Printing an error here will result in endless recursion, so we must be careful + + if (!gdmono->is_runtime_initialized() && GDMono::get_singleton()->get_editor_tools_assembly()) + return Vector<StackInfo>(); + + MonoObject *stack_trace = mono_object_new(mono_domain_get(), CACHED_CLASS(System_Diagnostics_StackTrace)->get_mono_ptr()); + + MonoBoolean need_file_info = true; + void *ctor_args[1] = { &need_file_info }; + + CACHED_METHOD(System_Diagnostics_StackTrace, ctor_bool)->invoke_raw(stack_trace, ctor_args); + + Vector<StackInfo> si; + si = stack_trace_get_info(stack_trace); + + return si; +} + +Vector<ScriptLanguage::StackInfo> CSharpLanguage::stack_trace_get_info(MonoObject *p_stack_trace) { + + // Printing an error here could result in endless recursion, so we must be careful + + MonoObject *exc = NULL; + + GDMonoUtils::StackTrace_GetFrames st_get_frames = CACHED_METHOD_THUNK(System_Diagnostics_StackTrace, GetFrames); + MonoArray *frames = st_get_frames(p_stack_trace, &exc); + + if (exc) { + GDMonoUtils::print_unhandled_exception(exc, true /* fail silently to avoid endless recursion */); + return Vector<StackInfo>(); + } + + int frame_count = mono_array_length(frames); + + if (frame_count <= 0) + return Vector<StackInfo>(); + + GDMonoUtils::DebugUtils_StackFrameInfo get_sf_info = CACHED_METHOD_THUNK(DebuggingUtils, GetStackFrameInfo); + + Vector<StackInfo> si; + si.resize(frame_count); + + for (int i = 0; i < frame_count; i++) { + StackInfo &sif = si[i]; + MonoObject *frame = mono_array_get(frames, MonoObject *, i); + + MonoString *file_name; + int file_line_num; + MonoString *method_decl; + get_sf_info(frame, &file_name, &file_line_num, &method_decl, &exc); + + if (exc) { + GDMonoUtils::print_unhandled_exception(exc, true /* fail silently to avoid endless recursion */); + return Vector<StackInfo>(); + } + + sif.file = GDMonoMarshal::mono_string_to_godot(file_name); + sif.line = file_line_num; + sif.func = GDMonoMarshal::mono_string_to_godot(method_decl); + } + + return si; +} + void CSharpLanguage::frame() { const Ref<MonoGCHandle> &task_scheduler_handle = GDMonoUtils::mono_cache.task_scheduler_handle; @@ -1049,7 +1115,7 @@ bool CSharpInstance::has_method(const StringName &p_method) const { GDMonoClass *top = script->script_class; while (top && top != script->native) { - if (top->has_method(p_method)) { + if (top->has_fetched_method_unknown_params(p_method)) { return true; } @@ -1227,7 +1293,7 @@ ScriptInstance::RPCMode CSharpInstance::get_rpc_mode(const StringName &p_method) GDMonoClass *top = script->script_class; while (top && top != script->native) { - GDMonoMethod *method = top->get_method(p_method); + GDMonoMethod *method = top->get_fetched_method_unknown_params(p_method); if (method && !method->is_static()) return _member_get_rpc_mode(method); @@ -1848,7 +1914,7 @@ void CSharpScript::set_source_code(const String &p_code) { bool CSharpScript::has_method(const StringName &p_method) const { - return script_class->has_method(p_method); + return script_class->has_fetched_method_unknown_params(p_method); } Error CSharpScript::reload(bool p_keep_state) { diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index 171601f3d..3ce8a9b64 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -303,7 +303,7 @@ public: /* TODO */ virtual void debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {} /* TODO */ virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {} /* TODO */ virtual String debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems, int p_max_depth) { return ""; } - /* TODO */ virtual Vector<StackInfo> debug_get_current_stack_info() { return Vector<StackInfo>(); } + virtual Vector<StackInfo> debug_get_current_stack_info(); /* PROFILING FUNCTIONS */ /* TODO */ virtual void profiling_start() {} @@ -335,6 +335,8 @@ public: virtual void *alloc_instance_binding_data(Object *p_object); virtual void free_instance_binding_data(void *p_data); + Vector<StackInfo> stack_trace_get_info(MonoObject *p_stack_trace); + CSharpLanguage(); ~CSharpLanguage(); }; diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 2205ac4e9..800e3b723 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -448,14 +448,14 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo compile_items.push_back(output_file); } - for (Map<StringName, TypeInterface>::Element *E = obj_types.front(); E; E = E->next()) { - const TypeInterface &itype = E->get(); + for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) { + const TypeInterface &itype = E.get(); if (itype.api_type == ClassDB::API_EDITOR) continue; - String output_file = path_join(obj_type_dir, E->get().proxy_name + ".cs"); - Error err = _generate_cs_type(E->get(), output_file); + String output_file = path_join(obj_type_dir, itype.proxy_name + ".cs"); + Error err = _generate_cs_type(itype, output_file); if (err == ERR_SKIP) continue; @@ -580,14 +580,14 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir, if (!solution.set_path(p_output_dir)) return ERR_FILE_NOT_FOUND; - for (Map<StringName, TypeInterface>::Element *E = obj_types.front(); E; E = E->next()) { - const TypeInterface &itype = E->get(); + for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) { + const TypeInterface &itype = E.get(); if (itype.api_type != ClassDB::API_EDITOR) continue; - String output_file = path_join(obj_type_dir, E->get().proxy_name + ".cs"); - Error err = _generate_cs_type(E->get(), output_file); + String output_file = path_join(obj_type_dir, itype.proxy_name + ".cs"); + Error err = _generate_cs_type(itype, output_file); if (err == ERR_SKIP) continue; @@ -945,7 +945,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str return ERR_BUG; } - Map<StringName, TypeInterface>::Element *object_itype = obj_types.find("Object"); + OrderedHashMap<StringName, TypeInterface>::Element object_itype = obj_types.find("Object"); if (!object_itype) { ERR_PRINT("BUG: Object type interface not found!"); @@ -953,7 +953,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str } output.push_back(MEMBER_BEGIN "public " CS_CLASS_SIGNALAWAITER " ToSignal("); - output.push_back(object_itype->get().cs_type); + output.push_back(object_itype.get().cs_type); output.push_back(" source, string signal)\n" OPEN_BLOCK_L2 "return new " CS_CLASS_SIGNALAWAITER "(source, signal, this);\n" CLOSE_BLOCK_L2); } @@ -999,9 +999,9 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte // Search it in base types too const TypeInterface *current_type = &p_itype; while (!setter && current_type->base_name != StringName()) { - Map<StringName, TypeInterface>::Element *base_match = obj_types.find(current_type->base_name); - ERR_FAIL_NULL_V(base_match, ERR_BUG); - current_type = &base_match->get(); + OrderedHashMap<StringName, TypeInterface>::Element base_match = obj_types.find(current_type->base_name); + ERR_FAIL_COND_V(!base_match, ERR_BUG); + current_type = &base_match.get(); setter = current_type->find_method_by_name(p_iprop.setter); } @@ -1010,9 +1010,9 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte // Search it in base types too current_type = &p_itype; while (!getter && current_type->base_name != StringName()) { - Map<StringName, TypeInterface>::Element *base_match = obj_types.find(current_type->base_name); - ERR_FAIL_NULL_V(base_match, ERR_BUG); - current_type = &base_match->get(); + OrderedHashMap<StringName, TypeInterface>::Element base_match = obj_types.find(current_type->base_name); + ERR_FAIL_COND_V(!base_match, ERR_BUG); + current_type = &base_match.get(); getter = current_type->find_method_by_name(p_iprop.getter); } @@ -1324,8 +1324,8 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { generated_icall_funcs.clear(); - for (Map<StringName, TypeInterface>::Element *type_elem = obj_types.front(); type_elem; type_elem = type_elem->next()) { - const TypeInterface &itype = type_elem->get(); + for (OrderedHashMap<StringName, TypeInterface>::Element type_elem = obj_types.front(); type_elem; type_elem = type_elem.next()) { + const TypeInterface &itype = type_elem.get(); List<InternalCall> &custom_icalls = itype.api_type == ClassDB::API_EDITOR ? editor_custom_icalls : core_custom_icalls; @@ -1631,20 +1631,20 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_by_name_or_null(const StringName &p_cname) { - const Map<StringName, TypeInterface>::Element *match = builtin_types.find(p_cname); + const Map<StringName, TypeInterface>::Element *builtin_type_match = builtin_types.find(p_cname); - if (match) - return &match->get(); + if (builtin_type_match) + return &builtin_type_match->get(); - match = obj_types.find(p_cname); + const OrderedHashMap<StringName, TypeInterface>::Element obj_type_match = obj_types.find(p_cname); - if (match) - return &match->get(); + if (obj_type_match) + return &obj_type_match.get(); - match = enum_types.find(p_cname); + const Map<StringName, TypeInterface>::Element *enum_match = enum_types.find(p_cname); - if (match) - return &match->get(); + if (enum_match) + return &enum_match->get(); return NULL; } @@ -2484,8 +2484,8 @@ void BindingsGenerator::initialize() { _generate_header_icalls(); - for (Map<StringName, TypeInterface>::Element *E = obj_types.front(); E; E = E->next()) - _generate_method_icalls(E->get()); + for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) + _generate_method_icalls(E.get()); _generate_method_icalls(builtin_types["NodePath"]); _generate_method_icalls(builtin_types["RID"]); diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h index 717a6b7a6..8929b45cc 100644 --- a/modules/mono/editor/bindings_generator.h +++ b/modules/mono/editor/bindings_generator.h @@ -429,10 +429,11 @@ class BindingsGenerator { static bool verbose_output; + OrderedHashMap<StringName, TypeInterface> obj_types; + Map<StringName, TypeInterface> placeholder_types; Map<StringName, TypeInterface> builtin_types; Map<StringName, TypeInterface> enum_types; - Map<StringName, TypeInterface> obj_types; List<EnumInterface> global_enums; List<ConstantInterface> global_constants; diff --git a/modules/mono/editor/godotsharp_editor.cpp b/modules/mono/editor/godotsharp_editor.cpp index da0a7b4fb..9e48da68c 100644 --- a/modules/mono/editor/godotsharp_editor.cpp +++ b/modules/mono/editor/godotsharp_editor.cpp @@ -151,7 +151,7 @@ Error GodotSharpEditor::open_in_external_editor(const Ref<Script> &p_script, int if (p_line >= 0) { args.push_back("-g"); - args.push_back(script_path + ":" + itos(p_line) + ":" + itos(p_col)); + args.push_back(script_path + ":" + itos(p_line + 1) + ":" + itos(p_col)); } else { args.push_back(script_path); } @@ -170,6 +170,11 @@ Error GodotSharpEditor::open_in_external_editor(const Ref<Script> &p_script, int monodevel_instance = memnew(MonoDevelopInstance(GodotSharpDirs::get_project_sln_path())); String script_path = ProjectSettings::get_singleton()->globalize_path(p_script->get_path()); + + if (p_line >= 0) { + script_path += ";" + itos(p_line + 1) + ";" + itos(p_col); + } + monodevel_instance->execute(script_path); } break; default: diff --git a/modules/mono/glue/cs_files/DebuggingUtils.cs b/modules/mono/glue/cs_files/DebuggingUtils.cs new file mode 100644 index 000000000..ced78f658 --- /dev/null +++ b/modules/mono/glue/cs_files/DebuggingUtils.cs @@ -0,0 +1,77 @@ +using System; +using System.Diagnostics; +using System.Reflection; +using System.Text; + +namespace Godot +{ + internal static class DebuggingUtils + { + internal static void AppendTypeName(this StringBuilder sb, Type type) + { + if (type.IsPrimitive) + sb.Append(type.Name); + else if (type == typeof(void)) + sb.Append("void"); + else + sb.Append(type.ToString()); + + sb.Append(" "); + } + + public static void GetStackFrameInfo(StackFrame frame, out string fileName, out int fileLineNumber, out string methodDecl) + { + fileName = frame.GetFileName(); + fileLineNumber = frame.GetFileLineNumber(); + + MethodBase methodBase = frame.GetMethod(); + + StringBuilder sb = new StringBuilder(); + + if (methodBase is MethodInfo methodInfo) + sb.AppendTypeName(methodInfo.ReturnType); + + sb.Append(methodBase.DeclaringType.FullName); + sb.Append("."); + sb.Append(methodBase.Name); + + if (methodBase.IsGenericMethod) + { + Type[] genericParams = methodBase.GetGenericArguments(); + + sb.Append("<"); + + for (int j = 0; j < genericParams.Length; j++) + { + if (j > 0) + sb.Append(", "); + + sb.AppendTypeName(genericParams[j]); + } + + sb.Append(">"); + } + + sb.Append("("); + + bool varArgs = (methodBase.CallingConvention & CallingConventions.VarArgs) != 0; + + ParameterInfo[] parameter = methodBase.GetParameters(); + + for (int i = 0; i < parameter.Length; i++) + { + if (i > 0) + sb.Append(", "); + + if (i == parameter.Length - 1 && varArgs) + sb.Append("params "); + + sb.AppendTypeName(parameter[i].ParameterType); + } + + sb.Append(")"); + + methodDecl = sb.ToString(); + } + } +} diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index d4df7e0cb..6c07c90f7 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -226,7 +226,7 @@ void GDMono::initialize() { mono_install_unhandled_exception_hook(gdmono_unhandled_exception_hook, NULL); - OS::get_singleton()->print("Mono: ALL IS GOOD\n"); + OS::get_singleton()->print("Mono: INITIALIZED\n"); } #ifndef MONO_GLUE_DISABLED diff --git a/modules/mono/mono_gd/gd_mono_class.cpp b/modules/mono/mono_gd/gd_mono_class.cpp index d3315568c..b826352f0 100644 --- a/modules/mono/mono_gd/gd_mono_class.cpp +++ b/modules/mono/mono_gd/gd_mono_class.cpp @@ -89,11 +89,6 @@ Vector<MonoClassField *> GDMonoClass::get_enum_fields() { } #endif -bool GDMonoClass::has_method(const StringName &p_name) { - - return get_method(p_name) != NULL; -} - bool GDMonoClass::has_attribute(GDMonoClass *p_attr_class) { #ifdef DEBUG_ENABLED @@ -225,7 +220,7 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base methods_fetched = true; } -GDMonoMethod *GDMonoClass::get_method(const StringName &p_name) { +GDMonoMethod *GDMonoClass::get_fetched_method_unknown_params(const StringName &p_name) { ERR_FAIL_COND_V(!methods_fetched, NULL); @@ -239,6 +234,11 @@ GDMonoMethod *GDMonoClass::get_method(const StringName &p_name) { return NULL; } +bool GDMonoClass::has_fetched_method_unknown_params(const StringName &p_name) { + + return get_fetched_method_unknown_params(p_name) != NULL; +} + GDMonoMethod *GDMonoClass::get_method(const StringName &p_name, int p_params_count) { MethodKey key = MethodKey(p_name, p_params_count); @@ -303,6 +303,8 @@ GDMonoMethod *GDMonoClass::get_method_with_desc(const String &p_description, boo MonoMethod *method = mono_method_desc_search_in_class(desc, mono_class); mono_method_desc_free(desc); + ERR_FAIL_COND_V(mono_method_get_class(method) != mono_class, NULL); + return get_method(method); } diff --git a/modules/mono/mono_gd/gd_mono_class.h b/modules/mono/mono_gd/gd_mono_class.h index b6052ac0e..f5895be14 100644 --- a/modules/mono/mono_gd/gd_mono_class.h +++ b/modules/mono/mono_gd/gd_mono_class.h @@ -112,7 +112,8 @@ public: Vector<MonoClassField *> get_enum_fields(); #endif - bool has_method(const StringName &p_name); + GDMonoMethod *get_fetched_method_unknown_params(const StringName &p_name); + bool has_fetched_method_unknown_params(const StringName &p_name); bool has_attribute(GDMonoClass *p_attr_class); MonoObject *get_attribute(GDMonoClass *p_attr_class); @@ -120,8 +121,7 @@ public: void fetch_attributes(); void fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base); - GDMonoMethod *get_method(const StringName &p_name); - GDMonoMethod *get_method(const StringName &p_name, int p_params_count); + GDMonoMethod *get_method(const StringName &p_name, int p_params_count = 0); GDMonoMethod *get_method(MonoMethod *p_raw_method); GDMonoMethod *get_method(MonoMethod *p_raw_method, const StringName &p_name); GDMonoMethod *get_method(MonoMethod *p_raw_method, const StringName &p_name, int p_params_count); diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp index ff999b36f..4aa2c007c 100644 --- a/modules/mono/mono_gd/gd_mono_utils.cpp +++ b/modules/mono/mono_gd/gd_mono_utils.cpp @@ -31,6 +31,7 @@ #include "gd_mono_utils.h" #include "os/dir_access.h" +#include "os/os.h" #include "project_settings.h" #include "reference.h" @@ -53,6 +54,7 @@ MonoCache mono_cache; #define CACHE_NS_CLASS_AND_CHECK(m_ns, m_class, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.class_##m_ns##_##m_class, m_val) #define CACHE_RAW_MONO_CLASS_AND_CHECK(m_class, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.rawclass_##m_class, m_val) #define CACHE_FIELD_AND_CHECK(m_class, m_field, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.field_##m_class##_##m_field, m_val) +#define CACHE_METHOD_AND_CHECK(m_class, m_method, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.method_##m_class##_##m_method, m_val) #define CACHE_METHOD_THUNK_AND_CHECK(m_class, m_method, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.methodthunk_##m_class##_##m_method, m_val) void MonoCache::clear_members() { @@ -72,6 +74,13 @@ void MonoCache::clear_members() { class_String = NULL; class_IntPtr = NULL; +#ifdef DEBUG_ENABLED + class_System_Diagnostics_StackTrace = NULL; + methodthunk_System_Diagnostics_StackTrace_GetFrames = NULL; + method_System_Diagnostics_StackTrace_ctor_bool = NULL; + method_System_Diagnostics_StackTrace_ctor_Exception_bool = NULL; +#endif + rawclass_Dictionary = NULL; class_Vector2 = NULL; @@ -94,6 +103,11 @@ void MonoCache::clear_members() { class_WeakRef = NULL; class_MarshalUtils = NULL; +#ifdef DEBUG_ENABLED + class_DebuggingUtils = NULL; + methodthunk_DebuggingUtils_GetStackFrameInfo = NULL; +#endif + class_ExportAttribute = NULL; field_ExportAttribute_hint = NULL; field_ExportAttribute_hintString = NULL; @@ -137,6 +151,13 @@ void update_corlib_cache() { CACHE_CLASS_AND_CHECK(double, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_double_class())); CACHE_CLASS_AND_CHECK(String, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_string_class())); CACHE_CLASS_AND_CHECK(IntPtr, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_intptr_class())); + +#ifdef DEBUG_ENABLED + CACHE_CLASS_AND_CHECK(System_Diagnostics_StackTrace, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Diagnostics", "StackTrace")); + CACHE_METHOD_THUNK_AND_CHECK(System_Diagnostics_StackTrace, GetFrames, (StackTrace_GetFrames)CACHED_CLASS(System_Diagnostics_StackTrace)->get_method("GetFrames")->get_thunk()); + CACHE_METHOD_AND_CHECK(System_Diagnostics_StackTrace, ctor_bool, CACHED_CLASS(System_Diagnostics_StackTrace)->get_method_with_desc("System.Diagnostics.StackTrace:.ctor(bool)", true)); + CACHE_METHOD_AND_CHECK(System_Diagnostics_StackTrace, ctor_Exception_bool, CACHED_CLASS(System_Diagnostics_StackTrace)->get_method_with_desc("System.Diagnostics.StackTrace:.ctor(System.Exception,bool)", true)); +#endif } void update_godot_api_cache() { @@ -161,6 +182,10 @@ void update_godot_api_cache() { CACHE_CLASS_AND_CHECK(WeakRef, GODOT_API_CLASS(WeakRef)); CACHE_CLASS_AND_CHECK(MarshalUtils, GODOT_API_CLASS(MarshalUtils)); +#ifdef DEBUG_ENABLED + CACHE_CLASS_AND_CHECK(DebuggingUtils, GODOT_API_CLASS(DebuggingUtils)); +#endif + // Attributes CACHE_CLASS_AND_CHECK(ExportAttribute, GODOT_API_CLASS(ExportAttribute)); CACHE_FIELD_AND_CHECK(ExportAttribute, hint, CACHED_CLASS(ExportAttribute)->get_field("hint")); @@ -183,6 +208,10 @@ void update_godot_api_cache() { CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, FailureCallback, (SignalAwaiter_FailureCallback)GODOT_API_CLASS(SignalAwaiter)->get_method("FailureCallback", 0)->get_thunk()); CACHE_METHOD_THUNK_AND_CHECK(GodotTaskScheduler, Activate, (GodotTaskScheduler_Activate)GODOT_API_CLASS(GodotTaskScheduler)->get_method("Activate", 0)->get_thunk()); +#ifdef DEBUG_ENABLED + CACHE_METHOD_THUNK_AND_CHECK(DebuggingUtils, GetStackFrameInfo, (DebugUtils_StackFrameInfo)GODOT_API_CLASS(DebuggingUtils)->get_method("GetStackFrameInfo", 4)->get_thunk()); +#endif + { /* * TODO Right now we only support Dictionary<object, object>. @@ -366,9 +395,47 @@ String get_exception_name_and_message(MonoObject *p_ex) { return res; } -void print_unhandled_exception(MonoObject *p_ex) { - ERR_PRINT(GDMonoUtils::get_exception_name_and_message(p_ex).utf8()); - mono_print_unhandled_exception(p_ex); +void print_unhandled_exception(MonoObject *p_exc) { + print_unhandled_exception(p_exc, false); +} + +void print_unhandled_exception(MonoObject *p_exc, bool p_fail_silently) { + mono_print_unhandled_exception(p_exc); +#ifdef DEBUG_ENABLED + GDMonoClass *st_klass = CACHED_CLASS(System_Diagnostics_StackTrace); + MonoObject *stack_trace = mono_object_new(mono_domain_get(), st_klass->get_mono_ptr()); + + MonoBoolean need_file_info = true; + void *ctor_args[2] = { p_exc, &need_file_info }; + + MonoObject *unexpected_exc = NULL; + CACHED_METHOD(System_Diagnostics_StackTrace, ctor_Exception_bool)->invoke_raw(stack_trace, ctor_args, &unexpected_exc); + + if (unexpected_exc != NULL) { + mono_print_unhandled_exception(unexpected_exc); + + if (p_fail_silently) { + // Called from CSharpLanguage::get_current_stack_info, + // so printing an error here could result in endless recursion + OS::get_singleton()->printerr("Mono: Method GDMonoUtils::print_unhandled_exception failed"); + return; + } else { + ERR_FAIL(); + } + } + + Vector<ScriptLanguage::StackInfo> si; + if (stack_trace != NULL) + si = CSharpLanguage::get_singleton()->stack_trace_get_info(stack_trace); + + String file = si.size() ? si[0].file : __FILE__; + String func = si.size() ? si[0].func : FUNCTION_STR; + int line = si.size() ? si[0].line : __LINE__; + String error_msg = "Unhandled exception"; + String exc_msg = GDMonoUtils::get_exception_name_and_message(p_exc); + + ScriptDebugger::get_singleton()->send_error(func, file, line, error_msg, exc_msg, ERR_HANDLER_ERROR, si); +#endif } } // namespace GDMonoUtils diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h index 284585856..1acc54799 100644 --- a/modules/mono/mono_gd/gd_mono_utils.h +++ b/modules/mono/mono_gd/gd_mono_utils.h @@ -46,13 +46,10 @@ typedef MonoObject *(*MarshalUtils_ArraysToDict)(MonoArray *, MonoArray *, MonoO typedef MonoObject *(*SignalAwaiter_SignalCallback)(MonoObject *, MonoArray **, MonoObject **); typedef MonoObject *(*SignalAwaiter_FailureCallback)(MonoObject *, MonoObject **); typedef MonoObject *(*GodotTaskScheduler_Activate)(MonoObject *, MonoObject **); +typedef MonoArray *(*StackTrace_GetFrames)(MonoObject *, MonoObject **); +typedef void (*DebugUtils_StackFrameInfo)(MonoObject *, MonoString **, int *, MonoString **, MonoObject **); struct MonoCache { - // Format for cached classes in the Godot namespace: class_<Class> - // Macro: CACHED_CLASS(<Class>) - - // Format for cached classes in a different namespace: class_<Namespace>_<Class> - // Macro: CACHED_NS_CLASS(<Namespace>, <Class>) // ----------------------------------------------- // corlib classes @@ -73,6 +70,13 @@ struct MonoCache { GDMonoClass *class_String; GDMonoClass *class_IntPtr; +#ifdef DEBUG_ENABLED + GDMonoClass *class_System_Diagnostics_StackTrace; + StackTrace_GetFrames methodthunk_System_Diagnostics_StackTrace_GetFrames; + GDMonoMethod *method_System_Diagnostics_StackTrace_ctor_bool; + GDMonoMethod *method_System_Diagnostics_StackTrace_ctor_Exception_bool; +#endif + MonoClass *rawclass_Dictionary; // ----------------------------------------------- @@ -96,6 +100,11 @@ struct MonoCache { GDMonoClass *class_WeakRef; GDMonoClass *class_MarshalUtils; +#ifdef DEBUG_ENABLED + GDMonoClass *class_DebuggingUtils; + DebugUtils_StackFrameInfo methodthunk_DebuggingUtils_GetStackFrameInfo; +#endif + GDMonoClass *class_ExportAttribute; GDMonoField *field_ExportAttribute_hint; GDMonoField *field_ExportAttribute_hintString; @@ -167,7 +176,8 @@ MonoDomain *create_domain(const String &p_friendly_name); String get_exception_name_and_message(MonoObject *p_ex); -void print_unhandled_exception(MonoObject *p_ex); +void print_unhandled_exception(MonoObject *p_exc); +void print_unhandled_exception(MonoObject *p_exc, bool p_fail_silently); } // namespace GDMonoUtils @@ -175,9 +185,9 @@ void print_unhandled_exception(MonoObject *p_ex); #define CACHED_CLASS(m_class) (GDMonoUtils::mono_cache.class_##m_class) #define CACHED_CLASS_RAW(m_class) (GDMonoUtils::mono_cache.class_##m_class->get_mono_ptr()) -#define CACHED_NS_CLASS(m_ns, m_class) (GDMonoUtils::mono_cache.class_##m_ns##_##m_class) #define CACHED_RAW_MONO_CLASS(m_class) (GDMonoUtils::mono_cache.rawclass_##m_class) #define CACHED_FIELD(m_class, m_field) (GDMonoUtils::mono_cache.field_##m_class##_##m_field) +#define CACHED_METHOD(m_class, m_method) (GDMonoUtils::mono_cache.method_##m_class##_##m_method) #define CACHED_METHOD_THUNK(m_class, m_method) (GDMonoUtils::mono_cache.methodthunk_##m_class##_##m_method) #ifdef REAL_T_IS_DOUBLE diff --git a/scene/resources/bit_mask.cpp b/scene/resources/bit_mask.cpp index e99db8d9c..e9e15a253 100644 --- a/scene/resources/bit_mask.cpp +++ b/scene/resources/bit_mask.cpp @@ -81,7 +81,7 @@ void BitMap::set_bit_rect(const Rect2 &p_rect, bool p_value) { if (p_value) b |= (1 << bbit); else - b &= !(1 << bbit); + b &= ~(1 << bbit); data[bbyte] = b; } @@ -127,7 +127,7 @@ void BitMap::set_bit(const Point2 &p_pos, bool p_value) { if (p_value) b |= (1 << bbit); else - b &= !(1 << bbit); + b &= ~(1 << bbit); bitmask[bbyte] = b; } diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp index 575c222cc..b35a9ae96 100644 --- a/scene/resources/dynamic_font.cpp +++ b/scene/resources/dynamic_font.cpp @@ -631,6 +631,7 @@ bool DynamicFontAtSize::update_oversampling() { textures.clear(); char_map.clear(); oversampling = font_oversampling; + valid = false; _load(); return true; @@ -973,14 +974,26 @@ void DynamicFont::finish_dynamic_fonts() { void DynamicFont::update_oversampling() { + Vector<Ref<DynamicFont> > changed; + + if (dynamic_font_mutex) + dynamic_font_mutex->lock(); + SelfList<DynamicFont> *E = dynamic_fonts.first(); while (E) { if (E->self()->data_at_size.is_valid() && E->self()->data_at_size->update_oversampling()) { - E->self()->emit_changed(); + changed.push_back(E->self()); } E = E->next(); } + + if (dynamic_font_mutex) + dynamic_font_mutex->unlock(); + + for (int i = 0; i < changed.size(); i++) { + changed[i]->emit_changed(); + } } ///////////////////////// |
