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);