summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/bind/core_bind.cpp12
-rw-r--r--core/bind/core_bind.h2
-rw-r--r--core/object.cpp16
-rw-r--r--doc/classes/BaseButton.xml1
-rw-r--r--doc/classes/CollisionObject2D.xml2
-rw-r--r--doc/classes/ColorPickerButton.xml2
-rw-r--r--doc/classes/MainLoop.xml1
-rw-r--r--doc/classes/NinePatchRect.xml2
-rw-r--r--doc/classes/PoolByteArray.xml5
-rw-r--r--doc/classes/ShaderMaterial.xml2
-rw-r--r--doc/classes/SpriteFrames.xml1
-rw-r--r--doc/classes/StyleBox.xml8
-rw-r--r--doc/classes/Thread.xml3
-rw-r--r--editor/editor_node.cpp47
-rw-r--r--editor/editor_node.h2
-rw-r--r--editor/editor_resource_preview.cpp2
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp25
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp10
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp9
-rw-r--r--main/main.cpp3
-rw-r--r--modules/gdscript/gdscript_parser.cpp4
-rw-r--r--modules/mono/csharp_script.cpp54
-rw-r--r--modules/mono/csharp_script.h8
-rw-r--r--modules/mono/glue/base_object_glue.cpp1
-rw-r--r--modules/mono/mono_gd/gd_mono_internals.cpp4
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp1
-rw-r--r--modules/visual_script/visual_script_editor.cpp4
-rw-r--r--platform/osx/os_osx.mm6
-rw-r--r--scene/gui/center_container.cpp6
-rw-r--r--scene/gui/graph_edit.cpp7
30 files changed, 190 insertions, 60 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 0eacffeb88..68650019a2 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -3024,6 +3024,16 @@ float _Engine::get_frames_per_second() const {
return Engine::get_singleton()->get_frames_per_second();
}
+uint64_t _Engine::get_physics_frames() const {
+
+ return Engine::get_singleton()->get_physics_frames();
+}
+
+uint64_t _Engine::get_idle_frames() const {
+
+ return Engine::get_singleton()->get_idle_frames();
+}
+
void _Engine::set_time_scale(float p_scale) {
Engine::get_singleton()->set_time_scale(p_scale);
}
@@ -3108,6 +3118,8 @@ void _Engine::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_frames_drawn"), &_Engine::get_frames_drawn);
ClassDB::bind_method(D_METHOD("get_frames_per_second"), &_Engine::get_frames_per_second);
+ ClassDB::bind_method(D_METHOD("get_physics_frames"), &_Engine::get_physics_frames);
+ ClassDB::bind_method(D_METHOD("get_idle_frames"), &_Engine::get_idle_frames);
ClassDB::bind_method(D_METHOD("get_main_loop"), &_Engine::get_main_loop);
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 7c5031cad4..65f20c375e 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -747,6 +747,8 @@ public:
int get_target_fps() const;
float get_frames_per_second() const;
+ uint64_t get_physics_frames() const;
+ uint64_t get_idle_frames() const;
int get_frames_drawn();
diff --git a/core/object.cpp b/core/object.cpp
index 35ccc38d4e..21666a334c 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -1185,13 +1185,11 @@ Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int
const Connection &c = slot_map.getv(i).conn;
- Object *target;
-#ifdef DEBUG_ENABLED
- target = ObjectDB::get_instance(slot_map.getk(i)._id);
- ERR_CONTINUE(!target);
-#else
- target = c.target;
-#endif
+ Object *target = ObjectDB::get_instance(slot_map.getk(i)._id);
+ if (!target) {
+ // Target might have been deleted during signal callback, this is expected and OK.
+ continue;
+ }
const Variant **args = p_args;
int argc = p_argcount;
@@ -1519,10 +1517,6 @@ void Object::_disconnect(const StringName &p_signal, Object *p_to_object, const
Signal *s = signal_map.getptr(p_signal);
ERR_FAIL_COND_MSG(!s, vformat("Nonexistent signal '%s' in %s.", p_signal, to_string()));
- ERR_FAIL_COND_MSG(s->lock > 0,
- vformat("Attempt to disconnect %s signal '%s' while in emission callback '%s' (in target %s). Use CONNECT_DEFERRED (to be able to safely disconnect) or CONNECT_ONESHOT (for automatic disconnection) as connection flags.",
- to_string(), p_signal, p_to_method, p_to_object->to_string()));
-
Signal::Target target(p_to_object->get_instance_id(), p_to_method);
ERR_FAIL_COND_MSG(!s->slot_map.has(target), "Disconnecting nonexistent signal '" + p_signal + "', slot: " + itos(target._id) + ":" + target.method + ".");
diff --git a/doc/classes/BaseButton.xml b/doc/classes/BaseButton.xml
index 21f46efe84..0128e7b220 100644
--- a/doc/classes/BaseButton.xml
+++ b/doc/classes/BaseButton.xml
@@ -112,6 +112,7 @@
The state of buttons are disabled.
</constant>
<constant name="DRAW_HOVER_PRESSED" value="4" enum="DrawMode">
+ The state of buttons are both hovered and pressed.
</constant>
<constant name="ACTION_MODE_BUTTON_PRESS" value="0" enum="ActionMode">
Require just a press to consider the button clicked.
diff --git a/doc/classes/CollisionObject2D.xml b/doc/classes/CollisionObject2D.xml
index b9ec9480cf..bbc2e44dc0 100644
--- a/doc/classes/CollisionObject2D.xml
+++ b/doc/classes/CollisionObject2D.xml
@@ -44,6 +44,7 @@
<argument index="0" name="owner_id" type="int">
</argument>
<description>
+ Returns the [code]one_way_collision_margin[/code] of the shape owner identified by given [code]owner_id[/code].
</description>
</method>
<method name="get_shape_owners">
@@ -199,6 +200,7 @@
<argument index="1" name="margin" type="float">
</argument>
<description>
+ Sets the [code]one_way_collision_margin[/code] of the shape owner identified by given [code]owner_id[/code] to [code]margin[/code] pixels.
</description>
</method>
<method name="shape_owner_set_transform">
diff --git a/doc/classes/ColorPickerButton.xml b/doc/classes/ColorPickerButton.xml
index e8c78fb6bf..37116b096a 100644
--- a/doc/classes/ColorPickerButton.xml
+++ b/doc/classes/ColorPickerButton.xml
@@ -43,10 +43,12 @@
</signal>
<signal name="picker_created">
<description>
+ Emitted when the [ColorPicker] is created (the button is pressed for the first time).
</description>
</signal>
<signal name="popup_closed">
<description>
+ Emitted when the [ColorPicker] is closed.
</description>
</signal>
</signals>
diff --git a/doc/classes/MainLoop.xml b/doc/classes/MainLoop.xml
index d5ca39e09a..606c898a35 100644
--- a/doc/classes/MainLoop.xml
+++ b/doc/classes/MainLoop.xml
@@ -69,6 +69,7 @@
<argument index="1" name="meta" type="Variant">
</argument>
<description>
+ Called when the user performs an action in the system global menu (e.g. the Mac OS menu bar).
</description>
</method>
<method name="_idle" qualifiers="virtual">
diff --git a/doc/classes/NinePatchRect.xml b/doc/classes/NinePatchRect.xml
index 8935ac9d94..7a7973684d 100644
--- a/doc/classes/NinePatchRect.xml
+++ b/doc/classes/NinePatchRect.xml
@@ -15,6 +15,7 @@
<argument index="0" name="margin" type="int" enum="Margin">
</argument>
<description>
+ Returns the size of the margin identified by the given [enum Margin] constant.
</description>
</method>
<method name="set_patch_margin">
@@ -25,6 +26,7 @@
<argument index="1" name="value" type="int">
</argument>
<description>
+ Sets the size of the margin identified by the given [enum Margin] constant to [code]value[/code] in pixels.
</description>
</method>
</methods>
diff --git a/doc/classes/PoolByteArray.xml b/doc/classes/PoolByteArray.xml
index 867f042cd2..83c348f6be 100644
--- a/doc/classes/PoolByteArray.xml
+++ b/doc/classes/PoolByteArray.xml
@@ -78,6 +78,11 @@
<return type="String">
</return>
<description>
+ Returns a hexadecimal representation of this array as a [String].
+ [codeblock]
+ var array = PoolByteArray([11, 46, 255])
+ print(array.hex_encode()) # Prints: 0b2eff
+ [/codeblock]
</description>
</method>
<method name="insert">
diff --git a/doc/classes/ShaderMaterial.xml b/doc/classes/ShaderMaterial.xml
index ef355c4417..0f39b703ca 100644
--- a/doc/classes/ShaderMaterial.xml
+++ b/doc/classes/ShaderMaterial.xml
@@ -25,6 +25,7 @@
<argument index="0" name="name" type="String">
</argument>
<description>
+ Returns [code]true[/code] if the property identified by [code]name[/code] can be reverted to a default value.
</description>
</method>
<method name="property_get_revert">
@@ -33,6 +34,7 @@
<argument index="0" name="name" type="String">
</argument>
<description>
+ Returns the default value of the material property with given [code]name[/code].
</description>
</method>
<method name="set_shader_param">
diff --git a/doc/classes/SpriteFrames.xml b/doc/classes/SpriteFrames.xml
index f28192519e..2f2075074c 100644
--- a/doc/classes/SpriteFrames.xml
+++ b/doc/classes/SpriteFrames.xml
@@ -170,6 +170,7 @@
</methods>
<members>
<member name="frames" type="Array" setter="_set_frames" getter="_get_frames">
+ Compatibility property, always equals to an empty array.
</member>
</members>
<constants>
diff --git a/doc/classes/StyleBox.xml b/doc/classes/StyleBox.xml
index 1d873ef0b1..1a11904792 100644
--- a/doc/classes/StyleBox.xml
+++ b/doc/classes/StyleBox.xml
@@ -17,18 +17,22 @@
<argument index="1" name="rect" type="Rect2">
</argument>
<description>
+ Draws this stylebox using a [CanvasItem] with given [RID].
+ You can get a [RID] value using [method Object.get_instance_id] on a [CanvasItem]-derived node.
</description>
</method>
<method name="get_center_size" qualifiers="const">
<return type="Vector2">
</return>
<description>
+ Returns the size of this [StyleBox] without the margins.
</description>
</method>
<method name="get_current_item_drawn" qualifiers="const">
<return type="CanvasItem">
</return>
<description>
+ Returns the [CanvasItem] that handles its [constant CanvasItem.NOTIFICATION_DRAW] or [method CanvasItem._draw] callback at this moment.
</description>
</method>
<method name="get_default_margin" qualifiers="const">
@@ -37,6 +41,7 @@
<argument index="0" name="margin" type="int" enum="Margin">
</argument>
<description>
+ Returns the default value of the specified [enum Margin].
</description>
</method>
<method name="get_margin" qualifiers="const">
@@ -45,7 +50,7 @@
<argument index="0" name="margin" type="int" enum="Margin">
</argument>
<description>
- Returns the content margin offset for the specified margin.
+ Returns the content margin offset for the specified [enum Margin].
Positive values reduce size inwards, unlike [Control]'s margin values.
</description>
</method>
@@ -71,6 +76,7 @@
<argument index="1" name="offset" type="float">
</argument>
<description>
+ Sets the default value of the specified [enum Margin] to given [code]offset[/code] in pixels.
</description>
</method>
<method name="test_mask" qualifiers="const">
diff --git a/doc/classes/Thread.xml b/doc/classes/Thread.xml
index 25e40d4c1f..e56ea2325e 100644
--- a/doc/classes/Thread.xml
+++ b/doc/classes/Thread.xml
@@ -50,10 +50,13 @@
</methods>
<constants>
<constant name="PRIORITY_LOW" value="0" enum="Priority">
+ A thread running with lower priority than normally.
</constant>
<constant name="PRIORITY_NORMAL" value="1" enum="Priority">
+ A thread with a standard priority.
</constant>
<constant name="PRIORITY_HIGH" value="2" enum="Priority">
+ A thread running with higher priority than normally.
</constant>
</constants>
</class>
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 0ea8e04471..c5b67eb971 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -369,6 +369,19 @@ void EditorNode::_notification(int p_what) {
case NOTIFICATION_READY: {
+ {
+ _initializing_addons = true;
+ Vector<String> addons;
+ if (ProjectSettings::get_singleton()->has_setting("editor_plugins/enabled")) {
+ addons = ProjectSettings::get_singleton()->get("editor_plugins/enabled");
+ }
+
+ for (int i = 0; i < addons.size(); i++) {
+ set_addon_plugin_enabled(addons[i], true);
+ }
+ _initializing_addons = false;
+ }
+
VisualServer::get_singleton()->viewport_set_hide_scenario(get_scene_root()->get_viewport_rid(), true);
VisualServer::get_singleton()->viewport_set_hide_canvas(get_scene_root()->get_viewport_rid(), true);
VisualServer::get_singleton()->viewport_set_disable_environment(get_viewport()->get_viewport_rid(), true);
@@ -660,12 +673,14 @@ void EditorNode::_sources_changed(bool p_exist) {
if (waiting_for_first_scan) {
waiting_for_first_scan = false;
- EditorResourcePreview::get_singleton()->start(); //start previes now that it's safe
+ // Start preview thread now that it's safe.
+ if (!singleton->cmdline_export_mode) {
+ EditorResourcePreview::get_singleton()->start();
+ }
_load_docks();
if (defer_load_scene != "") {
-
load_scene(defer_load_scene);
defer_load_scene = "";
}
@@ -1155,7 +1170,10 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) {
save.step(TTR("Saving Scene"), 4);
_save_scene(p_file, p_idx);
- EditorResourcePreview::get_singleton()->check_for_invalidation(p_file);
+
+ if (!singleton->cmdline_export_mode) {
+ EditorResourcePreview::get_singleton()->check_for_invalidation(p_file);
+ }
}
bool EditorNode::_validate_scene_recursive(const String &p_filename, Node *p_node) {
@@ -3839,7 +3857,7 @@ Ref<Texture> EditorNode::get_class_icon(const String &p_class, const String &p_f
void EditorNode::progress_add_task(const String &p_task, const String &p_label, int p_steps, bool p_can_cancel) {
- if (singleton->disable_progress_dialog) {
+ if (singleton->cmdline_export_mode) {
print_line(p_task + ": begin: " + p_label + " steps: " + itos(p_steps));
} else {
singleton->progress_dialog->add_task(p_task, p_label, p_steps, p_can_cancel);
@@ -3848,7 +3866,7 @@ void EditorNode::progress_add_task(const String &p_task, const String &p_label,
bool EditorNode::progress_task_step(const String &p_task, const String &p_state, int p_step, bool p_force_refresh) {
- if (singleton->disable_progress_dialog) {
+ if (singleton->cmdline_export_mode) {
print_line("\t" + p_task + ": step " + itos(p_step) + ": " + p_state);
return false;
} else {
@@ -3859,7 +3877,7 @@ bool EditorNode::progress_task_step(const String &p_task, const String &p_state,
void EditorNode::progress_end_task(const String &p_task) {
- if (singleton->disable_progress_dialog) {
+ if (singleton->cmdline_export_mode) {
print_line(p_task + ": end");
} else {
singleton->progress_dialog->end_task(p_task);
@@ -3945,7 +3963,7 @@ Error EditorNode::export_preset(const String &p_preset, const String &p_path, bo
export_defer.path = p_path;
export_defer.debug = p_debug;
export_defer.pack_only = p_pack_only;
- disable_progress_dialog = true;
+ cmdline_export_mode = true;
return OK;
}
@@ -5587,7 +5605,7 @@ EditorNode::EditorNode() {
_initializing_addons = false;
docks_visible = true;
restoring_scenes = false;
- disable_progress_dialog = false;
+ cmdline_export_mode = false;
scene_distraction = false;
script_distraction = false;
@@ -6776,19 +6794,6 @@ EditorNode::EditorNode() {
import_dock->initialize_import_options();
- {
- _initializing_addons = true;
- Vector<String> addons;
- if (ProjectSettings::get_singleton()->has_setting("editor_plugins/enabled")) {
- addons = ProjectSettings::get_singleton()->get("editor_plugins/enabled");
- }
-
- for (int i = 0; i < addons.size(); i++) {
- set_addon_plugin_enabled(addons[i], true);
- }
- _initializing_addons = false;
- }
-
FileAccess::set_file_close_fail_notify_callback(_file_access_close_error_notify);
waiting_for_first_scan = true;
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 7f53f77c76..a5c04d3531 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -561,7 +561,7 @@ private:
bool pack_only;
} export_defer;
- bool disable_progress_dialog;
+ bool cmdline_export_mode;
static EditorNode *singleton;
diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp
index 9d31e26086..f63d4884e2 100644
--- a/editor/editor_resource_preview.cpp
+++ b/editor/editor_resource_preview.cpp
@@ -215,7 +215,6 @@ void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref<
void EditorResourcePreview::_thread() {
-#ifndef SERVER_ENABLED
exited = false;
while (!exit) {
@@ -349,7 +348,6 @@ void EditorResourcePreview::_thread() {
preview_mutex->unlock();
}
}
-#endif
exited = true;
}
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 9223e86f42..e9a705a0dc 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -3987,29 +3987,21 @@ void CanvasItemEditor::_update_scrollbars() {
updating_scroll = true;
- // Move the zoom buttons
+ // Move the zoom buttons.
Point2 controls_vb_begin = Point2(5, 5);
controls_vb_begin += (show_rulers) ? Point2(RULER_WIDTH, RULER_WIDTH) : Point2();
controls_vb->set_begin(controls_vb_begin);
- // Move and resize the scrollbars
- Size2 size = viewport->get_size();
Size2 hmin = h_scroll->get_minimum_size();
Size2 vmin = v_scroll->get_minimum_size();
- v_scroll->set_begin(Point2(size.width - vmin.width, (show_rulers) ? RULER_WIDTH : 0));
- v_scroll->set_end(Point2(size.width, size.height));
-
- h_scroll->set_begin(Point2((show_rulers) ? RULER_WIDTH : 0, size.height - hmin.height));
- h_scroll->set_end(Point2(size.width - vmin.width, size.height));
-
- // Get the visible frame
+ // Get the visible frame.
Size2 screen_rect = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height"));
Rect2 local_rect = Rect2(Point2(), viewport->get_size() - Size2(vmin.width, hmin.height));
_queue_update_bone_list();
- // Calculate scrollable area
+ // Calculate scrollable area.
Rect2 canvas_item_rect = Rect2(Point2(), screen_rect);
if (editor->get_edited_scene()) {
Rect2 content_rect = _get_encompassing_rect(editor->get_edited_scene());
@@ -4019,7 +4011,8 @@ void CanvasItemEditor::_update_scrollbars() {
canvas_item_rect.size += screen_rect * 2;
canvas_item_rect.position -= screen_rect;
- // Constraints the view offset and updates the scrollbars
+ // Constraints the view offset and updates the scrollbars.
+ Size2 size = viewport->get_size();
Point2 begin = canvas_item_rect.position;
Point2 end = canvas_item_rect.position + canvas_item_rect.size - local_rect.size / zoom;
bool constrain_editor_view = bool(EditorSettings::get_singleton()->get("editors/2d/constrain_editor_view"));
@@ -4066,7 +4059,13 @@ void CanvasItemEditor::_update_scrollbars() {
h_scroll->set_page(screen_rect.x);
}
- // Calculate scrollable area
+ // Move and resize the scrollbars, avoiding overlap.
+ v_scroll->set_begin(Point2(size.width - vmin.width, (show_rulers) ? RULER_WIDTH : 0));
+ v_scroll->set_end(Point2(size.width, size.height - (h_scroll->is_visible() ? hmin.height : 0)));
+ h_scroll->set_begin(Point2((show_rulers) ? RULER_WIDTH : 0, size.height - hmin.height));
+ h_scroll->set_end(Point2(size.width - (v_scroll->is_visible() ? vmin.width : 0), size.height));
+
+ // Calculate scrollable area.
v_scroll->set_value(view_offset.y);
h_scroll->set_value(view_offset.x);
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
index de23193df0..dbb2934ffb 100644
--- a/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -1196,7 +1196,9 @@ void Polygon2DEditor::_uv_draw() {
rect.position -= uv_edit_draw->get_size();
rect.size += uv_edit_draw->get_size() * 2.0;
+
updating_uv_scroll = true;
+
uv_hscroll->set_min(rect.position.x);
uv_hscroll->set_max(rect.position.x + rect.size.x);
if (ABS(rect.position.x - (rect.position.x + rect.size.x)) <= uv_edit_draw->get_size().x) {
@@ -1216,6 +1218,14 @@ void Polygon2DEditor::_uv_draw() {
uv_vscroll->set_page(uv_edit_draw->get_size().y);
uv_vscroll->set_value(uv_draw_ofs.y);
}
+
+ Size2 hmin = uv_hscroll->get_combined_minimum_size();
+ Size2 vmin = uv_vscroll->get_combined_minimum_size();
+
+ // Avoid scrollbar overlapping.
+ uv_hscroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, uv_vscroll->is_visible() ? -vmin.width : 0);
+ uv_vscroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, uv_hscroll->is_visible() ? -hmin.height : 0);
+
updating_uv_scroll = false;
}
diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp
index 13faeb0edb..8672e936e0 100644
--- a/editor/plugins/texture_region_editor_plugin.cpp
+++ b/editor/plugins/texture_region_editor_plugin.cpp
@@ -178,6 +178,7 @@ void TextureRegionEditor::_region_draw() {
scroll_rect.size += scroll_margin * 2;
updating_scroll = true;
+
hscroll->set_min(scroll_rect.position.x);
hscroll->set_max(scroll_rect.position.x + scroll_rect.size.x);
if (ABS(scroll_rect.position.x - (scroll_rect.position.x + scroll_rect.size.x)) <= scroll_margin.x) {
@@ -198,6 +199,14 @@ void TextureRegionEditor::_region_draw() {
vscroll->set_page(scroll_margin.y);
vscroll->set_value(draw_ofs.y);
}
+
+ Size2 hmin = hscroll->get_combined_minimum_size();
+ Size2 vmin = vscroll->get_combined_minimum_size();
+
+ // Avoid scrollbar overlapping.
+ hscroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, vscroll->is_visible() ? -vmin.width : 0);
+ vscroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, hscroll->is_visible() ? -hmin.height : 0);
+
updating_scroll = false;
if (node_ninepatch || obj_styleBox.is_valid()) {
diff --git a/main/main.cpp b/main/main.cpp
index 2f92451844..0ff392978a 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -2169,6 +2169,9 @@ void Main::cleanup() {
ScriptServer::finish_languages();
+ // Sync pending commands that may have been queued from a different thread during ScriptServer finalization
+ VisualServer::get_singleton()->sync();
+
#ifdef TOOLS_ENABLED
EditorNode::unregister_editor_types();
#endif
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 3c056fc004..fc2e626795 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -7046,12 +7046,10 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
return_type = _type_from_property(mi.return_val, false);
-#ifdef DEBUG_ENABLED
// Check all arguments beforehand to solve warnings
for (int i = 1; i < p_call->arguments.size(); i++) {
_reduce_node_type(p_call->arguments[i]);
}
-#endif // DEBUG_ENABLED
// Check arguments
@@ -7079,12 +7077,10 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
ERR_FAIL_V(DataType());
}
-#ifdef DEBUG_ENABLED
// Check all arguments beforehand to solve warnings
for (int i = arg_id + 1; i < p_call->arguments.size(); i++) {
_reduce_node_type(p_call->arguments[i]);
}
-#endif // DEBUG_ENABLED
IdentifierNode *func_id = static_cast<IdentifierNode *>(p_call->arguments[arg_id]);
callee_name = func_id->name;
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index d82e78d080..8a024eef13 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -159,6 +159,19 @@ void CSharpLanguage::finish() {
// Clear here, after finalizing all domains to make sure there is nothing else referencing the elements.
script_bindings.clear();
+#ifdef DEBUG_ENABLED
+ for (List<ObjectID>::Element *E = unsafely_referenced_objects.front(); E; E = E->next()) {
+ const ObjectID &id = E->get();
+ Object *obj = ObjectDB::get_instance(id);
+
+ if (obj) {
+ ERR_PRINTS("Leaked unsafe reference to object: " + obj->get_class() + ":" + itos(id));
+ } else {
+ ERR_PRINTS("Leaked unsafe reference to deleted object: " + itos(id));
+ }
+ }
+#endif
+
finalizing = false;
}
@@ -615,6 +628,23 @@ Vector<ScriptLanguage::StackInfo> CSharpLanguage::stack_trace_get_info(MonoObjec
}
#endif
+void CSharpLanguage::post_unsafe_reference(Object *p_obj) {
+#ifdef DEBUG_ENABLED
+ ObjectID id = p_obj->get_instance_id();
+ ERR_FAIL_COND_MSG(unsafely_referenced_objects.find(id), "Multiple unsafe references for object: " + p_obj->get_class() + ":" + itos(id));
+ unsafely_referenced_objects.push_back(id);
+#endif
+}
+
+void CSharpLanguage::pre_unsafe_unreference(Object *p_obj) {
+#ifdef DEBUG_ENABLED
+ ObjectID id = p_obj->get_instance_id();
+ List<ObjectID>::Element *elem = unsafely_referenced_objects.find(id);
+ ERR_FAIL_NULL(elem);
+ unsafely_referenced_objects.erase(elem);
+#endif
+}
+
void CSharpLanguage::frame() {
if (gdmono && gdmono->is_runtime_initialized() && gdmono->get_core_api_assembly() != NULL) {
@@ -1286,6 +1316,7 @@ bool CSharpLanguage::setup_csharp_script_binding(CSharpScriptBinding &r_script_b
// See: godot_icall_Reference_Dtor(MonoObject *p_obj, Object *p_ptr)
ref->reference();
+ CSharpLanguage::get_singleton()->post_unsafe_reference(ref);
}
return true;
@@ -1736,9 +1767,12 @@ bool CSharpInstance::_reference_owner_unsafe() {
// See: _unreference_owner_unsafe()
// May not me referenced yet, so we must use init_ref() instead of reference()
- bool success = Object::cast_to<Reference>(owner)->init_ref();
- unsafe_referenced = success;
- return success;
+ if (static_cast<Reference *>(owner)->init_ref()) {
+ CSharpLanguage::get_singleton()->post_unsafe_reference(owner);
+ unsafe_referenced = true;
+ }
+
+ return unsafe_referenced;
}
bool CSharpInstance::_unreference_owner_unsafe() {
@@ -1759,6 +1793,7 @@ bool CSharpInstance::_unreference_owner_unsafe() {
// See: _reference_owner_unsafe()
// Destroying the owner here means self destructing, so we defer the owner destruction to the caller.
+ CSharpLanguage::get_singleton()->pre_unsafe_unreference(owner);
return static_cast<Reference *>(owner)->unreference();
}
@@ -2243,7 +2278,11 @@ bool CSharpScript::_update_exports() {
MonoException *ctor_exc = NULL;
ctor->invoke(tmp_object, NULL, &ctor_exc);
+ Object *tmp_native = GDMonoMarshal::unbox<Object *>(CACHED_FIELD(GodotObject, ptr)->get_value(tmp_object));
+
if (ctor_exc) {
+ // TODO: Should we free 'tmp_native' if the exception was thrown after its creation?
+
MonoGCHandle::free_handle(tmp_pinned_gchandle);
tmp_object = NULL;
@@ -2322,6 +2361,15 @@ bool CSharpScript::_update_exports() {
MonoGCHandle::free_handle(tmp_pinned_gchandle);
tmp_object = NULL;
+
+ if (tmp_native && !Object::cast_to<Reference>(tmp_native)) {
+ Node *node = Object::cast_to<Node>(tmp_native);
+ if (node && node->is_inside_tree()) {
+ ERR_PRINTS("Temporary instance was added to the scene tree.");
+ } else {
+ memdelete(tmp_native);
+ }
+ }
}
placeholder_fallback_enabled = false;
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 027f429125..30f56e00bd 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -307,6 +307,11 @@ class CSharpLanguage : public ScriptLanguage {
Map<Object *, CSharpScriptBinding> script_bindings;
+#ifdef DEBUG_ENABLED
+ // List of unsafely referenced objects
+ List<ObjectID> unsafely_referenced_objects;
+#endif
+
struct StringNameCache {
StringName _signal_callback;
@@ -458,6 +463,9 @@ public:
Vector<StackInfo> stack_trace_get_info(MonoObject *p_stack_trace);
#endif
+ void post_unsafe_reference(Object *p_obj);
+ void pre_unsafe_unreference(Object *p_obj);
+
CSharpLanguage();
~CSharpLanguage();
};
diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp
index 04a489f1f9..02246b2f2f 100644
--- a/modules/mono/glue/base_object_glue.cpp
+++ b/modules/mono/glue/base_object_glue.cpp
@@ -108,6 +108,7 @@ void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoolea
// Unsafe refcount decrement. The managed instance also counts as a reference.
// See: CSharpLanguage::alloc_instance_binding_data(Object *p_object)
+ CSharpLanguage::get_singleton()->pre_unsafe_unreference(ref);
if (ref->unreference()) {
memdelete(ref);
} else {
diff --git a/modules/mono/mono_gd/gd_mono_internals.cpp b/modules/mono/mono_gd/gd_mono_internals.cpp
index 8669182c4e..75aa77c7b0 100644
--- a/modules/mono/mono_gd/gd_mono_internals.cpp
+++ b/modules/mono/mono_gd/gd_mono_internals.cpp
@@ -83,7 +83,9 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
// See: godot_icall_Reference_Dtor(MonoObject *p_obj, Object *p_ptr)
// May not me referenced yet, so we must use init_ref() instead of reference()
- ref->init_ref();
+ if (ref->init_ref()) {
+ CSharpLanguage::get_singleton()->post_unsafe_reference(ref);
+ }
}
// The object was just created, no script instance binding should have been attached
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index 3c8aa0c727..6bb9f28a32 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -115,6 +115,7 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) {
// but the managed instance is alive, the refcount will be 1 instead of 0.
// See: godot_icall_Reference_Dtor(MonoObject *p_obj, Object *p_ptr)
ref->reference();
+ CSharpLanguage::get_singleton()->post_unsafe_reference(ref);
}
return mono_object;
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index 4bfd4f48ce..ec20698ae8 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -575,7 +575,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
Button *btn = memnew(Button);
btn->set_text(TTR("Add Input Port"));
hbnc->add_child(btn);
- btn->connect("pressed", this, "_add_input_port", varray(E->get()));
+ btn->connect("pressed", this, "_add_input_port", varray(E->get()), CONNECT_DEFERRED);
}
if (nd_list->is_output_port_editable()) {
if (nd_list->is_input_port_editable())
@@ -584,7 +584,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
Button *btn = memnew(Button);
btn->set_text(TTR("Add Output Port"));
hbnc->add_child(btn);
- btn->connect("pressed", this, "_add_output_port", varray(E->get()));
+ btn->connect("pressed", this, "_add_output_port", varray(E->get()), CONNECT_DEFERRED);
}
gnode->add_child(hbnc);
} else if (Object::cast_to<VisualScriptExpression>(node.ptr())) {
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 2b002d3b5d..6a214b8669 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -479,7 +479,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
}
- (NSRange)markedRange {
- return (markedText.length > 0) ? NSMakeRange(0, markedText.length - 1) : kEmptyRange;
+ return NSMakeRange(0, markedText.length);
}
- (NSRange)selectedRange {
@@ -492,6 +492,10 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
} else {
[markedText initWithString:aString];
}
+ if (markedText.length == 0) {
+ [self unmarkText];
+ return;
+ }
if (OS_OSX::singleton->im_active) {
imeInputEventInProgress = true;
OS_OSX::singleton->im_text.parse_utf8([[markedText mutableString] UTF8String]);
diff --git a/scene/gui/center_container.cpp b/scene/gui/center_container.cpp
index 9f4353ceb6..64d6885bc8 100644
--- a/scene/gui/center_container.cpp
+++ b/scene/gui/center_container.cpp
@@ -54,7 +54,13 @@ Size2 CenterContainer::get_minimum_size() const {
void CenterContainer::set_use_top_left(bool p_enable) {
+ if (use_top_left == p_enable) {
+ return;
+ }
+
use_top_left = p_enable;
+
+ minimum_size_changed();
queue_sort();
}
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index be465751b6..42bb8023f2 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -200,6 +200,13 @@ void GraphEdit::_update_scroll() {
else
v_scroll->show();
+ Size2 hmin = h_scroll->get_combined_minimum_size();
+ Size2 vmin = v_scroll->get_combined_minimum_size();
+
+ // Avoid scrollbar overlapping.
+ h_scroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, v_scroll->is_visible() ? -vmin.width : 0);
+ v_scroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, h_scroll->is_visible() ? -hmin.height : 0);
+
set_block_minimum_size_adjust(false);
if (!awaiting_scroll_offset_update) {