diff --git a/doc/classes/ItemList.xml b/doc/classes/ItemList.xml
index 2914e0c6d99..f5da4553d0b 100644
--- a/doc/classes/ItemList.xml
+++ b/doc/classes/ItemList.xml
@@ -439,6 +439,9 @@
Default text [Color] of the item.
+
+ Text [Color] used when the item is hovered and not selected yet.
+
The tint of text outline of the item.
@@ -479,6 +482,9 @@
The focused style for the [ItemList], drawn on top of the background, but below everything else.
+
+ [StyleBox] for the hovered, but not selected items.
+
The background style for the [ItemList].
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 5cd5ff05c57..aa639823cc7 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -1296,13 +1296,20 @@ Ref create_editor_theme(const Ref p_theme) {
style_itemlist_cursor->set_draw_center(false);
style_itemlist_cursor->set_border_width_all(border_width);
style_itemlist_cursor->set_border_color(highlight_color);
+
+ Ref style_itemlist_hover = style_tree_selected->duplicate();
+ style_itemlist_hover->set_bg_color(highlight_color * Color(1, 1, 1, 0.3));
+ style_itemlist_hover->set_border_width_all(0);
+
theme->set_stylebox("panel", "ItemList", style_itemlist_bg);
theme->set_stylebox("focus", "ItemList", style_widget_focus);
theme->set_stylebox("cursor", "ItemList", style_itemlist_cursor);
theme->set_stylebox("cursor_unfocused", "ItemList", style_itemlist_cursor);
theme->set_stylebox("selected_focus", "ItemList", style_tree_focus);
theme->set_stylebox("selected", "ItemList", style_tree_selected);
+ theme->set_stylebox("hovered", "ItemList", style_itemlist_hover);
theme->set_color("font_color", "ItemList", font_color);
+ theme->set_color("font_hovered_color", "ItemList", mono_color);
theme->set_color("font_selected_color", "ItemList", mono_color);
theme->set_color("font_outline_color", "ItemList", font_outline_color);
theme->set_color("guide_color", "ItemList", guide_color);
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index 8dc4f695025..c23232c9742 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -646,6 +646,14 @@ void ItemList::gui_input(const Ref &p_event) {
return;
}
+ if (mm.is_valid()) {
+ int closest = get_item_at_position(mm->get_position(), true);
+ if (closest != hovered) {
+ hovered = closest;
+ queue_redraw();
+ }
+ }
+
if (mb.is_valid() && mb->is_pressed()) {
search_string = ""; //any mousepress cancels
Vector2 pos = mb->get_position();
@@ -975,12 +983,14 @@ void ItemList::_update_theme_item_cache() {
theme_cache.font = get_theme_font(SNAME("font"));
theme_cache.font_size = get_theme_font_size(SNAME("font_size"));
theme_cache.font_color = get_theme_color(SNAME("font_color"));
+ theme_cache.font_hovered_color = get_theme_color(SNAME("font_hovered_color"));
theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
theme_cache.font_outline_size = get_theme_constant(SNAME("outline_size"));
theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
theme_cache.line_separation = get_theme_constant(SNAME("line_separation"));
theme_cache.icon_margin = get_theme_constant(SNAME("icon_margin"));
+ theme_cache.hovered_style = get_theme_stylebox(SNAME("hovered"));
theme_cache.selected_style = get_theme_stylebox(SNAME("selected"));
theme_cache.selected_focus_style = get_theme_stylebox(SNAME("selected_focus"));
theme_cache.cursor_style = get_theme_stylebox(SNAME("cursor_unfocused"));
@@ -1101,7 +1111,11 @@ void ItemList::_notification(int p_what) {
rcache.size.width = width - rcache.position.x;
}
- if (items[i].selected) {
+ bool should_draw_selected_bg = items[i].selected;
+ bool should_draw_hovered_bg = hovered == i && !items[i].selected;
+ bool should_draw_custom_bg = items[i].custom_bg.a > 0.001;
+
+ if (should_draw_selected_bg || should_draw_hovered_bg || should_draw_custom_bg) {
Rect2 r = rcache;
r.position += base_ofs;
r.position.y -= theme_cache.v_separation / 2;
@@ -1113,23 +1127,15 @@ void ItemList::_notification(int p_what) {
r.position.x = size.width - r.position.x - r.size.x;
}
- draw_style_box(sbsel, r);
- }
- if (items[i].custom_bg.a > 0.001) {
- Rect2 r = rcache;
- r.position += base_ofs;
-
- // Size rect to make the align the temperature colors
- r.position.y -= theme_cache.v_separation / 2;
- r.size.y += theme_cache.v_separation;
- r.position.x -= theme_cache.h_separation / 2;
- r.size.x += theme_cache.h_separation;
-
- if (rtl) {
- r.position.x = size.width - r.position.x - r.size.x;
+ if (should_draw_selected_bg) {
+ draw_style_box(sbsel, r);
+ }
+ if (should_draw_hovered_bg) {
+ draw_style_box(theme_cache.hovered_style, r);
+ }
+ if (should_draw_custom_bg) {
+ draw_rect(r, items[i].custom_bg);
}
-
- draw_rect(r, items[i].custom_bg);
}
Vector2 text_ofs;
@@ -1204,7 +1210,17 @@ void ItemList::_notification(int p_what) {
max_len = size2.x;
}
- Color txt_modulate = items[i].selected ? theme_cache.font_selected_color : (items[i].custom_fg != Color() ? items[i].custom_fg : theme_cache.font_color);
+ Color txt_modulate;
+ if (items[i].selected) {
+ txt_modulate = theme_cache.font_selected_color;
+ } else if (hovered == i) {
+ txt_modulate = theme_cache.font_hovered_color;
+ } else if (items[i].custom_fg != Color()) {
+ txt_modulate = items[i].custom_fg;
+ } else {
+ txt_modulate = theme_cache.font_color;
+ }
+
if (items[i].disabled) {
txt_modulate.a *= 0.5;
}
@@ -1454,6 +1470,13 @@ void ItemList::_scroll_changed(double) {
queue_redraw();
}
+void ItemList::_mouse_exited() {
+ if (hovered > -1) {
+ hovered = -1;
+ queue_redraw();
+ }
+}
+
int ItemList::get_item_at_position(const Point2 &p_pos, bool p_exact) const {
Vector2 pos = p_pos;
pos -= theme_cache.panel_style->get_offset();
@@ -1851,9 +1874,10 @@ void ItemList::_bind_methods() {
ItemList::ItemList() {
scroll_bar = memnew(VScrollBar);
add_child(scroll_bar, false, INTERNAL_MODE_FRONT);
-
scroll_bar->connect("value_changed", callable_mp(this, &ItemList::_scroll_changed));
+ connect("mouse_exited", callable_mp(this, &ItemList::_mouse_exited));
+
set_focus_mode(FOCUS_ALL);
set_clip_contents(true);
}
diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h
index 590d5c63889..d050f4a9d0d 100644
--- a/scene/gui/item_list.h
+++ b/scene/gui/item_list.h
@@ -84,6 +84,7 @@ private:
};
int current = -1;
+ int hovered = -1;
bool shape_changed = true;
@@ -130,12 +131,14 @@ private:
Ref font;
int font_size = 0;
Color font_color;
+ Color font_hovered_color;
Color font_selected_color;
int font_outline_size = 0;
Color font_outline_color;
int line_separation = 0;
int icon_margin = 0;
+ Ref hovered_style;
Ref selected_style;
Ref selected_focus_style;
Ref cursor_style;
@@ -146,6 +149,7 @@ private:
void _scroll_changed(double);
void _check_shape_changed();
void _shape_text(int p_idx);
+ void _mouse_exited();
protected:
virtual void _update_theme_item_cache() override;
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index a70cdeda20f..0ee51a46e83 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -803,9 +803,11 @@ void fill_default_theme(Ref &theme, const Ref &default_font, const
theme->set_font_size("font_size", "ItemList", -1);
theme->set_color("font_color", "ItemList", control_font_lower_color);
+ theme->set_color("font_hovered_color", "ItemList", control_font_hover_color);
theme->set_color("font_selected_color", "ItemList", control_font_pressed_color);
theme->set_color("font_outline_color", "ItemList", Color(1, 1, 1));
theme->set_color("guide_color", "ItemList", Color(0.7, 0.7, 0.7, 0.25));
+ theme->set_stylebox("hovered", "ItemList", make_flat_stylebox(Color(1, 1, 1, 0.07)));
theme->set_stylebox("selected", "ItemList", make_flat_stylebox(style_selected_color));
theme->set_stylebox("selected_focus", "ItemList", make_flat_stylebox(style_selected_color));
theme->set_stylebox("cursor", "ItemList", focus);