diff --git a/doc/classes/TreeItem.xml b/doc/classes/TreeItem.xml index 66a42d4bb4f..96d216ec4af 100644 --- a/doc/classes/TreeItem.xml +++ b/doc/classes/TreeItem.xml @@ -438,6 +438,12 @@ Returns [code]true[/code] if the given [param column] is selected. + + + + Returns [code]true[/code] if [member visible] is [code]true[/code] and all its ancestors are also visible. + + diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index bf456cd0485..fd1117b1a2a 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -680,7 +680,7 @@ bool TreeItem::_is_any_collapsed(bool p_only_visible) { } bool TreeItem::is_any_collapsed(bool p_only_visible) { - if (p_only_visible && !is_visible()) { + if (p_only_visible && !is_visible_in_tree()) { return false; } @@ -701,12 +701,31 @@ void TreeItem::set_visible(bool p_visible) { tree->queue_redraw(); _changed_notify(); } + + _handle_visibility_changed(p_visible); } bool TreeItem::is_visible() { return visible; } +bool TreeItem::is_visible_in_tree() const { + return visible && parent_visible_in_tree; +} + +void TreeItem::_handle_visibility_changed(bool p_visible) { + TreeItem *child = get_first_child(); + while (child) { + child->_propagate_visibility_changed(p_visible); + child = child->get_next(); + } +} + +void TreeItem::_propagate_visibility_changed(bool p_parent_visible_in_tree) { + parent_visible_in_tree = p_parent_visible_in_tree; + _handle_visibility_changed(p_parent_visible_in_tree); +} + void TreeItem::uncollapse_tree() { TreeItem *t = this; while (t) { @@ -777,6 +796,7 @@ TreeItem *TreeItem::create_child(int p_index) { } ti->parent = this; + ti->parent_visible_in_tree = is_visible_in_tree(); return ti; } @@ -788,6 +808,8 @@ void TreeItem::add_child(TreeItem *p_item) { p_item->_change_tree(tree); p_item->parent = this; + p_item->parent_visible_in_tree = is_visible_in_tree(); + p_item->_handle_visibility_changed(p_item->parent_visible_in_tree); TreeItem *item_prev = first_child; while (item_prev && item_prev->next) { @@ -895,7 +917,7 @@ TreeItem *TreeItem::_get_prev_in_tree(bool p_wrap, bool p_include_invisible) { TreeItem *TreeItem::get_prev_visible(bool p_wrap) { TreeItem *loop = this; TreeItem *prev_item = _get_prev_in_tree(p_wrap); - while (prev_item && !prev_item->is_visible()) { + while (prev_item && !prev_item->is_visible_in_tree()) { prev_item = prev_item->_get_prev_in_tree(p_wrap); if (prev_item == loop) { // Check that we haven't looped all the way around to the start. @@ -936,7 +958,7 @@ TreeItem *TreeItem::_get_next_in_tree(bool p_wrap, bool p_include_invisible) { TreeItem *TreeItem::get_next_visible(bool p_wrap) { TreeItem *loop = this; TreeItem *next_item = _get_next_in_tree(p_wrap); - while (next_item && !next_item->is_visible()) { + while (next_item && !next_item->is_visible_in_tree()) { next_item = next_item->_get_next_in_tree(p_wrap); if (next_item == loop) { // Check that we haven't looped all the way around to the start. @@ -1630,6 +1652,7 @@ void TreeItem::_bind_methods() { ClassDB::bind_method(D_METHOD("set_visible", "enable"), &TreeItem::set_visible); ClassDB::bind_method(D_METHOD("is_visible"), &TreeItem::is_visible); + ClassDB::bind_method(D_METHOD("is_visible_in_tree"), &TreeItem::is_visible_in_tree); ClassDB::bind_method(D_METHOD("uncollapse_tree"), &TreeItem::uncollapse_tree); @@ -1779,7 +1802,7 @@ Size2 Tree::_get_cell_icon_size(const TreeItem::Cell &p_cell) const { } int Tree::compute_item_height(TreeItem *p_item) const { - if ((p_item == root && hide_root) || !p_item->is_visible()) { + if ((p_item == root && hide_root) || !p_item->is_visible_in_tree()) { return 0; } @@ -1837,7 +1860,7 @@ int Tree::compute_item_height(TreeItem *p_item) const { } int Tree::get_item_height(TreeItem *p_item) const { - if (!p_item->is_visible()) { + if (!p_item->is_visible_in_tree()) { return 0; } int height = compute_item_height(p_item); @@ -2028,7 +2051,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 return -1; //draw no more! } - if (!p_item->is_visible()) { + if (!p_item->is_visible_in_tree()) { return 0; } @@ -2485,7 +2508,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 } // Draw relationship lines. - if (theme_cache.draw_relationship_lines > 0 && (!hide_root || c->parent != root) && c->is_visible()) { + if (theme_cache.draw_relationship_lines > 0 && (!hide_root || c->parent != root) && c->is_visible_in_tree()) { int root_ofs = children_pos.x + ((p_item->disable_folding || hide_folding) ? theme_cache.h_separation : theme_cache.item_margin); int parent_ofs = p_pos.x + theme_cache.item_margin; Point2i root_pos = Point2i(root_ofs, children_pos.y + child_self_height / 2) - theme_cache.offset + p_draw_ofs; @@ -2766,7 +2789,7 @@ void Tree::_range_click_timeout() { } int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int x_limit, bool p_double_click, TreeItem *p_item, MouseButton p_button, const Ref &p_mod) { - if (p_item && !p_item->is_visible()) { + if (p_item && !p_item->is_visible_in_tree()) { // Skip any processing of invisible items. return 0; } @@ -4775,7 +4798,7 @@ int Tree::get_item_offset(TreeItem *p_item) const { return ofs; } - if ((it != root || !hide_root) && it->is_visible()) { + if ((it != root || !hide_root) && it->is_visible_in_tree()) { ofs += compute_item_height(it); ofs += theme_cache.v_separation; } @@ -5148,7 +5171,7 @@ void Tree::_do_incr_search(const String &p_add) { TreeItem *Tree::_find_item_at_pos(TreeItem *p_item, const Point2 &p_pos, int &r_column, int &h, int §ion) const { Point2 pos = p_pos; - if ((root != p_item || !hide_root) && p_item->is_visible()) { + if ((root != p_item || !hide_root) && p_item->is_visible_in_tree()) { h = compute_item_height(p_item) + theme_cache.v_separation; if (pos.y < h) { if (drop_mode_flags == DROP_MODE_ON_ITEM) { @@ -5181,7 +5204,7 @@ TreeItem *Tree::_find_item_at_pos(TreeItem *p_item, const Point2 &p_pos, int &r_ h = 0; } - if (p_item->is_collapsed() || !p_item->is_visible()) { + if (p_item->is_collapsed() || !p_item->is_visible_in_tree()) { return nullptr; // do not try children, it's collapsed } diff --git a/scene/gui/tree.h b/scene/gui/tree.h index ee5f0d420ba..e921486714b 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -128,6 +128,7 @@ private: bool collapsed = false; // won't show children bool visible = true; + bool parent_visible_in_tree = true; bool disable_folding = false; int custom_min_height = 0; @@ -146,6 +147,8 @@ private: void _changed_notify(); void _cell_selected(int p_cell); void _cell_deselected(int p_cell); + void _handle_visibility_changed(bool p_visible); + void _propagate_visibility_changed(bool p_parent_visible_in_tree); void _change_tree(Tree *p_tree); @@ -299,6 +302,7 @@ public: void set_visible(bool p_visible); bool is_visible(); + bool is_visible_in_tree() const; void uncollapse_tree();