Browse Source

Merge pull request #98560 from Koyper/tree_relationship_line_fix

[Tree] Fix relationship lines 1px width draw bug when MSAA anti aliasing is enabled
Thaddeus Crews 4 months ago
parent
commit
8aaae4f4f3
2 changed files with 25 additions and 18 deletions
  1. 24 18
      scene/gui/tree.cpp
  2. 1 0
      scene/gui/tree.h

+ 24 - 18
scene/gui/tree.cpp

@@ -2722,8 +2722,8 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
 		TreeItem *c = p_item->first_child;
 		TreeItem *c = p_item->first_child;
 
 
 		int base_ofs = children_pos.y - theme_cache.offset.y + p_draw_ofs.y;
 		int base_ofs = children_pos.y - theme_cache.offset.y + p_draw_ofs.y;
-		int prev_ofs = base_ofs;
-		int prev_hl_ofs = base_ofs;
+		float prev_ofs = base_ofs;
+		float prev_hl_ofs = base_ofs;
 
 
 		while (c) {
 		while (c) {
 			int child_h = -1;
 			int child_h = -1;
@@ -2736,10 +2736,10 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
 			// Draw relationship lines.
 			// Draw relationship lines.
 			if (theme_cache.draw_relationship_lines > 0 && (!hide_root || c->parent != root) && c->is_visible_in_tree()) {
 			if (theme_cache.draw_relationship_lines > 0 && (!hide_root || c->parent != root) && c->is_visible_in_tree()) {
 				int parent_ofs = p_pos.x + theme_cache.item_margin;
 				int parent_ofs = p_pos.x + theme_cache.item_margin;
-				Point2i parent_pos = Point2i(parent_ofs - theme_cache.arrow->get_width() / 2, p_pos.y + label_h / 2 + theme_cache.arrow->get_height() / 2) - theme_cache.offset + p_draw_ofs;
+				Point2i parent_pos = Point2i(parent_ofs - theme_cache.arrow->get_width() * 0.5, p_pos.y + label_h * 0.5 + theme_cache.arrow->get_height() * 0.5) - theme_cache.offset + p_draw_ofs;
 
 
 				int root_ofs = children_pos.x + ((p_item->disable_folding || hide_folding) ? theme_cache.h_separation : theme_cache.item_margin);
 				int root_ofs = children_pos.x + ((p_item->disable_folding || hide_folding) ? theme_cache.h_separation : theme_cache.item_margin);
-				Point2i root_pos = Point2i(root_ofs, children_pos.y + child_self_height / 2) - theme_cache.offset + p_draw_ofs;
+				Point2i root_pos = Point2i(root_ofs, children_pos.y + child_self_height * 0.5) - theme_cache.offset + p_draw_ofs;
 				if (!hide_folding && !p_item->disable_folding && c->get_visible_child_count() > 0) {
 				if (!hide_folding && !p_item->disable_folding && c->get_visible_child_count() > 0) {
 					root_pos -= Point2i(theme_cache.arrow->get_width(), 0);
 					root_pos -= Point2i(theme_cache.arrow->get_width(), 0);
 				}
 				}
@@ -2751,6 +2751,10 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
 				float parent_line_width = theme_cache.parent_hl_line_width * Math::round(theme_cache.base_scale);
 				float parent_line_width = theme_cache.parent_hl_line_width * Math::round(theme_cache.base_scale);
 				float children_line_width = theme_cache.children_hl_line_width * Math::round(theme_cache.base_scale);
 				float children_line_width = theme_cache.children_hl_line_width * Math::round(theme_cache.base_scale);
 
 
+				float line_pixel_shift = int(Math::round(line_width * content_scale_factor)) % 2 == 0 ? 0.0 : 0.5;
+				float parent_line_pixel_shift = int(Math::round(parent_line_width * content_scale_factor)) % 2 == 0 ? 0.0 : 0.5;
+				float children_line_pixel_shift = int(Math::round(children_line_width * content_scale_factor)) % 2 == 0 ? 0.0 : 0.5;
+
 				int more_prev_ofs = 0;
 				int more_prev_ofs = 0;
 
 
 				if (root_pos.y + line_width >= 0) {
 				if (root_pos.y + line_width >= 0) {
@@ -2758,37 +2762,38 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
 						root_pos.x = get_size().width - root_pos.x;
 						root_pos.x = get_size().width - root_pos.x;
 						parent_pos.x = get_size().width - parent_pos.x;
 						parent_pos.x = get_size().width - parent_pos.x;
 					}
 					}
+					float parent_bottom_y = root_pos.y + parent_line_width * 0.5 + parent_line_pixel_shift;
 
 
 					// Order of parts on this bend: the horizontal line first, then the vertical line.
 					// Order of parts on this bend: the horizontal line first, then the vertical line.
 					if (_is_branch_selected(c)) {
 					if (_is_branch_selected(c)) {
 						// If this item or one of its children is selected, we draw the line using parent highlight style.
 						// If this item or one of its children is selected, we draw the line using parent highlight style.
 						if (!is_no_space) {
 						if (!is_no_space) {
 							if (htotal >= 0) {
 							if (htotal >= 0) {
-								RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(parent_line_width / 2), root_pos.y), theme_cache.parent_hl_line_color, parent_line_width);
+								RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(root_pos.x, root_pos.y + parent_line_pixel_shift), Point2(parent_pos.x + parent_line_width * 0.5 + parent_line_pixel_shift, root_pos.y + parent_line_pixel_shift), theme_cache.parent_hl_line_color, parent_line_width);
 							}
 							}
-							RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), theme_cache.parent_hl_line_color, parent_line_width);
+							RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(parent_pos.x + parent_line_pixel_shift, parent_bottom_y), Point2(parent_pos.x + parent_line_pixel_shift, prev_hl_ofs), theme_cache.parent_hl_line_color, parent_line_width);
 						}
 						}
 
 
 						more_prev_ofs = theme_cache.parent_hl_line_margin;
 						more_prev_ofs = theme_cache.parent_hl_line_margin;
-						prev_hl_ofs = root_pos.y + Math::floor(parent_line_width / 2);
+						prev_hl_ofs = parent_bottom_y;
 					} else if (p_item->is_selected(0)) {
 					} else if (p_item->is_selected(0)) {
 						// If parent item is selected (but this item is not), we draw the line using children highlight style.
 						// If parent item is selected (but this item is not), we draw the line using children highlight style.
 						// Siblings of the selected branch can be drawn with a slight offset and their vertical line must appear as highlighted.
 						// Siblings of the selected branch can be drawn with a slight offset and their vertical line must appear as highlighted.
 						if (_is_sibling_branch_selected(c)) {
 						if (_is_sibling_branch_selected(c)) {
 							if (!is_no_space) {
 							if (!is_no_space) {
 								if (htotal >= 0) {
 								if (htotal >= 0) {
-									RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(parent_line_width / 2), root_pos.y), theme_cache.children_hl_line_color, children_line_width);
+									RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(root_pos.x, root_pos.y + children_line_pixel_shift), Point2i(parent_pos.x + parent_line_width * 0.5 + children_line_pixel_shift, root_pos.y + children_line_pixel_shift), theme_cache.children_hl_line_color, children_line_width);
 								}
 								}
-								RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), theme_cache.parent_hl_line_color, parent_line_width);
+								RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(parent_pos.x + parent_line_pixel_shift, parent_bottom_y), Point2(parent_pos.x + parent_line_pixel_shift, prev_hl_ofs), theme_cache.parent_hl_line_color, parent_line_width);
 							}
 							}
 
 
-							prev_hl_ofs = root_pos.y + Math::floor(parent_line_width / 2);
+							prev_hl_ofs = parent_bottom_y;
 						} else {
 						} else {
 							if (!is_no_space) {
 							if (!is_no_space) {
 								if (htotal >= 0) {
 								if (htotal >= 0) {
-									RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(children_line_width / 2), root_pos.y), theme_cache.children_hl_line_color, children_line_width);
+									RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(root_pos.x, root_pos.y + children_line_pixel_shift), Point2(parent_pos.x + children_line_width * 0.5 + children_line_pixel_shift, root_pos.y + children_line_pixel_shift), theme_cache.children_hl_line_color, children_line_width);
 								}
 								}
-								RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(children_line_width / 2)), Point2i(parent_pos.x, prev_ofs + Math::floor(children_line_width / 2)), theme_cache.children_hl_line_color, children_line_width);
+								RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(parent_pos.x + children_line_pixel_shift, root_pos.y + children_line_width * 0.5 + children_line_pixel_shift), Point2(parent_pos.x + children_line_pixel_shift, prev_ofs + children_line_width * 0.5), theme_cache.children_hl_line_color, children_line_width);
 							}
 							}
 						}
 						}
 					} else {
 					} else {
@@ -2797,24 +2802,24 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
 						if (_is_sibling_branch_selected(c)) {
 						if (_is_sibling_branch_selected(c)) {
 							if (!is_no_space) {
 							if (!is_no_space) {
 								if (htotal >= 0) {
 								if (htotal >= 0) {
-									RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + theme_cache.parent_hl_line_margin, root_pos.y), theme_cache.relationship_line_color, line_width);
+									RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(root_pos.x, root_pos.y + line_pixel_shift), Point2(parent_pos.x + theme_cache.parent_hl_line_margin, root_pos.y + line_pixel_shift), theme_cache.relationship_line_color, line_width);
 								}
 								}
-								RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), theme_cache.parent_hl_line_color, parent_line_width);
+								RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(parent_pos.x + parent_line_pixel_shift, parent_bottom_y), Point2(parent_pos.x + parent_line_pixel_shift, prev_hl_ofs), theme_cache.parent_hl_line_color, parent_line_width);
 							}
 							}
 
 
-							prev_hl_ofs = root_pos.y + Math::floor(parent_line_width / 2);
+							prev_hl_ofs = parent_bottom_y;
 						} else {
 						} else {
 							if (!is_no_space) {
 							if (!is_no_space) {
 								if (htotal >= 0) {
 								if (htotal >= 0) {
-									RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(line_width / 2), root_pos.y), theme_cache.relationship_line_color, line_width);
+									RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(root_pos.x, root_pos.y + line_pixel_shift), Point2(parent_pos.x + line_width * 0.5 + line_pixel_shift, root_pos.y + line_pixel_shift), theme_cache.relationship_line_color, line_width);
 								}
 								}
-								RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(line_width / 2)), Point2i(parent_pos.x, prev_ofs + Math::floor(line_width / 2)), theme_cache.relationship_line_color, line_width);
+								RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(parent_pos.x + line_pixel_shift, root_pos.y + line_width * 0.5 + line_pixel_shift), Point2(parent_pos.x + line_pixel_shift, prev_ofs + line_width * 0.5), theme_cache.relationship_line_color, line_width);
 							}
 							}
 						}
 						}
 					}
 					}
 				}
 				}
 
 
-				prev_ofs = root_pos.y + more_prev_ofs;
+				prev_ofs = root_pos.y + more_prev_ofs + line_pixel_shift;
 			}
 			}
 
 
 			if (child_h < 0) {
 			if (child_h < 0) {
@@ -4921,6 +4926,7 @@ void Tree::_notification(int p_what) {
 			draw_size.y -= tbh;
 			draw_size.y -= tbh;
 
 
 			cache.rtl = is_layout_rtl();
 			cache.rtl = is_layout_rtl();
+			content_scale_factor = popup_editor->is_embedded() ? 1.0 : popup_editor->get_parent_visible_window()->get_content_scale_factor();
 
 
 			if (root && get_size().x > 0 && get_size().y > 0) {
 			if (root && get_size().x > 0 && get_size().y > 0) {
 				int self_height = 0; // Just to pass a reference, we don't need the root's `self_height`.
 				int self_height = 0; // Just to pass a reference, we don't need the root's `self_height`.

+ 1 - 0
scene/gui/tree.h

@@ -488,6 +488,7 @@ private:
 	Vector2 range_drag_capture_pos;
 	Vector2 range_drag_capture_pos;
 
 
 	bool propagate_mouse_activated = false;
 	bool propagate_mouse_activated = false;
+	float content_scale_factor = 0.0;
 
 
 	Rect2 custom_popup_rect;
 	Rect2 custom_popup_rect;
 	int edited_col = -1;
 	int edited_col = -1;