summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/color.cpp2
-rw-r--r--core/script_debugger_local.cpp5
-rw-r--r--core/script_debugger_local.h1
-rw-r--r--core/script_debugger_remote.cpp83
-rw-r--r--core/script_debugger_remote.h1
-rw-r--r--core/script_language.h4
-rw-r--r--doc/classes/Control.xml12
-rw-r--r--doc/classes/EditorSettings.xml2
-rw-r--r--doc/classes/Label.xml1
-rw-r--r--doc/classes/VehicleBody.xml17
-rw-r--r--editor/editor_settings.cpp6
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp110
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h1
-rw-r--r--editor/plugins/script_editor_plugin.cpp28
-rw-r--r--editor/script_editor_debugger.cpp15
-rw-r--r--modules/gdnative/pluginscript/pluginscript_language.cpp8
-rw-r--r--modules/gdscript/gdscript.h4
-rw-r--r--modules/mono/csharp_script.cpp72
-rw-r--r--modules/mono/csharp_script.h4
-rw-r--r--modules/mono/editor/bindings_generator.cpp58
-rw-r--r--modules/mono/editor/bindings_generator.h3
-rw-r--r--modules/mono/editor/godotsharp_editor.cpp7
-rw-r--r--modules/mono/glue/cs_files/DebuggingUtils.cs77
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp2
-rw-r--r--modules/mono/mono_gd/gd_mono_class.cpp14
-rw-r--r--modules/mono/mono_gd/gd_mono_class.h6
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp73
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.h24
-rw-r--r--scene/resources/bit_mask.cpp4
29 files changed, 454 insertions, 190 deletions
diff --git a/core/color.cpp b/core/color.cpp
index 7278b5c4ee..36afe5e004 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 57463a662d..0da377453e 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 c93120331d..c87bc90bb4 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 e3dc8eb53a..a297bb738f 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 924d5de2c4..2c4e29f172 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 6bf2129f9b..66614a293c 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 680e008ff1..214f78afab 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 174b62fde0..da6ecebcba 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 089b81164b..bfc130634d 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 77916a7e9f..4256ddd674 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/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 7081bb925f..d3e3269c42 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/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 2a46aba207..bd5e5c7355 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -4435,6 +4435,7 @@ void CanvasItemEditorViewport::_on_change_type_closed() {
void CanvasItemEditorViewport::_create_preview(const Vector<String> &files) const {
label->set_position(get_global_position() + Point2(14, 14) * EDSCALE);
label_desc->set_position(label->get_position() + Point2(0, label->get_size().height));
+ bool add_preview = false;
for (int i = 0; i < files.size(); i++) {
String path = files[i];
RES res = ResourceLoader::load(path);
@@ -4456,9 +4457,12 @@ void CanvasItemEditorViewport::_create_preview(const Vector<String> &files) cons
}
}
}
- editor->get_scene_root()->add_child(preview_node);
+ add_preview = true;
}
}
+
+ if (add_preview)
+ editor->get_scene_root()->add_child(preview_node);
}
void CanvasItemEditorViewport::_remove_preview() {
@@ -4603,6 +4607,14 @@ bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, cons
void CanvasItemEditorViewport::_perform_drop_data() {
_remove_preview();
+ // Without root dropping multiple files is not allowed
+ if (!target_node && selected_files.size() > 1) {
+ accept->get_ok()->set_text(TTR("Ok"));
+ accept->set_text(TTR("Cannot instantiate multiple nodes without root."));
+ accept->popup_centered_minsize();
+ return;
+ }
+
Vector<String> error_files;
editor_data->get_undo_redo().create_action(TTR("Create Node"));
@@ -4613,30 +4625,40 @@ void CanvasItemEditorViewport::_perform_drop_data() {
if (res.is_null()) {
continue;
}
- Ref<Texture> texture = Ref<Texture>(Object::cast_to<Texture>(*res));
Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
- if (texture != NULL) {
- Node *child;
- if (default_type == "Light2D")
- child = memnew(Light2D);
- else if (default_type == "Particles2D")
- child = memnew(Particles2D);
- else if (default_type == "Polygon2D")
- child = memnew(Polygon2D);
- else if (default_type == "TouchScreenButton")
- child = memnew(TouchScreenButton);
- else if (default_type == "TextureRect")
- child = memnew(TextureRect);
- else if (default_type == "NinePatchRect")
- child = memnew(NinePatchRect);
- else
- child = memnew(Sprite); // default
-
- _create_nodes(target_node, child, path, drop_pos);
- } else if (scene != NULL) {
- bool success = _create_instance(target_node, path, drop_pos);
- if (!success) {
- error_files.push_back(path);
+ if (scene != NULL && scene.is_valid()) {
+ if (!target_node) {
+ // Without root node act the same as "Load Inherited Scene"
+ Error err = EditorNode::get_singleton()->load_scene(path, false, true);
+ if (err != OK) {
+ error_files.push_back(path);
+ }
+ } else {
+ bool success = _create_instance(target_node, path, drop_pos);
+ if (!success) {
+ error_files.push_back(path);
+ }
+ }
+ } else {
+ Ref<Texture> texture = Ref<Texture>(Object::cast_to<Texture>(*res));
+ if (texture != NULL && texture.is_valid()) {
+ Node *child;
+ if (default_type == "Light2D")
+ child = memnew(Light2D);
+ else if (default_type == "Particles2D")
+ child = memnew(Particles2D);
+ else if (default_type == "Polygon2D")
+ child = memnew(Polygon2D);
+ else if (default_type == "TouchScreenButton")
+ child = memnew(TouchScreenButton);
+ else if (default_type == "TextureRect")
+ child = memnew(TextureRect);
+ else if (default_type == "NinePatchRect")
+ child = memnew(NinePatchRect);
+ else
+ child = memnew(Sprite); // default
+
+ _create_nodes(target_node, child, path, drop_pos);
}
}
}
@@ -4661,14 +4683,14 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian
if (String(d["type"]) == "files") {
Vector<String> files = d["files"];
bool can_instance = false;
- for (int i = 0; i < files.size(); i++) { // check if dragged files contain resource or scene can be created at least one
+ for (int i = 0; i < files.size(); i++) { // check if dragged files contain resource or scene can be created at least once
RES res = ResourceLoader::load(files[i]);
if (res.is_null()) {
continue;
}
String type = res->get_class();
if (type == "PackedScene") {
- Ref<PackedScene> sdata = ResourceLoader::load(files[i]);
+ Ref<PackedScene> sdata = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
Node *instanced_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
if (!instanced_scene) {
continue;
@@ -4682,7 +4704,7 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian
type == "StreamTexture" ||
type == "AtlasTexture" ||
type == "LargeTexture") {
- Ref<Texture> texture = ResourceLoader::load(files[i]);
+ Ref<Texture> texture = Ref<Texture>(Object::cast_to<Texture>(*res));
if (texture.is_valid() == false) {
continue;
}
@@ -4708,6 +4730,7 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian
}
void CanvasItemEditorViewport::_show_resource_type_selector() {
+ _remove_preview();
List<BaseButton *> btn_list;
button_group->get_buttons(&btn_list);
@@ -4719,6 +4742,17 @@ void CanvasItemEditorViewport::_show_resource_type_selector() {
selector->popup_centered_minsize();
}
+bool CanvasItemEditorViewport::_only_packed_scenes_selected() const {
+
+ for (int i = 0; i < selected_files.size(); ++i) {
+ if (ResourceLoader::load(selected_files[i])->get_class() != "PackedScene") {
+ return false;
+ }
+ }
+
+ return true;
+}
+
void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p_data) {
bool is_shift = Input::get_singleton()->is_key_pressed(KEY_SHIFT);
bool is_alt = Input::get_singleton()->is_key_pressed(KEY_ALT);
@@ -4728,6 +4762,8 @@ void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p
if (d.has("type") && String(d["type"]) == "files") {
selected_files = d["files"];
}
+ if (selected_files.size() == 0)
+ return;
List<Node *> list = editor->get_editor_selection()->get_selected_node_list();
if (list.size() == 0) {
@@ -4737,25 +4773,19 @@ void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p
} else {
drop_pos = p_point;
target_node = NULL;
- _show_resource_type_selector();
- return;
}
}
- if (list.size() != 1) {
- accept->get_ok()->set_text(TTR("I see.."));
- accept->set_text(TTR("This operation requires a single selected node."));
- accept->popup_centered_minsize();
- _remove_preview();
- return;
- }
- target_node = list[0];
- if (is_shift && target_node != editor->get_edited_scene()) {
- target_node = target_node->get_parent();
+ if (list.size() > 0) {
+ target_node = list[0];
+ if (is_shift && target_node != editor->get_edited_scene()) {
+ target_node = target_node->get_parent();
+ }
}
+
drop_pos = p_point;
- if (is_alt) {
+ if (is_alt && !_only_packed_scenes_selected()) {
_show_resource_type_selector();
} else {
_perform_drop_data();
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index 5be71bfc28..ace87f9fe2 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -576,6 +576,7 @@ class CanvasItemEditorViewport : public Control {
void _remove_preview();
bool _cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node);
+ bool _only_packed_scenes_selected() const;
void _create_nodes(Node *parent, Node *child, String &path, const Point2 &p_point);
bool _create_instance(Node *parent, String &path, const Point2 &p_point);
void _perform_drop_data();
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 51954a24d6..f99768400f 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_editor_debugger.cpp b/editor/script_editor_debugger.cpp
index cbf2687d73..629b5b63fb 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 2405afc677..8101ebc6f3 100644
--- a/modules/gdnative/pluginscript/pluginscript_language.cpp
+++ b/modules/gdnative/pluginscript/pluginscript_language.cpp
@@ -45,7 +45,11 @@ void PluginScriptLanguage::init() {
}
String PluginScriptLanguage::get_type() const {
- return String(_desc.type);
+ // We should use _desc.type here, however the returned type is used to
+ // query ClassDB which would complain given the type is not registered
+ // from his point of view...
+ // To solve this we just use a more generic (but present in ClassDB) type.
+ return String("PluginScript");
}
String PluginScriptLanguage::get_extension() const {
@@ -168,7 +172,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 b5bbaa6dc9..9566e3b32e 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 949c636050..2d7583cc23 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 171601f3d8..3ce8a9b64e 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 2205ac4e98..800e3b723b 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 717a6b7a6b..8929b45cce 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 da0a7b4fbd..9e48da68c1 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 0000000000..ced78f658d
--- /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 d4df7e0cb2..6c07c90f79 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 d3315568cb..b826352f02 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 b6052ac0ed..f5895be144 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 ff999b36f2..4aa2c007c2 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 284585856e..1acc547993 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 e99db8d9cb..e9e15a2532 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;
}