ソースを参照

Fix CanvasItem visibility propagation

kobewi 3 年 前
コミット
3a77484f70

+ 1 - 1
editor/plugins/canvas_item_editor_plugin.cpp

@@ -3510,7 +3510,7 @@ void CanvasItemEditor::_draw_invisible_nodes_positions(Node *p_node, const Trans
 		return;
 	}
 	CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
-	if (canvas_item && !canvas_item->is_visible()) {
+	if (canvas_item && !canvas_item->is_visible_in_tree()) {
 		return;
 	}
 

+ 21 - 14
scene/main/canvas_item.cpp

@@ -56,19 +56,21 @@ Transform2D CanvasItem::_edit_get_transform() const {
 #endif
 
 bool CanvasItem::is_visible_in_tree() const {
-	return visible && visible_in_tree;
+	return visible && parent_visible_in_tree;
 }
 
-void CanvasItem::_propagate_visibility_changed(bool p_visible, bool p_was_visible) {
-	if (p_visible && first_draw) { //avoid propagating it twice
+void CanvasItem::_propagate_visibility_changed(bool p_visible, bool p_is_source) {
+	if (p_visible && first_draw) { // Avoid propagating it twice.
 		first_draw = false;
 	}
-	visible_in_tree = p_visible;
+	if (!p_is_source) {
+		parent_visible_in_tree = p_visible;
+	}
 	notification(NOTIFICATION_VISIBILITY_CHANGED);
 
 	if (visible && p_visible) {
 		update();
-	} else if (!p_visible && (visible || p_was_visible)) {
+	} else if (!p_visible && (visible || p_is_source)) {
 		emit_signal(SceneStringNames::get_singleton()->hidden);
 	}
 	_block();
@@ -76,8 +78,12 @@ void CanvasItem::_propagate_visibility_changed(bool p_visible, bool p_was_visibl
 	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..
-			c->_propagate_visibility_changed(p_visible);
+		if (c) { // Should the top_levels stop propagation? I think so, but...
+			if (c->visible) {
+				c->_propagate_visibility_changed(p_visible);
+			} else {
+				c->parent_visible_in_tree = p_visible;
+			}
 		}
 	}
 
@@ -92,11 +98,12 @@ void CanvasItem::set_visible(bool p_visible) {
 	visible = p_visible;
 	RenderingServer::get_singleton()->canvas_item_set_visible(canvas_item, p_visible);
 
-	if (!is_inside_tree()) {
+	if (!parent_visible_in_tree) {
+		notification(NOTIFICATION_VISIBILITY_CHANGED);
 		return;
 	}
 
-	_propagate_visibility_changed(p_visible, !p_visible);
+	_propagate_visibility_changed(p_visible, true);
 }
 
 void CanvasItem::show() {
@@ -264,13 +271,13 @@ void CanvasItem::_notification(int p_what) {
 				CanvasItem *ci = Object::cast_to<CanvasItem>(parent);
 
 				if (ci) {
-					visible_in_tree = ci->is_visible_in_tree();
+					parent_visible_in_tree = ci->is_visible_in_tree();
 					C = ci->children_items.push_back(this);
 				} else {
 					CanvasLayer *cl = Object::cast_to<CanvasLayer>(parent);
 
 					if (cl) {
-						visible_in_tree = cl->is_visible();
+						parent_visible_in_tree = cl->is_visible();
 					} else {
 						// Look for a window.
 						Viewport *viewport = nullptr;
@@ -288,9 +295,9 @@ void CanvasItem::_notification(int p_what) {
 						window = Object::cast_to<Window>(viewport);
 						if (window) {
 							window->connect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed));
-							visible_in_tree = window->is_visible();
+							parent_visible_in_tree = window->is_visible();
 						} else {
-							visible_in_tree = true;
+							parent_visible_in_tree = true;
 						}
 					}
 				}
@@ -333,7 +340,7 @@ void CanvasItem::_notification(int p_what) {
 				window->disconnect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed));
 			}
 			global_invalid = true;
-			visible_in_tree = false;
+			parent_visible_in_tree = false;
 		} break;
 
 		case NOTIFICATION_VISIBILITY_CHANGED: {

+ 2 - 2
scene/main/canvas_item.h

@@ -85,7 +85,7 @@ private:
 	Window *window = nullptr;
 	bool first_draw = false;
 	bool visible = true;
-	bool visible_in_tree = false;
+	bool parent_visible_in_tree = false;
 	bool clip_children = false;
 	bool pending_update = false;
 	bool top_level = false;
@@ -108,7 +108,7 @@ private:
 
 	void _top_level_raise_self();
 
-	void _propagate_visibility_changed(bool p_visible, bool p_was_visible = false);
+	void _propagate_visibility_changed(bool p_visible, bool p_is_source = false);
 
 	void _update_callback();
 

+ 1 - 1
scene/main/canvas_layer.cpp

@@ -61,7 +61,7 @@ void CanvasLayer::set_visible(bool p_visible) {
 			if (c->is_visible()) {
 				c->_propagate_visibility_changed(p_visible);
 			} else {
-				c->notification(CanvasItem::NOTIFICATION_VISIBILITY_CHANGED);
+				c->parent_visible_in_tree = p_visible;
 			}
 		}
 	}