Bladeren bron

Allow TreeItem nodes to toggle visibility

monkeyman192 3 jaren geleden
bovenliggende
commit
31381f8c9e
3 gewijzigde bestanden met toevoegingen van 90 en 8 verwijderingen
  1. 4 0
      doc/classes/TreeItem.xml
  2. 78 8
      scene/gui/tree.cpp
  3. 8 0
      scene/gui/tree.h

+ 4 - 0
doc/classes/TreeItem.xml

@@ -687,6 +687,10 @@
 		<member name="disable_folding" type="bool" setter="set_disable_folding" getter="is_folding_disabled">
 			If [code]true[/code], folding is disabled for this TreeItem.
 		</member>
+		<member name="visible" type="bool" setter="set_visible" getter="is_visible">
+			If [code]true[/code], the [TreeItem] is visible (default).
+			Note that if a [TreeItem] is set to not be visible, none of its children will be visible either.
+		</member>
 	</members>
 	<constants>
 		<constant name="CELL_MODE_STRING" value="0" enum="TreeCellMode">

+ 78 - 8
scene/gui/tree.cpp

@@ -544,6 +544,21 @@ bool TreeItem::is_collapsed() {
 	return collapsed;
 }
 
+void TreeItem::set_visible(bool p_visible) {
+	if (visible == p_visible) {
+		return;
+	}
+	visible = p_visible;
+	if (tree) {
+		tree->update();
+		_changed_notify();
+	}
+}
+
+bool TreeItem::is_visible() {
+	return visible;
+}
+
 void TreeItem::uncollapse_tree() {
 	TreeItem *t = this;
 	while (t) {
@@ -646,7 +661,7 @@ TreeItem *TreeItem::get_first_child() const {
 	return first_child;
 }
 
-TreeItem *TreeItem::get_prev_visible(bool p_wrap) {
+TreeItem *TreeItem::_get_prev_visible(bool p_wrap) {
 	TreeItem *current = this;
 
 	TreeItem *prev = current->get_prev();
@@ -682,7 +697,21 @@ TreeItem *TreeItem::get_prev_visible(bool p_wrap) {
 	return current;
 }
 
-TreeItem *TreeItem::get_next_visible(bool p_wrap) {
+TreeItem *TreeItem::get_prev_visible(bool p_wrap) {
+	TreeItem *loop = this;
+	TreeItem *prev = this->_get_prev_visible(p_wrap);
+	while (prev && !prev->is_visible()) {
+		prev = prev->_get_prev_visible(p_wrap);
+		if (prev == loop) {
+			// Check that we haven't looped all the way around to the start.
+			prev = nullptr;
+			break;
+		}
+	}
+	return prev;
+}
+
+TreeItem *TreeItem::_get_next_visible(bool p_wrap) {
 	TreeItem *current = this;
 
 	if (!current->collapsed && current->first_child) {
@@ -709,12 +738,37 @@ TreeItem *TreeItem::get_next_visible(bool p_wrap) {
 	return current;
 }
 
+TreeItem *TreeItem::get_next_visible(bool p_wrap) {
+	TreeItem *loop = this;
+	TreeItem *next = this->_get_next_visible(p_wrap);
+	while (next && !next->is_visible()) {
+		next = next->_get_next_visible(p_wrap);
+		if (next == loop) {
+			// Check that we haven't looped all the way around to the start.
+			next = nullptr;
+			break;
+		}
+	}
+	return next;
+}
+
 TreeItem *TreeItem::get_child(int p_idx) {
 	_create_children_cache();
 	ERR_FAIL_INDEX_V(p_idx, children_cache.size(), nullptr);
 	return children_cache.get(p_idx);
 }
 
+int TreeItem::get_visible_child_count() {
+	_create_children_cache();
+	int visible_count = 0;
+	for (int i = 0; i < children_cache.size(); i++) {
+		if (children_cache[i]->is_visible()) {
+			visible_count += 1;
+		}
+	}
+	return visible_count;
+}
+
 int TreeItem::get_child_count() {
 	_create_children_cache();
 	return children_cache.size();
@@ -1256,6 +1310,9 @@ void TreeItem::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_collapsed", "enable"), &TreeItem::set_collapsed);
 	ClassDB::bind_method(D_METHOD("is_collapsed"), &TreeItem::is_collapsed);
 
+	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("uncollapse_tree"), &TreeItem::uncollapse_tree);
 
 	ClassDB::bind_method(D_METHOD("set_custom_minimum_height", "height"), &TreeItem::set_custom_minimum_height);
@@ -1340,6 +1397,7 @@ void TreeItem::_bind_methods() {
 	}
 
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collapsed"), "set_collapsed", "is_collapsed");
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_folding"), "set_disable_folding", "is_folding_disabled");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "custom_minimum_height", PROPERTY_HINT_RANGE, "0,1000,1"), "set_custom_minimum_height", "get_custom_minimum_height");
 
@@ -1445,7 +1503,7 @@ void Tree::update_cache() {
 }
 
 int Tree::compute_item_height(TreeItem *p_item) const {
-	if (p_item == root && hide_root) {
+	if ((p_item == root && hide_root) || !p_item->is_visible()) {
 		return 0;
 	}
 
@@ -1506,6 +1564,9 @@ int Tree::compute_item_height(TreeItem *p_item) const {
 }
 
 int Tree::get_item_height(TreeItem *p_item) const {
+	if (!p_item->is_visible()) {
+		return 0;
+	}
 	int height = compute_item_height(p_item);
 	height += cache.vseparation;
 
@@ -1686,6 +1747,10 @@ 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()) {
+		return 0;
+	}
+
 	RID ci = get_canvas_item();
 
 	int htotal = 0;
@@ -2056,7 +2121,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
 			}
 		}
 
-		if (!p_item->disable_folding && !hide_folding && p_item->first_child) { //has children, draw the guide box
+		if (!p_item->disable_folding && !hide_folding && p_item->first_child && p_item->get_visible_child_count() != 0) { //has visible children, draw the guide box
 
 			Ref<Texture2D> arrow;
 
@@ -2382,6 +2447,11 @@ 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<InputEventWithModifiers> &p_mod) {
+	if (p_item && !p_item->is_visible()) {
+		// Skip any processing of invisible items.
+		return 0;
+	}
+
 	int item_h = compute_item_height(p_item) + cache.vseparation;
 
 	bool skip = (p_item == root && hide_root);
@@ -4147,7 +4217,7 @@ int Tree::get_column_minimum_width(int p_column) const {
 					depth += 1;
 				} else {
 					TreeItem *common_parent = item->get_parent();
-					while (common_parent != next->get_parent()) {
+					while (common_parent != next->get_parent() && common_parent) {
 						common_parent = common_parent->get_parent();
 						depth -= 1;
 					}
@@ -4464,7 +4534,7 @@ Point2 Tree::get_scroll() const {
 }
 
 void Tree::scroll_to_item(TreeItem *p_item, bool p_center_on_item) {
-	if (!is_visible_in_tree()) {
+	if (!is_visible_in_tree() || !p_item->is_visible()) {
 		return; // Hack to work around crash in get_item_rect() if Tree is not in tree.
 	}
 
@@ -4588,7 +4658,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 &section) const {
 	Point2 pos = p_pos;
 
-	if (root != p_item || !hide_root) {
+	if ((root != p_item || !hide_root) && p_item->is_visible()) {
 		h = compute_item_height(p_item) + cache.vseparation;
 		if (pos.y < h) {
 			if (drop_mode_flags == DROP_MODE_ON_ITEM) {
@@ -4621,7 +4691,7 @@ TreeItem *Tree::_find_item_at_pos(TreeItem *p_item, const Point2 &p_pos, int &r_
 		h = 0;
 	}
 
-	if (p_item->is_collapsed()) {
+	if (p_item->is_collapsed() || !p_item->is_visible()) {
 		return nullptr; // do not try children, it's collapsed
 	}
 

+ 8 - 0
scene/gui/tree.h

@@ -124,6 +124,7 @@ private:
 	Vector<Cell> cells;
 
 	bool collapsed = false; // won't show children
+	bool visible = true;
 	bool disable_folding = false;
 	int custom_min_height = 0;
 
@@ -209,6 +210,9 @@ private:
 	void _propagate_check_through_children(int p_column, bool p_checked, bool p_emit_signal);
 	void _propagate_check_through_parents(int p_column, bool p_emit_signal);
 
+	TreeItem *_get_prev_visible(bool p_wrap = false);
+	TreeItem *_get_next_visible(bool p_wrap = false);
+
 public:
 	void set_text(int p_column, String p_text);
 	String get_text(int p_column) const;
@@ -273,6 +277,9 @@ public:
 	void set_collapsed(bool p_collapsed);
 	bool is_collapsed();
 
+	void set_visible(bool p_visible);
+	bool is_visible();
+
 	void uncollapse_tree();
 
 	void set_custom_minimum_height(int p_height);
@@ -335,6 +342,7 @@ public:
 	TreeItem *get_next_visible(bool p_wrap = false);
 
 	TreeItem *get_child(int p_idx);
+	int get_visible_child_count();
 	int get_child_count();
 	Array get_children();
 	int get_index();