diff options
author | Juan Linietsky <reduzio@gmail.com> | 2023-05-12 13:53:15 +0200 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2023-05-15 16:54:10 +0200 |
commit | 0a9f72d5a80c8957ef5172f546c9076089862cef (patch) | |
tree | 250a57d39630efd1a290efd897d11a838dd53867 /scene/main/canvas_item.cpp | |
parent | fd4a06c51555904104b18494d0224f450d74fe2a (diff) | |
download | redot-engine-0a9f72d5a80c8957ef5172f546c9076089862cef.tar.gz |
Make more base nodes thread safe
Ongoing work to make more of the base nodes thread safe.
Diffstat (limited to 'scene/main/canvas_item.cpp')
-rw-r--r-- | scene/main/canvas_item.cpp | 134 |
1 files changed, 124 insertions, 10 deletions
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index cb115a6d94..6c8bd08915 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -56,6 +56,7 @@ Transform2D CanvasItem::_edit_get_transform() const { #endif bool CanvasItem::is_visible_in_tree() const { + ERR_READ_THREAD_GUARD_V(false); return visible && parent_visible_in_tree; } @@ -69,6 +70,7 @@ void CanvasItem::_propagate_visibility_changed(bool p_parent_visible_in_tree) { } void CanvasItem::set_visible(bool p_visible) { + ERR_MAIN_THREAD_GUARD; if (visible == p_visible) { return; } @@ -105,14 +107,17 @@ void CanvasItem::_handle_visibility_change(bool p_visible) { } void CanvasItem::show() { + ERR_MAIN_THREAD_GUARD; set_visible(true); } void CanvasItem::hide() { + ERR_MAIN_THREAD_GUARD; set_visible(false); } bool CanvasItem::is_visible() const { + ERR_READ_THREAD_GUARD_V(false); return visible; } @@ -143,10 +148,11 @@ void CanvasItem::_redraw_callback() { } void CanvasItem::_invalidate_global_transform() { - global_invalid = true; + global_invalid.set(); } Transform2D CanvasItem::get_global_transform_with_canvas() const { + ERR_READ_THREAD_GUARD_V(Transform2D()); if (canvas_layer) { return canvas_layer->get_final_transform() * get_global_transform(); } else if (is_inside_tree()) { @@ -157,20 +163,26 @@ Transform2D CanvasItem::get_global_transform_with_canvas() const { } Transform2D CanvasItem::get_screen_transform() const { + ERR_READ_THREAD_GUARD_V(Transform2D()); ERR_FAIL_COND_V(!is_inside_tree(), Transform2D()); return get_viewport()->get_popup_base_transform() * get_global_transform_with_canvas(); } Transform2D CanvasItem::get_global_transform() const { - if (global_invalid) { + ERR_READ_THREAD_GUARD_V(Transform2D()); + + if (global_invalid.is_set()) { + // This code can enter multiple times from threads if dirty, this is expected. const CanvasItem *pi = get_parent_item(); + Transform2D new_global; if (pi) { - global_transform = pi->get_global_transform() * get_transform(); + new_global = pi->get_global_transform() * get_transform(); } else { - global_transform = get_transform(); + new_global = get_transform(); } - global_invalid = false; + global_transform = new_global; + global_invalid.clear(); } return global_transform; @@ -253,6 +265,8 @@ void CanvasItem::_exit_canvas() { } void CanvasItem::_notification(int p_what) { + ERR_MAIN_THREAD_GUARD; + switch (p_what) { case NOTIFICATION_ENTER_TREE: { ERR_FAIL_COND(!is_inside_tree()); @@ -294,7 +308,7 @@ void CanvasItem::_notification(int p_what) { } } - global_invalid = true; + global_invalid.set(); _enter_canvas(); RenderingServer::get_singleton()->canvas_item_set_visible(canvas_item, is_visible_in_tree()); // The visibility of the parent may change. @@ -327,7 +341,7 @@ void CanvasItem::_notification(int p_what) { window->disconnect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed)); window = nullptr; } - global_invalid = true; + global_invalid.set(); parent_visible_in_tree = false; if (get_viewport()) { @@ -346,6 +360,8 @@ void CanvasItem::_notification(int p_what) { } void CanvasItem::update_draw_order() { + ERR_MAIN_THREAD_GUARD; + if (!is_inside_tree()) { return; } @@ -363,6 +379,7 @@ void CanvasItem::_window_visibility_changed() { } void CanvasItem::queue_redraw() { + ERR_THREAD_GUARD; // Calling from thread is safe. if (!is_inside_tree()) { return; } @@ -376,6 +393,7 @@ void CanvasItem::queue_redraw() { } void CanvasItem::move_to_front() { + ERR_MAIN_THREAD_GUARD; if (!get_parent()) { return; } @@ -383,6 +401,7 @@ void CanvasItem::move_to_front() { } void CanvasItem::set_modulate(const Color &p_modulate) { + ERR_THREAD_GUARD; if (modulate == p_modulate) { return; } @@ -392,10 +411,12 @@ void CanvasItem::set_modulate(const Color &p_modulate) { } Color CanvasItem::get_modulate() const { + ERR_READ_THREAD_GUARD_V(Color()); return modulate; } Color CanvasItem::get_modulate_in_tree() const { + ERR_READ_THREAD_GUARD_V(Color()); Color final_modulate = modulate; CanvasItem *parent_item = get_parent_item(); while (parent_item) { @@ -406,6 +427,7 @@ Color CanvasItem::get_modulate_in_tree() const { } void CanvasItem::set_as_top_level(bool p_top_level) { + ERR_MAIN_THREAD_GUARD; if (top_level == p_top_level) { return; } @@ -445,6 +467,7 @@ bool CanvasItem::is_set_as_top_level() const { } CanvasItem *CanvasItem::get_parent_item() const { + ERR_READ_THREAD_GUARD_V(nullptr); if (top_level) { return nullptr; } @@ -453,6 +476,7 @@ CanvasItem *CanvasItem::get_parent_item() const { } void CanvasItem::set_self_modulate(const Color &p_self_modulate) { + ERR_THREAD_GUARD; if (self_modulate == p_self_modulate) { return; } @@ -462,10 +486,12 @@ void CanvasItem::set_self_modulate(const Color &p_self_modulate) { } Color CanvasItem::get_self_modulate() const { + ERR_READ_THREAD_GUARD_V(Color()); return self_modulate; } void CanvasItem::set_light_mask(int p_light_mask) { + ERR_THREAD_GUARD; if (light_mask == p_light_mask) { return; } @@ -475,10 +501,12 @@ void CanvasItem::set_light_mask(int p_light_mask) { } int CanvasItem::get_light_mask() const { + ERR_READ_THREAD_GUARD_V(0); return light_mask; } void CanvasItem::item_rect_changed(bool p_size_changed) { + ERR_MAIN_THREAD_GUARD; if (p_size_changed) { queue_redraw(); } @@ -486,6 +514,7 @@ void CanvasItem::item_rect_changed(bool p_size_changed) { } void CanvasItem::set_z_index(int p_z) { + ERR_THREAD_GUARD; ERR_FAIL_COND(p_z < RS::CANVAS_ITEM_Z_MIN); ERR_FAIL_COND(p_z > RS::CANVAS_ITEM_Z_MAX); z_index = p_z; @@ -494,6 +523,7 @@ void CanvasItem::set_z_index(int p_z) { } void CanvasItem::set_z_as_relative(bool p_enabled) { + ERR_THREAD_GUARD; if (z_relative == p_enabled) { return; } @@ -502,14 +532,17 @@ void CanvasItem::set_z_as_relative(bool p_enabled) { } bool CanvasItem::is_z_relative() const { + ERR_READ_THREAD_GUARD_V(false); return z_relative; } int CanvasItem::get_z_index() const { + ERR_READ_THREAD_GUARD_V(0); return z_index; } int CanvasItem::get_effective_z_index() const { + ERR_READ_THREAD_GUARD_V(0); int effective_z_index = z_index; if (is_z_relative()) { CanvasItem *p = get_parent_item(); @@ -521,15 +554,18 @@ int CanvasItem::get_effective_z_index() const { } void CanvasItem::set_y_sort_enabled(bool p_enabled) { + ERR_THREAD_GUARD; y_sort_enabled = p_enabled; RS::get_singleton()->canvas_item_set_sort_children_by_y(canvas_item, y_sort_enabled); } bool CanvasItem::is_y_sort_enabled() const { + ERR_READ_THREAD_GUARD_V(false); return y_sort_enabled; } void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, real_t p_dash, bool p_aligned) { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL_COND(p_dash <= 0.0); @@ -565,12 +601,14 @@ void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, cons } void CanvasItem::draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, bool p_antialiased) { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width, p_antialiased); } void CanvasItem::draw_polyline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width, bool p_antialiased) { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); Vector<Color> colors = { p_color }; @@ -578,12 +616,14 @@ void CanvasItem::draw_polyline(const Vector<Point2> &p_points, const Color &p_co } void CanvasItem::draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width, bool p_antialiased) { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); RenderingServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, p_colors, p_width, p_antialiased); } void CanvasItem::draw_arc(const Vector2 &p_center, real_t p_radius, real_t p_start_angle, real_t p_end_angle, int p_point_count, const Color &p_color, real_t p_width, bool p_antialiased) { + ERR_THREAD_GUARD; Vector<Point2> points; points.resize(p_point_count); Point2 *points_ptr = points.ptrw(); @@ -599,6 +639,7 @@ void CanvasItem::draw_arc(const Vector2 &p_center, real_t p_radius, real_t p_sta } void CanvasItem::draw_multiline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width) { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); Vector<Color> colors = { p_color }; @@ -606,12 +647,14 @@ void CanvasItem::draw_multiline(const Vector<Point2> &p_points, const Color &p_c } void CanvasItem::draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width) { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, p_colors, p_width); } void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled, real_t p_width) { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); Rect2 rect = p_rect.abs(); @@ -640,12 +683,14 @@ void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_fil } void CanvasItem::draw_circle(const Point2 &p_pos, real_t p_radius, const Color &p_color) { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); RenderingServer::get_singleton()->canvas_item_add_circle(canvas_item, p_pos, p_radius, p_color); } void CanvasItem::draw_texture(const Ref<Texture2D> &p_texture, const Point2 &p_pos, const Color &p_modulate) { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL_COND(p_texture.is_null()); @@ -654,6 +699,7 @@ void CanvasItem::draw_texture(const Ref<Texture2D> &p_texture, const Point2 &p_p } void CanvasItem::draw_texture_rect(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL_COND(p_texture.is_null()); @@ -661,24 +707,28 @@ void CanvasItem::draw_texture_rect(const Ref<Texture2D> &p_texture, const Rect2 } void CanvasItem::draw_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL_COND(p_texture.is_null()); p_texture->draw_rect_region(canvas_item, p_rect, p_src_rect, p_modulate, p_transpose, p_clip_uv); } void CanvasItem::draw_msdf_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, double p_outline, double p_pixel_range, double p_scale) { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL_COND(p_texture.is_null()); RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(canvas_item, p_rect, p_texture->get_rid(), p_src_rect, p_modulate, p_outline, p_pixel_range, p_scale); } void CanvasItem::draw_lcd_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate) { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL_COND(p_texture.is_null()); RenderingServer::get_singleton()->canvas_item_add_lcd_texture_rect_region(canvas_item, p_rect, p_texture->get_rid(), p_src_rect, p_modulate); } void CanvasItem::draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p_rect) { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL_COND(p_style_box.is_null()); @@ -687,6 +737,7 @@ void CanvasItem::draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p } void CanvasItem::draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture) { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); RID rid = p_texture.is_valid() ? p_texture->get_rid() : RID(); @@ -694,6 +745,7 @@ void CanvasItem::draw_primitive(const Vector<Point2> &p_points, const Vector<Col } void CanvasItem::draw_set_transform(const Point2 &p_offset, real_t p_rot, const Size2 &p_scale) { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); Transform2D xform(p_rot, p_offset); @@ -702,23 +754,27 @@ void CanvasItem::draw_set_transform(const Point2 &p_offset, real_t p_rot, const } void CanvasItem::draw_set_transform_matrix(const Transform2D &p_matrix) { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); RenderingServer::get_singleton()->canvas_item_add_set_transform(canvas_item, p_matrix); } void CanvasItem::draw_animation_slice(double p_animation_length, double p_slice_begin, double p_slice_end, double p_offset) { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); RenderingServer::get_singleton()->canvas_item_add_animation_slice(canvas_item, p_animation_length, p_slice_begin, p_slice_end, p_offset); } void CanvasItem::draw_end_animation() { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); RenderingServer::get_singleton()->canvas_item_add_animation_slice(canvas_item, 1, 0, 2, 0); } void CanvasItem::draw_polygon(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture) { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); RID rid = p_texture.is_valid() ? p_texture->get_rid() : RID(); @@ -727,6 +783,7 @@ void CanvasItem::draw_polygon(const Vector<Point2> &p_points, const Vector<Color } void CanvasItem::draw_colored_polygon(const Vector<Point2> &p_points, const Color &p_color, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture) { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); Vector<Color> colors = { p_color }; @@ -735,6 +792,7 @@ void CanvasItem::draw_colored_polygon(const Vector<Point2> &p_points, const Colo } void CanvasItem::draw_mesh(const Ref<Mesh> &p_mesh, const Ref<Texture2D> &p_texture, const Transform2D &p_transform, const Color &p_modulate) { + ERR_THREAD_GUARD; ERR_FAIL_COND(p_mesh.is_null()); RID texture_rid = p_texture.is_valid() ? p_texture->get_rid() : RID(); @@ -742,12 +800,14 @@ void CanvasItem::draw_mesh(const Ref<Mesh> &p_mesh, const Ref<Texture2D> &p_text } void CanvasItem::draw_multimesh(const Ref<MultiMesh> &p_multimesh, const Ref<Texture2D> &p_texture) { + ERR_THREAD_GUARD; ERR_FAIL_COND(p_multimesh.is_null()); RID texture_rid = p_texture.is_valid() ? p_texture->get_rid() : RID(); RenderingServer::get_singleton()->canvas_item_add_multimesh(canvas_item, p_multimesh->get_rid(), texture_rid); } void CanvasItem::draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, const Color &p_modulate, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL_COND(p_font.is_null()); @@ -755,6 +815,7 @@ void CanvasItem::draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const } void CanvasItem::draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, const Color &p_modulate, BitField<TextServer::LineBreakFlag> p_brk_flags, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL_COND(p_font.is_null()); @@ -762,6 +823,7 @@ void CanvasItem::draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_ } void CanvasItem::draw_string_outline(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_size, const Color &p_modulate, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL_COND(p_font.is_null()); @@ -769,6 +831,7 @@ void CanvasItem::draw_string_outline(const Ref<Font> &p_font, const Point2 &p_po } void CanvasItem::draw_multiline_string_outline(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, int p_size, const Color &p_modulate, BitField<TextServer::LineBreakFlag> p_brk_flags, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL_COND(p_font.is_null()); @@ -776,6 +839,7 @@ void CanvasItem::draw_multiline_string_outline(const Ref<Font> &p_font, const Po } void CanvasItem::draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, int p_font_size, const Color &p_modulate) const { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL_COND(p_char.length() != 1); ERR_FAIL_COND(p_font.is_null()); @@ -784,6 +848,7 @@ void CanvasItem::draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const S } void CanvasItem::draw_char_outline(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, int p_font_size, int p_size, const Color &p_modulate) const { + ERR_THREAD_GUARD; ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL_COND(p_char.length() != 1); ERR_FAIL_COND(p_font.is_null()); @@ -791,6 +856,12 @@ void CanvasItem::draw_char_outline(const Ref<Font> &p_font, const Point2 &p_pos, p_font->draw_char_outline(canvas_item, p_pos, p_char[0], p_font_size, p_size, p_modulate); } +void CanvasItem::_notify_transform_deferred() { + if (is_inside_tree() && notify_transform && !xform_change.in_list()) { + get_tree()->xform_change_list.add(&xform_change); + } +} + void CanvasItem::_notify_transform(CanvasItem *p_node) { /* This check exists to avoid re-propagating the transform * notification down the tree on dirty nodes. It provides @@ -798,16 +869,21 @@ void CanvasItem::_notify_transform(CanvasItem *p_node) { * notification anyway). */ - if (/*p_node->xform_change.in_list() &&*/ p_node->global_invalid) { + if (/*p_node->xform_change.in_list() &&*/ p_node->global_invalid.is_set()) { return; //nothing to do } - p_node->global_invalid = true; + p_node->global_invalid.set(); if (p_node->notify_transform && !p_node->xform_change.in_list()) { if (!p_node->block_transform_notify) { if (p_node->is_inside_tree()) { - get_tree()->xform_change_list.add(&p_node->xform_change); + if (is_accessible_from_caller_thread()) { + get_tree()->xform_change_list.add(&p_node->xform_change); + } else { + // Should be rare, but still needs to be handled. + MessageQueue::get_singleton()->push_callable(callable_mp(p_node, &CanvasItem::_notify_transform_deferred)); + } } } } @@ -821,11 +897,13 @@ void CanvasItem::_notify_transform(CanvasItem *p_node) { } Rect2 CanvasItem::get_viewport_rect() const { + ERR_READ_THREAD_GUARD_V(Rect2()); ERR_FAIL_COND_V(!is_inside_tree(), Rect2()); return get_viewport()->get_visible_rect(); } RID CanvasItem::get_canvas() const { + ERR_READ_THREAD_GUARD_V(RID()); ERR_FAIL_COND_V(!is_inside_tree(), RID()); if (canvas_layer) { @@ -836,6 +914,7 @@ RID CanvasItem::get_canvas() const { } ObjectID CanvasItem::get_canvas_layer_instance_id() const { + ERR_READ_THREAD_GUARD_V(ObjectID()); if (canvas_layer) { return canvas_layer->get_instance_id(); } else { @@ -844,6 +923,7 @@ ObjectID CanvasItem::get_canvas_layer_instance_id() const { } CanvasItem *CanvasItem::get_top_level() const { + ERR_READ_THREAD_GUARD_V(nullptr); CanvasItem *ci = const_cast<CanvasItem *>(this); while (!ci->top_level && Object::cast_to<CanvasItem>(ci->get_parent())) { ci = Object::cast_to<CanvasItem>(ci->get_parent()); @@ -853,6 +933,7 @@ CanvasItem *CanvasItem::get_top_level() const { } Ref<World2D> CanvasItem::get_world_2d() const { + ERR_READ_THREAD_GUARD_V(Ref<World2D>()); ERR_FAIL_COND_V(!is_inside_tree(), Ref<World2D>()); CanvasItem *tl = get_top_level(); @@ -865,19 +946,23 @@ Ref<World2D> CanvasItem::get_world_2d() const { } RID CanvasItem::get_viewport_rid() const { + ERR_READ_THREAD_GUARD_V(RID()); ERR_FAIL_COND_V(!is_inside_tree(), RID()); return get_viewport()->get_viewport_rid(); } void CanvasItem::set_block_transform_notify(bool p_enable) { + ERR_THREAD_GUARD; block_transform_notify = p_enable; } bool CanvasItem::is_block_transform_notify_enabled() const { + ERR_READ_THREAD_GUARD_V(false); return block_transform_notify; } void CanvasItem::set_draw_behind_parent(bool p_enable) { + ERR_THREAD_GUARD; if (behind == p_enable) { return; } @@ -886,10 +971,12 @@ void CanvasItem::set_draw_behind_parent(bool p_enable) { } bool CanvasItem::is_draw_behind_parent_enabled() const { + ERR_READ_THREAD_GUARD_V(false); return behind; } void CanvasItem::set_material(const Ref<Material> &p_material) { + ERR_THREAD_GUARD; material = p_material; RID rid; if (material.is_valid()) { @@ -900,19 +987,23 @@ void CanvasItem::set_material(const Ref<Material> &p_material) { } void CanvasItem::set_use_parent_material(bool p_use_parent_material) { + ERR_THREAD_GUARD; use_parent_material = p_use_parent_material; RS::get_singleton()->canvas_item_set_use_parent_material(canvas_item, p_use_parent_material); } bool CanvasItem::get_use_parent_material() const { + ERR_READ_THREAD_GUARD_V(false); return use_parent_material; } Ref<Material> CanvasItem::get_material() const { + ERR_READ_THREAD_GUARD_V(Ref<Material>()); return material; } Vector2 CanvasItem::make_canvas_position_local(const Vector2 &screen_point) const { + ERR_READ_THREAD_GUARD_V(Vector2()); ERR_FAIL_COND_V(!is_inside_tree(), screen_point); Transform2D local_matrix = (get_canvas_transform() * get_global_transform()).affine_inverse(); @@ -921,6 +1012,7 @@ Vector2 CanvasItem::make_canvas_position_local(const Vector2 &screen_point) cons } Ref<InputEvent> CanvasItem::make_input_local(const Ref<InputEvent> &p_event) const { + ERR_READ_THREAD_GUARD_V(Ref<InputEvent>()); ERR_FAIL_COND_V(p_event.is_null(), p_event); ERR_FAIL_COND_V(!is_inside_tree(), p_event); @@ -928,17 +1020,20 @@ Ref<InputEvent> CanvasItem::make_input_local(const Ref<InputEvent> &p_event) con } Vector2 CanvasItem::get_global_mouse_position() const { + ERR_READ_THREAD_GUARD_V(Vector2()); ERR_FAIL_COND_V(!get_viewport(), Vector2()); return get_canvas_transform().affine_inverse().xform(get_viewport()->get_mouse_position()); } Vector2 CanvasItem::get_local_mouse_position() const { + ERR_READ_THREAD_GUARD_V(Vector2()); ERR_FAIL_COND_V(!get_viewport(), Vector2()); return get_global_transform().affine_inverse().xform(get_global_mouse_position()); } void CanvasItem::force_update_transform() { + ERR_THREAD_GUARD; ERR_FAIL_COND(!is_inside_tree()); if (!xform_change.in_list()) { return; @@ -1148,6 +1243,7 @@ void CanvasItem::_bind_methods() { } Transform2D CanvasItem::get_canvas_transform() const { + ERR_READ_THREAD_GUARD_V(Transform2D()); ERR_FAIL_COND_V(!is_inside_tree(), Transform2D()); if (canvas_layer) { @@ -1160,6 +1256,7 @@ Transform2D CanvasItem::get_canvas_transform() const { } Transform2D CanvasItem::get_viewport_transform() const { + ERR_READ_THREAD_GUARD_V(Transform2D()); ERR_FAIL_COND_V(!is_inside_tree(), Transform2D()); if (canvas_layer) { @@ -1170,14 +1267,17 @@ Transform2D CanvasItem::get_viewport_transform() const { } void CanvasItem::set_notify_local_transform(bool p_enable) { + ERR_THREAD_GUARD; notify_local_transform = p_enable; } bool CanvasItem::is_local_transform_notification_enabled() const { + ERR_READ_THREAD_GUARD_V(false); return notify_local_transform; } void CanvasItem::set_notify_transform(bool p_enable) { + ERR_THREAD_GUARD; if (notify_transform == p_enable) { return; } @@ -1191,10 +1291,12 @@ void CanvasItem::set_notify_transform(bool p_enable) { } bool CanvasItem::is_transform_notification_enabled() const { + ERR_READ_THREAD_GUARD_V(false); return notify_transform; } int CanvasItem::get_canvas_layer() const { + ERR_READ_THREAD_GUARD_V(0); if (canvas_layer) { return canvas_layer->get_layer(); } else { @@ -1203,15 +1305,18 @@ int CanvasItem::get_canvas_layer() const { } void CanvasItem::set_visibility_layer(uint32_t p_visibility_layer) { + ERR_THREAD_GUARD; visibility_layer = p_visibility_layer; RenderingServer::get_singleton()->canvas_item_set_visibility_layer(canvas_item, p_visibility_layer); } uint32_t CanvasItem::get_visibility_layer() const { + ERR_READ_THREAD_GUARD_V(0); return visibility_layer; } void CanvasItem::set_visibility_layer_bit(uint32_t p_visibility_layer, bool p_enable) { + ERR_THREAD_GUARD; ERR_FAIL_UNSIGNED_INDEX(p_visibility_layer, 32); if (p_enable) { set_visibility_layer(visibility_layer | (1 << p_visibility_layer)); @@ -1221,6 +1326,7 @@ void CanvasItem::set_visibility_layer_bit(uint32_t p_visibility_layer, bool p_en } bool CanvasItem::get_visibility_layer_bit(uint32_t p_visibility_layer) const { + ERR_READ_THREAD_GUARD_V(0); ERR_FAIL_UNSIGNED_INDEX_V(p_visibility_layer, 32, false); return (visibility_layer & (1 << p_visibility_layer)); } @@ -1261,6 +1367,7 @@ void CanvasItem::_update_texture_filter_changed(bool p_propagate) { } void CanvasItem::set_texture_filter(TextureFilter p_texture_filter) { + ERR_MAIN_THREAD_GUARD; // Goes down in the tree, so only main thread can set. ERR_FAIL_INDEX(p_texture_filter, TEXTURE_FILTER_MAX); if (texture_filter == p_texture_filter) { return; @@ -1271,6 +1378,7 @@ void CanvasItem::set_texture_filter(TextureFilter p_texture_filter) { } CanvasItem::TextureFilter CanvasItem::get_texture_filter() const { + ERR_READ_THREAD_GUARD_V(TEXTURE_FILTER_NEAREST); return texture_filter; } @@ -1309,6 +1417,7 @@ void CanvasItem::_update_texture_repeat_changed(bool p_propagate) { } void CanvasItem::set_texture_repeat(TextureRepeat p_texture_repeat) { + ERR_MAIN_THREAD_GUARD; // Goes down in the tree, so only main thread can set. ERR_FAIL_INDEX(p_texture_repeat, TEXTURE_REPEAT_MAX); if (texture_repeat == p_texture_repeat) { return; @@ -1319,6 +1428,7 @@ void CanvasItem::set_texture_repeat(TextureRepeat p_texture_repeat) { } void CanvasItem::set_clip_children_mode(ClipChildrenMode p_clip_mode) { + ERR_THREAD_GUARD; ERR_FAIL_COND(p_clip_mode >= CLIP_CHILDREN_MAX); if (clip_children_mode == p_clip_mode) { @@ -1334,19 +1444,23 @@ void CanvasItem::set_clip_children_mode(ClipChildrenMode p_clip_mode) { RS::get_singleton()->canvas_item_set_canvas_group_mode(get_canvas_item(), RS::CanvasGroupMode(clip_children_mode)); } CanvasItem::ClipChildrenMode CanvasItem::get_clip_children_mode() const { + ERR_READ_THREAD_GUARD_V(CLIP_CHILDREN_DISABLED); return clip_children_mode; } CanvasItem::TextureRepeat CanvasItem::get_texture_repeat() const { + ERR_READ_THREAD_GUARD_V(TEXTURE_REPEAT_DISABLED); return texture_repeat; } CanvasItem::TextureFilter CanvasItem::get_texture_filter_in_tree() { + ERR_READ_THREAD_GUARD_V(TEXTURE_FILTER_NEAREST); _refresh_texture_filter_cache(); return (TextureFilter)texture_filter_cache; } CanvasItem::TextureRepeat CanvasItem::get_texture_repeat_in_tree() { + ERR_READ_THREAD_GUARD_V(TEXTURE_REPEAT_DISABLED); _refresh_texture_repeat_cache(); return (TextureRepeat)texture_repeat_cache; } |