Improve interaction feedback in modern theme

This commit is contained in:
passivestar 2026-01-03 21:39:02 +04:00
parent 05c097e5e2
commit 411c47f87e
7 changed files with 67 additions and 37 deletions

View file

@ -7509,13 +7509,13 @@ Vector<Ref<EditorResourceConversionPlugin>> EditorNode::find_resource_conversion
void EditorNode::_update_renderer_color() {
String rendering_method = renderer->get_selected_metadata();
if (rendering_method == "forward_plus") {
renderer->add_theme_color_override(SceneStringName(font_color), theme->get_color(SNAME("forward_plus_color"), EditorStringName(Editor)));
} else if (rendering_method == "mobile") {
renderer->add_theme_color_override(SceneStringName(font_color), theme->get_color(SNAME("mobile_color"), EditorStringName(Editor)));
} else if (rendering_method == "gl_compatibility") {
renderer->add_theme_color_override(SceneStringName(font_color), theme->get_color(SNAME("gl_compatibility_color"), EditorStringName(Editor)));
}
const Color renderer_normal_color = theme->get_color(rendering_method + "_color", EditorStringName(Editor));
const Color mono_color = theme->get_color(SNAME("mono_color"), EditorStringName(Editor));
renderer->add_theme_color_override(SceneStringName(font_color), renderer_normal_color);
renderer->add_theme_color_override("font_hover_color", renderer_normal_color.lerp(mono_color, 0.3));
renderer->add_theme_color_override("font_pressed_color", renderer_normal_color.lerp(mono_color, 0.4));
renderer->add_theme_color_override("font_hover_pressed_color", renderer_normal_color.lerp(mono_color, 0.5));
}
void EditorNode::_renderer_selected(int p_index) {

View file

@ -2065,7 +2065,7 @@ void EditorInspectorSection::_notification(int p_what) {
}
arrow_position.y = (header_height - arrow->get_height()) / 2;
if (can_click_unfold) {
draw_texture(arrow, arrow_position);
draw_texture(arrow, arrow_position, Color(1, 1, 1, header_hover ? 1.0 : 0.85));
}
margin_start += arrow->get_width() + theme_cache.horizontal_separation;
}
@ -2176,8 +2176,9 @@ void EditorInspectorSection::_notification(int p_what) {
if (object->has_method("_get_property_warning") && !String(object->call("_get_property_warning", related_enable_property)).is_empty()) {
font_color = theme_cache.warning_color;
}
const Color string_color = header_hover ? theme_cache.font_hover_mono_color : font_color;
HorizontalAlignment text_align = rtl ? HORIZONTAL_ALIGNMENT_RIGHT : HORIZONTAL_ALIGNMENT_LEFT;
draw_string(font, text_offset, label, text_align, available, font_size, theme_cache.font_color, TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS);
draw_string(font, text_offset, label, text_align, available, font_size, string_color, TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS);
}
// Draw section indentation.
@ -3576,6 +3577,7 @@ void EditorInspector::initialize_section_theme(EditorInspectorSection::ThemeCach
p_cache.font_hover_color = p_control->get_theme_color(SNAME("font_hover_color"), EditorStringName(Editor));
p_cache.font_pressed_color = p_control->get_theme_color(SNAME("font_pressed_color"), EditorStringName(Editor));
p_cache.font_hover_pressed_color = p_control->get_theme_color(SNAME("font_hover_pressed_color"), EditorStringName(Editor));
p_cache.font_hover_mono_color = p_control->get_theme_color(SNAME("mono_color"), EditorStringName(Editor)) * Color(1, 1, 1, 0.925);
p_cache.font = p_control->get_theme_font(SceneStringName(font), SNAME("Tree"));
p_cache.font_size = p_control->get_theme_font_size(SceneStringName(font_size), SNAME("Tree"));

View file

@ -482,6 +482,7 @@ class EditorInspectorSection : public Container {
Color font_hover_color;
Color font_pressed_color;
Color font_hover_pressed_color;
Color font_hover_mono_color;
Ref<Font> font;
int font_size = 0;

View file

@ -1271,7 +1271,7 @@ GameView::GameView(Ref<GameViewDebugger> p_debugger, EmbeddedProcessBase *p_embe
node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]->set_text(TTRC("Input"));
node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]->set_toggle_mode(true);
node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]->set_pressed(true);
node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]->set_theme_type_variation(SceneStringName(FlatButton));
node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]->set_theme_type_variation("FlatButtonNoIconTint");
node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]->connect(SceneStringName(pressed), callable_mp(this, &GameView::_node_type_pressed).bind(RuntimeNodeSelect::NODE_TYPE_NONE));
node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]->set_tooltip_text(TTRC("Allow game input."));
@ -1279,7 +1279,7 @@ GameView::GameView(Ref<GameViewDebugger> p_debugger, EmbeddedProcessBase *p_embe
input_hb->add_child(node_type_button[RuntimeNodeSelect::NODE_TYPE_2D]);
node_type_button[RuntimeNodeSelect::NODE_TYPE_2D]->set_text(TTRC("2D"));
node_type_button[RuntimeNodeSelect::NODE_TYPE_2D]->set_toggle_mode(true);
node_type_button[RuntimeNodeSelect::NODE_TYPE_2D]->set_theme_type_variation(SceneStringName(FlatButton));
node_type_button[RuntimeNodeSelect::NODE_TYPE_2D]->set_theme_type_variation("FlatButtonNoIconTint");
node_type_button[RuntimeNodeSelect::NODE_TYPE_2D]->connect(SceneStringName(pressed), callable_mp(this, &GameView::_node_type_pressed).bind(RuntimeNodeSelect::NODE_TYPE_2D));
node_type_button[RuntimeNodeSelect::NODE_TYPE_2D]->set_tooltip_text(TTRC("Disable game input and allow to select Node2Ds, Controls, and manipulate the 2D camera."));
@ -1287,7 +1287,7 @@ GameView::GameView(Ref<GameViewDebugger> p_debugger, EmbeddedProcessBase *p_embe
input_hb->add_child(node_type_button[RuntimeNodeSelect::NODE_TYPE_3D]);
node_type_button[RuntimeNodeSelect::NODE_TYPE_3D]->set_text(TTRC("3D"));
node_type_button[RuntimeNodeSelect::NODE_TYPE_3D]->set_toggle_mode(true);
node_type_button[RuntimeNodeSelect::NODE_TYPE_3D]->set_theme_type_variation(SceneStringName(FlatButton));
node_type_button[RuntimeNodeSelect::NODE_TYPE_3D]->set_theme_type_variation("FlatButtonNoIconTint");
node_type_button[RuntimeNodeSelect::NODE_TYPE_3D]->connect(SceneStringName(pressed), callable_mp(this, &GameView::_node_type_pressed).bind(RuntimeNodeSelect::NODE_TYPE_3D));
node_type_button[RuntimeNodeSelect::NODE_TYPE_3D]->set_tooltip_text(TTRC("Disable game input and allow to select Node3Ds and manipulate the 3D camera."));

View file

@ -157,6 +157,10 @@ public:
Color button_border_hover_color;
Color button_border_pressed_color;
Color flat_button_pressed_color;
Color flat_button_hover_pressed_color;
Color flat_button_hover_color;
Color shadow_color;
Color selection_color;
Color disabled_border_color;
@ -176,6 +180,7 @@ public:
Ref<StyleBoxFlat> flat_button;
Ref<StyleBoxFlat> flat_button_pressed;
Ref<StyleBoxFlat> flat_button_hover_pressed;
Ref<StyleBoxFlat> flat_button_hover;
Ref<StyleBoxFlat> popup_style;

View file

@ -1867,8 +1867,12 @@ void ThemeClassic::populate_editor_styles(const Ref<EditorTheme> &p_theme, Edito
p_theme->set_stylebox(SceneStringName(pressed), "FlatMenuButton", style_flat_button_pressed);
p_theme->set_stylebox("disabled", "FlatMenuButton", style_flat_button);
// Variation for Editor Log filter buttons.
p_theme->set_type_variation("FlatButtonNoIconTint", "FlatButton");
p_theme->set_color("icon_pressed_color", "FlatButtonNoIconTint", p_config.icon_normal_color);
p_theme->set_color("icon_hover_color", "FlatButtonNoIconTint", p_config.mono_color);
p_theme->set_color("icon_hover_pressed_color", "FlatButtonNoIconTint", p_config.mono_color);
// Variation for Editor Log filter buttons.
p_theme->set_type_variation("EditorLogFilterButton", "Button");
// When pressed, don't tint the icons with the accent color, just leave them normal.
p_theme->set_color("icon_pressed_color", "EditorLogFilterButton", p_config.icon_normal_color);

View file

@ -197,11 +197,15 @@ void ThemeModern::populate_shared_styles(const Ref<EditorTheme> &p_theme, Editor
p_config.button_normal_color = _get_base_color(p_config, -2.0, 0.85);
p_config.button_hover_color = _get_base_color(p_config, -2.9, 0.75);
p_config.button_pressed_color = _get_base_color(p_config, -3.2, 0.75);
p_config.button_disabled_color = _get_base_color(p_config, -1.5, 0.75);
p_config.button_disabled_color = _get_base_color(p_config, -1.4, 0.75);
p_config.button_border_normal_color = _get_base_color(p_config, -2.5, 0.75);
p_config.button_border_hover_color = _get_base_color(p_config, -3.4, 0.75);
p_config.button_border_pressed_color = _get_base_color(p_config, -3.7, 0.75);
p_config.flat_button_hover_color = _get_base_color(p_config, -1.2, 0.75);
p_config.flat_button_pressed_color = _get_base_color(p_config, -2.0, 0.75);
p_config.flat_button_hover_pressed_color = _get_base_color(p_config, -2.4, 0.75);
p_config.shadow_color = Color(0, 0, 0, p_config.dark_theme ? 0.3 : 0.1);
p_config.selection_color = p_config.accent_color * Color(1, 1, 1, 0.4);
p_config.disabled_border_color = p_config.mono_color.inverted().lerp(p_config.base_color, 0.7);
@ -315,8 +319,7 @@ void ThemeModern::populate_shared_styles(const Ref<EditorTheme> &p_theme, Editor
}
p_config.flat_button_hover = p_config.base_style->duplicate();
// Use the normal variation here and the hover one in the pressed state to lessen contrast.
p_config.flat_button_hover->set_bg_color(p_config.button_normal_color);
p_config.flat_button_hover->set_bg_color(p_config.flat_button_hover_color);
// This affects buttons in Tree so top and bottom margins should be kept low.
p_config.flat_button_hover->set_content_margin_individual(p_config.base_margin * 1.5 * EDSCALE, p_config.base_margin * 0.9 * EDSCALE, p_config.base_margin * 1.5 * EDSCALE, p_config.base_margin * 0.9 * EDSCALE);
if (p_config.draw_extra_borders) {
@ -324,11 +327,17 @@ void ThemeModern::populate_shared_styles(const Ref<EditorTheme> &p_theme, Editor
}
p_config.flat_button_pressed = p_config.flat_button_hover->duplicate();
p_config.flat_button_pressed->set_bg_color(_get_base_color(p_config, -2.4, 0.75));
p_config.flat_button_pressed->set_bg_color(p_config.flat_button_pressed_color);
if (p_config.draw_extra_borders) {
p_config.flat_button_pressed->set_border_color(p_config.extra_border_color_1);
}
p_config.flat_button_hover_pressed = p_config.flat_button_hover->duplicate();
p_config.flat_button_hover_pressed->set_bg_color(p_config.flat_button_hover_pressed_color);
if (p_config.draw_extra_borders) {
p_config.flat_button_hover_pressed->set_border_color(p_config.extra_border_color_1);
}
p_config.flat_button = p_config.flat_button_hover->duplicate();
p_config.flat_button->set_draw_center(false);
}
@ -673,20 +682,23 @@ void ThemeModern::populate_standard_styles(const Ref<EditorTheme> &p_theme, Edit
p_theme->set_color("guide_color", "Tree", Color(1, 1, 1, 0));
Ref<StyleBoxFlat> style_tree_hover = p_config.flat_button_hover->duplicate();
style_tree_hover->set_bg_color(p_config.button_disabled_color);
style_tree_hover->set_content_margin_all(0);
p_theme->set_stylebox("button_hover", "Tree", style_tree_hover);
p_theme->set_stylebox("hovered", "Tree", style_tree_hover);
p_theme->set_stylebox("hovered_dimmed", "Tree", style_tree_hover);
p_theme->set_stylebox("custom_button_hover", "Tree", style_tree_hover);
p_theme->set_stylebox("selected", "Tree", style_tree_hover);
Ref<StyleBoxFlat> style_tree_selected = p_config.flat_button_pressed->duplicate();
style_tree_selected->set_content_margin_all(0);
p_theme->set_stylebox("selected", "Tree", style_tree_selected);
p_theme->set_stylebox("selected_focus", "Tree", p_config.focus_style);
Ref<StyleBoxFlat> style_tree_hover_selected = style_tree_hover->duplicate();
style_tree_hover_selected->set_bg_color(p_config.button_normal_color);
Ref<StyleBoxFlat> style_tree_hovered_selected = p_config.flat_button_hover_pressed->duplicate();
style_tree_hovered_selected->set_content_margin_all(0);
p_theme->set_stylebox("hovered_selected", "Tree", style_tree_hover_selected);
p_theme->set_stylebox("hovered_selected", "Tree", style_tree_hovered_selected);
p_theme->set_stylebox("hovered_selected_focus", "Tree", p_config.focus_style);
// Cursor is drawn on top of the item so it needs to be transparent.
@ -710,7 +722,7 @@ void ThemeModern::populate_standard_styles(const Ref<EditorTheme> &p_theme, Edit
// ProjectList.
{
Ref<StyleBoxFlat> style_project_list_hover = p_config.flat_button_hover->duplicate();
style_project_list_hover->set_bg_color(_get_base_color(p_config, -0.5, 0.75));
style_project_list_hover->set_bg_color(_get_base_color(p_config, -0.2, 0.75));
style_project_list_hover->set_content_margin_all(0);
Ref<StyleBoxFlat> style_project_list_selected = style_project_list_hover->duplicate();
@ -740,9 +752,9 @@ void ThemeModern::populate_standard_styles(const Ref<EditorTheme> &p_theme, Edit
p_theme->set_stylebox("cursor", "ItemList", style_itemlist_cursor);
p_theme->set_stylebox("cursor_unfocused", "ItemList", style_itemlist_cursor);
p_theme->set_stylebox("selected_focus", "ItemList", p_config.focus_style);
p_theme->set_stylebox("selected", "ItemList", p_config.flat_button_hover);
p_theme->set_stylebox("selected", "ItemList", p_config.flat_button_pressed);
p_theme->set_stylebox("hovered", "ItemList", p_config.flat_button_hover);
p_theme->set_stylebox("hovered_selected", "ItemList", p_config.flat_button_hover);
p_theme->set_stylebox("hovered_selected", "ItemList", p_config.flat_button_hover_pressed);
p_theme->set_stylebox("hovered_selected_focus", "ItemList", p_config.focus_style);
p_theme->set_color(SceneStringName(font_color), "ItemList", p_config.font_color);
p_theme->set_color("font_hovered_color", "ItemList", p_config.font_hover_color);
@ -1687,7 +1699,7 @@ void ThemeModern::populate_editor_styles(const Ref<EditorTheme> &p_theme, Editor
p_theme->set_stylebox(CoreStringName(normal), "MainMenuBar", p_config.flat_button);
p_theme->set_stylebox(SceneStringName(pressed), "MainMenuBar", p_config.flat_button_pressed);
p_theme->set_stylebox(SceneStringName(hover), "MainMenuBar", p_config.flat_button_hover);
p_theme->set_stylebox("hover_pressed", "MainMenuBar", p_config.flat_button_hover);
p_theme->set_stylebox("hover_pressed", "MainMenuBar", p_config.flat_button_hover_pressed);
// Run bar.
Ref<StyleBoxFlat> run_bar_hover = p_config.base_style->duplicate();
@ -1726,6 +1738,10 @@ void ThemeModern::populate_editor_styles(const Ref<EditorTheme> &p_theme, Editor
Ref<StyleBoxEmpty> style_bottom_tab = p_config.base_empty_style->duplicate();
style_bottom_tab->set_content_margin_individual(p_config.base_margin * 2 * EDSCALE, p_config.base_margin * 1.2 * EDSCALE, p_config.base_margin * 2 * EDSCALE, p_config.base_margin * 1.2 * EDSCALE);
Ref<StyleBoxFlat> bottom_panel_button_pressed = p_config.flat_button_pressed->duplicate();
bottom_panel_button_pressed->set_content_margin_individual(p_config.base_margin * 2 * EDSCALE, p_config.base_margin * 1.2 * EDSCALE, p_config.base_margin * 2 * EDSCALE, p_config.base_margin * 1.2 * EDSCALE);
Ref<StyleBoxFlat> bottom_panel_button_hover = p_config.flat_button_hover->duplicate();
bottom_panel_button_hover->set_content_margin_individual(p_config.base_margin * 2 * EDSCALE, p_config.base_margin * 1.2 * EDSCALE, p_config.base_margin * 2 * EDSCALE, p_config.base_margin * 1.2 * EDSCALE);
@ -1733,7 +1749,7 @@ void ThemeModern::populate_editor_styles(const Ref<EditorTheme> &p_theme, Editor
p_theme->set_type_variation("BottomPanel", "TabContainer");
p_theme->set_stylebox(SceneStringName(panel), "BottomPanel", style_bottom_panel_hidden);
p_theme->set_stylebox("tabbar_background", "BottomPanel", style_bottom_panel_tabbar);
p_theme->set_stylebox("tab_selected", "BottomPanel", bottom_panel_button_hover);
p_theme->set_stylebox("tab_selected", "BottomPanel", bottom_panel_button_pressed);
p_theme->set_stylebox("tab_hovered", "BottomPanel", bottom_panel_button_hover);
p_theme->set_stylebox("tab_focus", "BottomPanel", p_config.base_empty_style);
p_theme->set_stylebox("tab_unselected", "BottomPanel", style_bottom_tab);
@ -1750,10 +1766,7 @@ void ThemeModern::populate_editor_styles(const Ref<EditorTheme> &p_theme, Editor
p_theme->set_stylebox(CoreStringName(normal), "BottomPanelButton", bottom_panel_button);
p_theme->set_stylebox(SceneStringName(hover), "BottomPanelButton", bottom_panel_button_hover);
p_theme->set_stylebox(SceneStringName(pressed), "BottomPanelButton", bottom_panel_button_hover);
Ref<StyleBoxFlat> bottom_panel_button_pressed = p_config.flat_button_hover->duplicate();
bottom_panel_button_pressed->set_content_margin_individual(p_config.base_margin * 2 * EDSCALE, p_config.base_margin * 1.2 * EDSCALE, p_config.base_margin * 2 * EDSCALE, p_config.base_margin * 1.2 * EDSCALE);
p_theme->set_stylebox(SceneStringName(pressed), "BottomPanelButton", bottom_panel_button_pressed);
p_theme->set_stylebox("hover_pressed", "BottomPanelButton", bottom_panel_button_pressed);
// Don't tint the icon even when in "pressed" state.
@ -1857,15 +1870,20 @@ void ThemeModern::populate_editor_styles(const Ref<EditorTheme> &p_theme, Editor
p_theme->set_stylebox(CoreStringName(normal), SceneStringName(FlatButton), p_config.base_empty_wide_style);
p_theme->set_stylebox(SceneStringName(hover), SceneStringName(FlatButton), p_config.flat_button_hover);
p_theme->set_stylebox(SceneStringName(pressed), SceneStringName(FlatButton), p_config.flat_button_pressed);
p_theme->set_stylebox("hover_pressed", SceneStringName(FlatButton), p_config.flat_button_pressed);
p_theme->set_stylebox("hover_pressed", SceneStringName(FlatButton), p_config.flat_button_hover_pressed);
p_theme->set_stylebox("disabled", SceneStringName(FlatButton), p_config.base_empty_wide_style);
p_theme->set_stylebox(CoreStringName(normal), "FlatMenuButton", p_config.base_empty_wide_style);
p_theme->set_stylebox(SceneStringName(hover), "FlatMenuButton", p_config.flat_button_hover);
p_theme->set_stylebox(SceneStringName(pressed), "FlatMenuButton", p_config.flat_button_pressed);
p_theme->set_stylebox("hover_pressed", "FlatMenuButton", p_config.flat_button_pressed);
p_theme->set_stylebox("hover_pressed", "FlatMenuButton", p_config.flat_button_hover_pressed);
p_theme->set_stylebox("disabled", "FlatMenuButton", p_config.base_empty_wide_style);
p_theme->set_type_variation("FlatButtonNoIconTint", "FlatButton");
p_theme->set_color("icon_pressed_color", "FlatButtonNoIconTint", p_config.icon_normal_color);
p_theme->set_color("icon_hover_color", "FlatButtonNoIconTint", p_config.mono_color);
p_theme->set_color("icon_hover_pressed_color", "FlatButtonNoIconTint", p_config.mono_color);
// Variation for Editor Log filter buttons.
p_theme->set_type_variation("EditorLogFilterButton", "Button");
@ -1879,10 +1897,10 @@ void ThemeModern::populate_editor_styles(const Ref<EditorTheme> &p_theme, Editor
p_theme->set_color("icon_hover_color", "EditorLogFilterButton", icon_hover_color);
p_theme->set_color("icon_hover_pressed_color", "EditorLogFilterButton", icon_hover_color);
// Hover and pressed styles are swapped for toggle buttons on purpose.
p_theme->set_stylebox(CoreStringName(normal), "EditorLogFilterButton", p_config.base_empty_style);
p_theme->set_stylebox(SceneStringName(hover), "EditorLogFilterButton", p_config.flat_button_pressed);
p_theme->set_stylebox(SceneStringName(pressed), "EditorLogFilterButton", p_config.flat_button_hover);
p_theme->set_stylebox(SceneStringName(hover), "EditorLogFilterButton", p_config.flat_button_hover);
p_theme->set_stylebox(SceneStringName(pressed), "EditorLogFilterButton", p_config.flat_button_pressed);
p_theme->set_stylebox("hover_pressed", "EditorLogFilterButton", p_config.flat_button_hover_pressed);
}
// Buttons styles that stand out against the panel background (e.g. AssetLib).
@ -2335,7 +2353,7 @@ void ThemeModern::populate_editor_styles(const Ref<EditorTheme> &p_theme, Editor
p_theme->set_stylebox(CoreStringName(normal), "EditorInspectorFlatButton", p_config.base_empty_wide_style);
p_theme->set_stylebox(SceneStringName(hover), "EditorInspectorFlatButton", p_config.flat_button_hover);
p_theme->set_stylebox(SceneStringName(pressed), "EditorInspectorFlatButton", p_config.flat_button_pressed);
p_theme->set_stylebox("hover_pressed", "EditorInspectorFlatButton", p_config.flat_button_pressed);
p_theme->set_stylebox("hover_pressed", "EditorInspectorFlatButton", p_config.flat_button_hover_pressed);
p_theme->set_stylebox("disabled", "EditorInspectorFlatButton", p_config.base_empty_wide_style);
// InspectorActionButton.