Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add highlight to the relationship lines of selected Tree items #48546

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion doc/classes/Tree.xml
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,12 @@
<theme_item name="checked" type="Texture2D">
The check icon to display when the [constant TreeItem.CELL_MODE_CHECK] mode cell is checked.
</theme_item>
<theme_item name="children_hl_line_color" type="Color" default="Color( 0.27, 0.27, 0.27, 1 )">
The [Color] of the relationship lines between the selected [TreeItem] and its children.
</theme_item>
<theme_item name="children_hl_line_width" type="int" default="1">
The width of the relationship lines between the selected [TreeItem] and its children.
</theme_item>
<theme_item name="cursor" type="StyleBox">
[StyleBox] used for the cursor, when the [Tree] is being focused.
</theme_item>
Expand Down Expand Up @@ -587,8 +593,20 @@
<theme_item name="outline_size" type="int" default="0">
The size of the text outline.
</theme_item>
<theme_item name="parent_hl_line_color" type="Color" default="Color( 0.27, 0.27, 0.27, 1 )">
The [Color] of the relationship lines between the selected [TreeItem] and its parents.
</theme_item>
<theme_item name="parent_hl_line_margin" type="int" default="0">
The space between the parent relationship lines for the selected [TreeItem] and the relationship lines to its siblings that are not selected.
</theme_item>
<theme_item name="parent_hl_line_width" type="int" default="1">
The width of the relationship lines between the selected [TreeItem] and its parents.
</theme_item>
<theme_item name="relationship_line_color" type="Color" default="Color( 0.27, 0.27, 0.27, 1 )">
[Color] of the relationship lines.
The default [Color] of the relationship lines.
</theme_item>
<theme_item name="relationship_line_width" type="int" default="1">
The default width of the relationship lines.
</theme_item>
<theme_item name="scroll_border" type="int" default="4">
The maximum distance between the mouse cursor and the control's border to trigger border scrolling when dragging.
Expand Down
24 changes: 18 additions & 6 deletions editor/editor_themes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -799,8 +799,6 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
style_tree_bg->set_border_color(dark_color_3);
theme->set_stylebox("bg", "Tree", style_tree_bg);

const Color guide_color = mono_color * Color(1, 1, 1, 0.05);
Color relationship_line_color = mono_color * Color(1, 1, 1, relationship_line_opacity);
// Tree
theme->set_icon("checked", "Tree", theme->get_icon("GuiChecked", "EditorIcons"));
theme->set_icon("unchecked", "Tree", theme->get_icon("GuiUnchecked", "EditorIcons"));
Expand All @@ -817,19 +815,33 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("font_color", "Tree", font_color);
theme->set_color("font_selected_color", "Tree", mono_color);
theme->set_color("title_button_color", "Tree", font_color);
theme->set_color("guide_color", "Tree", guide_color);
theme->set_color("relationship_line_color", "Tree", relationship_line_color);
theme->set_color("drop_position_color", "Tree", accent_color);
theme->set_constant("vseparation", "Tree", widget_default_margin.y - EDSCALE);
theme->set_constant("hseparation", "Tree", 6 * EDSCALE);
theme->set_constant("guide_width", "Tree", border_width);
theme->set_constant("item_margin", "Tree", 3 * default_margin_size * EDSCALE);
theme->set_constant("button_margin", "Tree", default_margin_size * EDSCALE);
theme->set_constant("draw_relationship_lines", "Tree", relationship_line_opacity >= 0.01);
theme->set_constant("draw_guides", "Tree", relationship_line_opacity < 0.01);
theme->set_constant("scroll_border", "Tree", 40 * EDSCALE);
theme->set_constant("scroll_speed", "Tree", 12);

const Color guide_color = mono_color * Color(1, 1, 1, 0.05);
Color relationship_line_color = mono_color * Color(1, 1, 1, relationship_line_opacity);

theme->set_constant("draw_guides", "Tree", relationship_line_opacity < 0.01);
theme->set_color("guide_color", "Tree", guide_color);

int relationship_line_width = 1;
Color parent_line_color = mono_color * Color(1, 1, 1, CLAMP(relationship_line_opacity + 0.45, 0.0, 1.0));
Color children_line_color = mono_color * Color(1, 1, 1, CLAMP(relationship_line_opacity + 0.25, 0.0, 1.0));
theme->set_constant("draw_relationship_lines", "Tree", relationship_line_opacity >= 0.01);
theme->set_constant("relationship_line_width", "Tree", relationship_line_width);
theme->set_constant("parent_hl_line_width", "Tree", relationship_line_width * 2);
theme->set_constant("children_hl_line_width", "Tree", relationship_line_width);
theme->set_constant("parent_hl_line_margin", "Tree", relationship_line_width * 3);
theme->set_color("relationship_line_color", "Tree", relationship_line_color);
theme->set_color("parent_hl_line_color", "Tree", parent_line_color);
theme->set_color("children_hl_line_color", "Tree", children_line_color);

Ref<StyleBoxFlat> style_tree_btn = style_default->duplicate();
style_tree_btn->set_bg_color(highlight_color);
style_tree_btn->set_border_width_all(0);
Expand Down
93 changes: 83 additions & 10 deletions scene/gui/tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1184,15 +1184,23 @@ void Tree::update_cache() {

cache.font_color = get_theme_color("font_color");
cache.font_selected_color = get_theme_color("font_selected_color");
cache.guide_color = get_theme_color("guide_color");
cache.drop_position_color = get_theme_color("drop_position_color");
cache.hseparation = get_theme_constant("hseparation");
cache.vseparation = get_theme_constant("vseparation");
cache.item_margin = get_theme_constant("item_margin");
cache.button_margin = get_theme_constant("button_margin");

cache.draw_guides = get_theme_constant("draw_guides");
cache.guide_color = get_theme_color("guide_color");
cache.draw_relationship_lines = get_theme_constant("draw_relationship_lines");
cache.relationship_line_width = get_theme_constant("relationship_line_width");
cache.parent_hl_line_width = get_theme_constant("parent_hl_line_width");
cache.children_hl_line_width = get_theme_constant("children_hl_line_width");
cache.parent_hl_line_margin = get_theme_constant("parent_hl_line_margin");
cache.relationship_line_color = get_theme_color("relationship_line_color");
cache.parent_hl_line_color = get_theme_color("parent_hl_line_color");
cache.children_hl_line_color = get_theme_color("children_hl_line_color");

cache.scroll_border = get_theme_constant("scroll_border");
cache.scroll_speed = get_theme_constant("scroll_speed");

Expand Down Expand Up @@ -1813,38 +1821,73 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2

TreeItem *c = p_item->first_child;

int prev_ofs = children_pos.y - cache.offset.y + p_draw_ofs.y;
int base_ofs = children_pos.y - cache.offset.y + p_draw_ofs.y;
int prev_ofs = base_ofs;
int prev_hl_ofs = base_ofs;

while (c) {
if (cache.draw_relationship_lines > 0 && (!hide_root || c->parent != root)) {
int root_ofs = children_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin);
int parent_ofs = p_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin);
int parent_ofs = p_pos.x + cache.item_margin;
Point2i root_pos = Point2i(root_ofs, children_pos.y + label_h / 2) - cache.offset + p_draw_ofs;

if (c->get_first_child() != nullptr) {
root_pos -= Point2i(cache.arrow->get_width(), 0);
}

float line_width = 1.0;
float line_width = cache.relationship_line_width;
float parent_line_width = cache.parent_hl_line_width;
float children_line_width = cache.children_hl_line_width;

#ifdef TOOLS_ENABLED
line_width *= Math::round(EDSCALE);
parent_line_width *= Math::round(EDSCALE);
children_line_width *= Math::round(EDSCALE);
#endif

Point2i parent_pos = Point2i(parent_ofs - cache.arrow->get_width() / 2, p_pos.y + label_h / 2 + cache.arrow->get_height() / 2) - cache.offset + p_draw_ofs;

int more_prev_ofs = 0;

if (root_pos.y + line_width >= 0) {
if (rtl) {
root_pos.x = get_size().width - root_pos.x;
parent_pos.x = get_size().width - parent_pos.x;
}
RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x - Math::floor(line_width / 2), root_pos.y), cache.relationship_line_color, line_width);
RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y), Point2i(parent_pos.x, prev_ofs), cache.relationship_line_color, line_width);

// Order of parts on this bend: the horizontal line first, then the vertical line.
if (_is_branch_selected(c)) {
// If this item or one of its children is selected, we draw the line using parent highlight style.
RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(parent_line_width / 2), root_pos.y), 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), cache.parent_hl_line_color, parent_line_width);

more_prev_ofs = cache.parent_hl_line_margin;
prev_hl_ofs = root_pos.y + Math::floor(parent_line_width / 2);
} 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.
// Siblings of the selected branch can be drawn with a slight offset (and also don't need a vertical line).
if (_is_sibling_branch_selected(c)) {
RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(parent_line_width / 2), root_pos.y), cache.children_hl_line_color, children_line_width);
} else {
RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(children_line_width / 2), root_pos.y), 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)), cache.children_hl_line_color, children_line_width);
}
} else {
// If nothing of the above is true, we draw the line using normal style.
// Siblings of the selected branch can be drawn with a slight offset (and also don't need a vertical line).
if (_is_sibling_branch_selected(c)) {
RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + cache.parent_hl_line_margin, root_pos.y), cache.relationship_line_color, line_width);
} else {
RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(line_width / 2), root_pos.y), 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)), cache.relationship_line_color, line_width);
}
}
}

if (htotal < 0) {
return -1;
}
prev_ofs = root_pos.y;
prev_ofs = root_pos.y + more_prev_ofs;
}

if (htotal >= 0) {
Expand All @@ -1853,10 +1896,10 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (child_h < 0) {
if (cache.draw_relationship_lines == 0) {
return -1; // break, stop drawing, no need to anymore
} else {
htotal = -1;
children_pos.y = cache.offset.y + p_draw_size.height;
}

htotal = -1;
children_pos.y = cache.offset.y + p_draw_size.height;
} else {
htotal += child_h;
children_pos.y += child_h;
Expand Down Expand Up @@ -1889,6 +1932,36 @@ int Tree::_count_selected_items(TreeItem *p_from) const {
return count;
}

bool Tree::_is_branch_selected(TreeItem *p_from) const {
for (int i = 0; i < columns.size(); i++) {
if (p_from->is_selected(i)) {
return true;
}
}

TreeItem *child_item = p_from->get_first_child();
while (child_item) {
if (_is_branch_selected(child_item)) {
return true;
}
child_item = child_item->get_next();
}

return false;
}

bool Tree::_is_sibling_branch_selected(TreeItem *p_from) const {
TreeItem *sibling_item = p_from->get_next();
while (sibling_item) {
if (_is_branch_selected(sibling_item)) {
return true;
}
sibling_item = sibling_item->get_next();
}

return false;
}

void Tree::select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_col, TreeItem *p_prev, bool *r_in_range, bool p_force_deselect) {
TreeItem::Cell &selected_cell = p_selected->cells.write[p_col];

Expand Down
8 changes: 8 additions & 0 deletions scene/gui/tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,8 @@ class Tree : public Control {
Color guide_color;
Color drop_position_color;
Color relationship_line_color;
Color parent_hl_line_color;
Color children_hl_line_color;
Color custom_button_font_highlight;

int hseparation = 0;
Expand All @@ -502,6 +504,10 @@ class Tree : public Control {
int button_margin = 0;
Point2 offset;
int draw_relationship_lines = 0;
int relationship_line_width = 0;
int parent_hl_line_width = 0;
int children_hl_line_width = 0;
int parent_hl_line_margin = 0;
int draw_guides = 0;
int scroll_border = 0;
int scroll_speed = 0;
Expand Down Expand Up @@ -574,6 +580,8 @@ class Tree : public Control {
bool hide_folding = false;

int _count_selected_items(TreeItem *p_from) const;
bool _is_branch_selected(TreeItem *p_from) const;
bool _is_sibling_branch_selected(TreeItem *p_from) const;
void _go_left();
void _go_right();
void _go_down();
Expand Down
6 changes: 6 additions & 0 deletions scene/resources/default_theme/default_theme.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -719,13 +719,19 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("guide_color", "Tree", Color(0, 0, 0, 0.1));
theme->set_color("drop_position_color", "Tree", Color(1, 0.3, 0.2));
theme->set_color("relationship_line_color", "Tree", Color(0.27, 0.27, 0.27));
theme->set_color("parent_hl_line_color", "Tree", Color(0.27, 0.27, 0.27));
theme->set_color("children_hl_line_color", "Tree", Color(0.27, 0.27, 0.27));
theme->set_color("custom_button_font_highlight", "Tree", control_font_hover_color);

theme->set_constant("hseparation", "Tree", 4 * scale);
theme->set_constant("vseparation", "Tree", 4 * scale);
theme->set_constant("item_margin", "Tree", 12 * scale);
theme->set_constant("button_margin", "Tree", 4 * scale);
theme->set_constant("draw_relationship_lines", "Tree", 0);
theme->set_constant("relationship_line_width", "Tree", 1);
theme->set_constant("parent_hl_line_width", "Tree", 1);
theme->set_constant("children_hl_line_width", "Tree", 1);
theme->set_constant("parent_hl_line_margin", "Tree", 0);
theme->set_constant("draw_guides", "Tree", 1);
theme->set_constant("scroll_border", "Tree", 4);
theme->set_constant("scroll_speed", "Tree", 12);
Expand Down