diff options
Diffstat (limited to 'scene/main/canvas_item.cpp')
-rw-r--r-- | scene/main/canvas_item.cpp | 173 |
1 files changed, 89 insertions, 84 deletions
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index c80665cf2e..b50f7866af 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -56,77 +56,67 @@ Transform2D CanvasItem::_edit_get_transform() const { #endif bool CanvasItem::is_visible_in_tree() const { - if (!is_inside_tree()) { - return false; + return visible && parent_visible_in_tree; +} + +void CanvasItem::_propagate_visibility_changed(bool p_parent_visible_in_tree) { + parent_visible_in_tree = p_parent_visible_in_tree; + if (!visible) { + return; + } + if (p_parent_visible_in_tree && first_draw) { // Avoid propagating it twice. + first_draw = false; } - const CanvasItem *p = this; + _handle_visibility_change(p_parent_visible_in_tree); +} - while (p) { - if (!p->visible) { - return false; - } - if (p->window && !p->window->is_visible()) { - return false; - } - p = p->get_parent_item(); +void CanvasItem::set_visible(bool p_visible) { + if (visible == p_visible) { + return; } - return true; -} + visible = p_visible; -void CanvasItem::_propagate_visibility_changed(bool p_visible) { - if (p_visible && first_draw) { //avoid propagating it twice - first_draw = false; + if (!parent_visible_in_tree) { + notification(NOTIFICATION_VISIBILITY_CHANGED); + return; } + + _handle_visibility_change(p_visible); +} + +void CanvasItem::_handle_visibility_change(bool p_visible) { + RenderingServer::get_singleton()->canvas_item_set_visible(canvas_item, p_visible); notification(NOTIFICATION_VISIBILITY_CHANGED); if (p_visible) { - update(); //todo optimize + update(); } else { emit_signal(SceneStringNames::get_singleton()->hidden); } - _block(); + _block(); for (int i = 0; i < get_child_count(); i++) { CanvasItem *c = Object::cast_to<CanvasItem>(get_child(i)); - if (c && c->visible) { //should the top_levels stop propagation? i think so but.. + if (c) { // Should the top_levels stop propagation? I think so, but... c->_propagate_visibility_changed(p_visible); } } - _unblock(); } void CanvasItem::show() { - if (visible) { - return; - } - - visible = true; - RenderingServer::get_singleton()->canvas_item_set_visible(canvas_item, true); - - if (!is_inside_tree()) { - return; - } - - _propagate_visibility_changed(true); + set_visible(true); } void CanvasItem::hide() { - if (!visible) { - return; - } - - visible = false; - RenderingServer::get_singleton()->canvas_item_set_visible(canvas_item, false); - - if (!is_inside_tree()) { - return; - } + set_visible(false); +} - _propagate_visibility_changed(false); +bool CanvasItem::is_visible() const { + return visible; } CanvasItem *CanvasItem::current_item_drawn = nullptr; @@ -142,7 +132,7 @@ void CanvasItem::_update_callback() { RenderingServer::get_singleton()->canvas_item_clear(get_canvas_item()); //todo updating = true - only allow drawing here - if (is_visible_in_tree()) { //todo optimize this!! + if (is_visible_in_tree()) { if (first_draw) { notification(NOTIFICATION_VISIBILITY_CHANGED); first_draw = false; @@ -276,32 +266,44 @@ void CanvasItem::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { ERR_FAIL_COND(!is_inside_tree()); first_draw = true; + Node *parent = get_parent(); if (parent) { CanvasItem *ci = Object::cast_to<CanvasItem>(parent); + if (ci) { + parent_visible_in_tree = ci->is_visible_in_tree(); C = ci->children_items.push_back(this); - } - if (!ci) { - //look for a window - Viewport *viewport = nullptr; - - while (parent) { - viewport = Object::cast_to<Viewport>(parent); - if (viewport) { - break; + } else { + CanvasLayer *cl = Object::cast_to<CanvasLayer>(parent); + + if (cl) { + parent_visible_in_tree = cl->is_visible(); + } else { + // Look for a window. + Viewport *viewport = nullptr; + + while (parent) { + viewport = Object::cast_to<Viewport>(parent); + if (viewport) { + break; + } + parent = parent->get_parent(); } - parent = parent->get_parent(); - } - ERR_FAIL_COND(!viewport); + ERR_FAIL_COND(!viewport); - window = Object::cast_to<Window>(viewport); - if (window) { - window->connect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed)); + window = Object::cast_to<Window>(viewport); + if (window) { + window->connect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed)); + parent_visible_in_tree = window->is_visible(); + } else { + parent_visible_in_tree = true; + } } } } + _enter_canvas(); _update_texture_filter_changed(false); @@ -311,6 +313,7 @@ void CanvasItem::_notification(int p_what) { get_tree()->xform_change_list.add(&xform_change); } } break; + case NOTIFICATION_MOVED_IN_PARENT: { if (!is_inside_tree()) { break; @@ -323,8 +326,8 @@ void CanvasItem::_notification(int p_what) { ERR_FAIL_COND(!p); RenderingServer::get_singleton()->canvas_item_set_draw_index(canvas_item, get_index()); } - } break; + case NOTIFICATION_EXIT_TREE: { if (xform_change.in_list()) { get_tree()->xform_change_list.remove(&xform_change); @@ -338,34 +341,21 @@ void CanvasItem::_notification(int p_what) { window->disconnect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed)); } global_invalid = true; + parent_visible_in_tree = false; } break; - case NOTIFICATION_DRAW: - case NOTIFICATION_TRANSFORM_CHANGED: { - } break; + case NOTIFICATION_VISIBILITY_CHANGED: { emit_signal(SceneStringNames::get_singleton()->visibility_changed); } break; } } -void CanvasItem::set_visible(bool p_visible) { - if (p_visible) { - show(); - } else { - hide(); - } -} - void CanvasItem::_window_visibility_changed() { if (visible) { _propagate_visibility_changed(window->is_visible()); } } -bool CanvasItem::is_visible() const { - return visible; -} - void CanvasItem::update() { if (!is_inside_tree()) { return; @@ -454,6 +444,25 @@ void CanvasItem::item_rect_changed(bool p_size_changed) { emit_signal(SceneStringNames::get_singleton()->item_rect_changed); } +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) { + ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); + + float length = (p_to - p_from).length(); + if (length < p_dash) { + RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width); + return; + } + + Point2 off = p_from; + Vector2 step = p_dash * (p_to - p_from).normalized(); + int steps = length / p_dash / 2; + for (int i = 0; i < steps; i++) { + RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, off, (off + step), p_color, p_width); + off += 2 * step; + } + RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, off, p_to, p_color, p_width); +} + void CanvasItem::draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width) { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); @@ -876,9 +885,9 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_on_top", "on_top"), &CanvasItem::_set_on_top); ClassDB::bind_method(D_METHOD("_is_on_top"), &CanvasItem::_is_on_top); - //ClassDB::bind_method(D_METHOD("get_transform"),&CanvasItem::get_transform); ClassDB::bind_method(D_METHOD("draw_line", "from", "to", "color", "width"), &CanvasItem::draw_line, DEFVAL(1.0)); + ClassDB::bind_method(D_METHOD("draw_dashed_line", "from", "to", "color", "width", "dash"), &CanvasItem::draw_dashed_line, DEFVAL(1.0), DEFVAL(2.0)); ClassDB::bind_method(D_METHOD("draw_polyline", "points", "color", "width", "antialiased"), &CanvasItem::draw_polyline, DEFVAL(1.0), DEFVAL(false)); ClassDB::bind_method(D_METHOD("draw_polyline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_polyline_colors, DEFVAL(1.0), DEFVAL(false)); ClassDB::bind_method(D_METHOD("draw_arc", "center", "radius", "start_angle", "end_angle", "point_count", "color", "width", "antialiased"), &CanvasItem::draw_arc, DEFVAL(1.0), DEFVAL(false)); @@ -909,6 +918,7 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("get_viewport_transform"), &CanvasItem::get_viewport_transform); ClassDB::bind_method(D_METHOD("get_viewport_rect"), &CanvasItem::get_viewport_rect); ClassDB::bind_method(D_METHOD("get_canvas_transform"), &CanvasItem::get_canvas_transform); + ClassDB::bind_method(D_METHOD("get_screen_transform"), &CanvasItem::get_screen_transform); ClassDB::bind_method(D_METHOD("get_local_mouse_position"), &CanvasItem::get_local_mouse_position); ClassDB::bind_method(D_METHOD("get_global_mouse_position"), &CanvasItem::get_global_mouse_position); ClassDB::bind_method(D_METHOD("get_canvas"), &CanvasItem::get_canvas); @@ -1005,12 +1015,7 @@ Transform2D CanvasItem::get_viewport_transform() const { ERR_FAIL_COND_V(!is_inside_tree(), Transform2D()); if (canvas_layer) { - if (get_viewport()) { - return get_viewport()->get_final_transform() * canvas_layer->get_transform(); - } else { - return canvas_layer->get_transform(); - } - + return get_viewport()->get_final_transform() * canvas_layer->get_transform(); } else { return get_viewport()->get_final_transform() * get_viewport()->get_canvas_transform(); } @@ -1032,8 +1037,8 @@ void CanvasItem::set_notify_transform(bool p_enable) { notify_transform = p_enable; if (notify_transform && is_inside_tree()) { - //this ensures that invalid globals get resolved, so notifications can be received - get_global_transform(); + // This ensures that invalid globals get resolved, so notifications can be received. + _ALLOW_DISCARD_ get_global_transform(); } } |