Rework CanvasItem visibility propagation

This commit is contained in:
kobewi 2022-02-06 00:26:28 +01:00
parent 9d1626b4d7
commit ab5b5e1577
2 changed files with 37 additions and 47 deletions

View File

@ -56,43 +56,19 @@ Transform2D CanvasItem::_edit_get_transform() const {
#endif #endif
bool CanvasItem::is_visible_in_tree() const { bool CanvasItem::is_visible_in_tree() const {
if (!is_inside_tree()) { return visible && visible_in_tree;
return false;
}
const CanvasItem *p = this;
while (p) {
if (!p->visible) {
return false;
}
if (p->window && !p->window->is_visible()) {
return false;
}
p = p->get_parent_item();
}
const Node *n = get_parent();
while (n) {
const CanvasLayer *c = Object::cast_to<CanvasLayer>(n);
if (c && !c->is_visible()) {
return false;
}
n = n->get_parent();
}
return true;
} }
void CanvasItem::_propagate_visibility_changed(bool p_visible) { void CanvasItem::_propagate_visibility_changed(bool p_visible, bool p_was_visible) {
if (p_visible && first_draw) { //avoid propagating it twice if (p_visible && first_draw) { //avoid propagating it twice
first_draw = false; first_draw = false;
} }
visible_in_tree = p_visible;
notification(NOTIFICATION_VISIBILITY_CHANGED); notification(NOTIFICATION_VISIBILITY_CHANGED);
if (p_visible) { if (visible && p_visible) {
update(); //todo optimize update();
} else { } else if (!p_visible && (visible || p_was_visible)) {
emit_signal(SceneStringNames::get_singleton()->hidden); emit_signal(SceneStringNames::get_singleton()->hidden);
} }
_block(); _block();
@ -120,7 +96,7 @@ void CanvasItem::set_visible(bool p_visible) {
return; return;
} }
_propagate_visibility_changed(p_visible); _propagate_visibility_changed(p_visible, !p_visible);
} }
void CanvasItem::show() { void CanvasItem::show() {
@ -148,7 +124,7 @@ void CanvasItem::_update_callback() {
RenderingServer::get_singleton()->canvas_item_clear(get_canvas_item()); RenderingServer::get_singleton()->canvas_item_clear(get_canvas_item());
//todo updating = true - only allow drawing here //todo updating = true - only allow drawing here
if (is_visible_in_tree()) { //todo optimize this!! if (is_visible_in_tree()) {
if (first_draw) { if (first_draw) {
notification(NOTIFICATION_VISIBILITY_CHANGED); notification(NOTIFICATION_VISIBILITY_CHANGED);
first_draw = false; first_draw = false;
@ -282,32 +258,44 @@ void CanvasItem::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: { case NOTIFICATION_ENTER_TREE: {
ERR_FAIL_COND(!is_inside_tree()); ERR_FAIL_COND(!is_inside_tree());
first_draw = true; first_draw = true;
Node *parent = get_parent(); Node *parent = get_parent();
if (parent) { if (parent) {
CanvasItem *ci = Object::cast_to<CanvasItem>(parent); CanvasItem *ci = Object::cast_to<CanvasItem>(parent);
if (ci) { if (ci) {
visible_in_tree = ci->is_visible_in_tree();
C = ci->children_items.push_back(this); C = ci->children_items.push_back(this);
} } else {
if (!ci) { CanvasLayer *cl = Object::cast_to<CanvasLayer>(parent);
//look for a window
Viewport *viewport = nullptr;
while (parent) { if (cl) {
viewport = Object::cast_to<Viewport>(parent); visible_in_tree = cl->is_visible();
if (viewport) { } else {
break; // 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); window = Object::cast_to<Window>(viewport);
if (window) { if (window) {
window->connect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed)); window->connect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed));
visible_in_tree = window->is_visible();
} else {
visible_in_tree = true;
}
} }
} }
} }
_enter_canvas(); _enter_canvas();
_update_texture_filter_changed(false); _update_texture_filter_changed(false);
@ -344,6 +332,7 @@ void CanvasItem::_notification(int p_what) {
window->disconnect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed)); window->disconnect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed));
} }
global_invalid = true; global_invalid = true;
visible_in_tree = false;
} break; } break;
case NOTIFICATION_DRAW: case NOTIFICATION_DRAW:
case NOTIFICATION_TRANSFORM_CHANGED: { case NOTIFICATION_TRANSFORM_CHANGED: {

View File

@ -87,6 +87,7 @@ private:
Window *window = nullptr; Window *window = nullptr;
bool first_draw = false; bool first_draw = false;
bool visible = true; bool visible = true;
bool visible_in_tree = false;
bool clip_children = false; bool clip_children = false;
bool pending_update = false; bool pending_update = false;
bool top_level = false; bool top_level = false;
@ -109,7 +110,7 @@ private:
void _top_level_raise_self(); void _top_level_raise_self();
void _propagate_visibility_changed(bool p_visible); void _propagate_visibility_changed(bool p_visible, bool p_was_visible = false);
void _update_callback(); void _update_callback();