From 91ff34b5b569916479fdcb40430d10cb7f15401c Mon Sep 17 00:00:00 2001 From: Yuri Sizov Date: Mon, 3 Apr 2023 18:01:10 +0200 Subject: [PATCH 1/4] Add a warning when trying to access theme items too early --- scene/gui/control.cpp | 50 +++++++++++++++++++++++++++++++++++++++++++ scene/gui/control.h | 2 ++ scene/main/window.cpp | 50 +++++++++++++++++++++++++++++++++++++++++++ scene/main/window.h | 1 + 4 files changed, 103 insertions(+) diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index d320ff01b3d2..569b89f68853 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -2424,6 +2424,10 @@ StringName Control::get_theme_type_variation() const { /// Theme property lookup. Ref Control::get_theme_icon(const StringName &p_name, const StringName &p_theme_type) const { + if (!data.initialized) { + WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + } + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { const Ref *tex = data.theme_icon_override.getptr(p_name); if (tex) { @@ -2443,6 +2447,10 @@ Ref Control::get_theme_icon(const StringName &p_name, const StringNam } Ref Control::get_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const { + if (!data.initialized) { + WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + } + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { const Ref *style = data.theme_style_override.getptr(p_name); if (style) { @@ -2462,6 +2470,10 @@ Ref Control::get_theme_stylebox(const StringName &p_name, const String } Ref Control::get_theme_font(const StringName &p_name, const StringName &p_theme_type) const { + if (!data.initialized) { + WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + } + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { const Ref *font = data.theme_font_override.getptr(p_name); if (font) { @@ -2481,6 +2493,10 @@ Ref Control::get_theme_font(const StringName &p_name, const StringName &p_ } int Control::get_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const { + if (!data.initialized) { + WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + } + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { const int *font_size = data.theme_font_size_override.getptr(p_name); if (font_size && (*font_size) > 0) { @@ -2500,6 +2516,10 @@ int Control::get_theme_font_size(const StringName &p_name, const StringName &p_t } Color Control::get_theme_color(const StringName &p_name, const StringName &p_theme_type) const { + if (!data.initialized) { + WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + } + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { const Color *color = data.theme_color_override.getptr(p_name); if (color) { @@ -2519,6 +2539,10 @@ Color Control::get_theme_color(const StringName &p_name, const StringName &p_the } int Control::get_theme_constant(const StringName &p_name, const StringName &p_theme_type) const { + if (!data.initialized) { + WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + } + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { const int *constant = data.theme_constant_override.getptr(p_name); if (constant) { @@ -2538,6 +2562,10 @@ int Control::get_theme_constant(const StringName &p_name, const StringName &p_th } bool Control::has_theme_icon(const StringName &p_name, const StringName &p_theme_type) const { + if (!data.initialized) { + WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + } + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { if (has_theme_icon_override(p_name)) { return true; @@ -2550,6 +2578,10 @@ bool Control::has_theme_icon(const StringName &p_name, const StringName &p_theme } bool Control::has_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const { + if (!data.initialized) { + WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + } + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { if (has_theme_stylebox_override(p_name)) { return true; @@ -2562,6 +2594,10 @@ bool Control::has_theme_stylebox(const StringName &p_name, const StringName &p_t } bool Control::has_theme_font(const StringName &p_name, const StringName &p_theme_type) const { + if (!data.initialized) { + WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + } + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { if (has_theme_font_override(p_name)) { return true; @@ -2574,6 +2610,10 @@ bool Control::has_theme_font(const StringName &p_name, const StringName &p_theme } bool Control::has_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const { + if (!data.initialized) { + WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + } + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { if (has_theme_font_size_override(p_name)) { return true; @@ -2586,6 +2626,10 @@ bool Control::has_theme_font_size(const StringName &p_name, const StringName &p_ } bool Control::has_theme_color(const StringName &p_name, const StringName &p_theme_type) const { + if (!data.initialized) { + WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + } + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { if (has_theme_color_override(p_name)) { return true; @@ -2598,6 +2642,10 @@ bool Control::has_theme_color(const StringName &p_name, const StringName &p_them } bool Control::has_theme_constant(const StringName &p_name, const StringName &p_theme_type) const { + if (!data.initialized) { + WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + } + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { if (has_theme_constant_override(p_name)) { return true; @@ -2894,6 +2942,8 @@ Control *Control::make_custom_tooltip(const String &p_text) const { void Control::_notification(int p_notification) { switch (p_notification) { case NOTIFICATION_POSTINITIALIZE: { + data.initialized = true; + _invalidate_theme_cache(); _update_theme_item_cache(); } break; diff --git a/scene/gui/control.h b/scene/gui/control.h index da973783e99b..e36e2797155b 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -161,6 +161,8 @@ class Control : public CanvasItem { // This Data struct is to avoid namespace pollution in derived classes. struct Data { + bool initialized = false; + // Global relations. List::Element *RI = nullptr; diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 0588a116a8f0..dbc778deec2b 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -1073,6 +1073,8 @@ Viewport *Window::get_embedder() const { void Window::_notification(int p_what) { switch (p_what) { case NOTIFICATION_POSTINITIALIZE: { + initialized = true; + _invalidate_theme_cache(); _update_theme_item_cache(); } break; @@ -1754,6 +1756,10 @@ StringName Window::get_theme_type_variation() const { /// Theme property lookup. Ref Window::get_theme_icon(const StringName &p_name, const StringName &p_theme_type) const { + if (!initialized) { + WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + } + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { const Ref *tex = theme_icon_override.getptr(p_name); if (tex) { @@ -1773,6 +1779,10 @@ Ref Window::get_theme_icon(const StringName &p_name, const StringName } Ref Window::get_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const { + if (!initialized) { + WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + } + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { const Ref *style = theme_style_override.getptr(p_name); if (style) { @@ -1792,6 +1802,10 @@ Ref Window::get_theme_stylebox(const StringName &p_name, const StringN } Ref Window::get_theme_font(const StringName &p_name, const StringName &p_theme_type) const { + if (!initialized) { + WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + } + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { const Ref *font = theme_font_override.getptr(p_name); if (font) { @@ -1811,6 +1825,10 @@ Ref Window::get_theme_font(const StringName &p_name, const StringName &p_t } int Window::get_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const { + if (!initialized) { + WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + } + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { const int *font_size = theme_font_size_override.getptr(p_name); if (font_size && (*font_size) > 0) { @@ -1830,6 +1848,10 @@ int Window::get_theme_font_size(const StringName &p_name, const StringName &p_th } Color Window::get_theme_color(const StringName &p_name, const StringName &p_theme_type) const { + if (!initialized) { + WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + } + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { const Color *color = theme_color_override.getptr(p_name); if (color) { @@ -1849,6 +1871,10 @@ Color Window::get_theme_color(const StringName &p_name, const StringName &p_them } int Window::get_theme_constant(const StringName &p_name, const StringName &p_theme_type) const { + if (!initialized) { + WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + } + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { const int *constant = theme_constant_override.getptr(p_name); if (constant) { @@ -1868,6 +1894,10 @@ int Window::get_theme_constant(const StringName &p_name, const StringName &p_the } bool Window::has_theme_icon(const StringName &p_name, const StringName &p_theme_type) const { + if (!initialized) { + WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + } + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { if (has_theme_icon_override(p_name)) { return true; @@ -1880,6 +1910,10 @@ bool Window::has_theme_icon(const StringName &p_name, const StringName &p_theme_ } bool Window::has_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const { + if (!initialized) { + WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + } + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { if (has_theme_stylebox_override(p_name)) { return true; @@ -1892,6 +1926,10 @@ bool Window::has_theme_stylebox(const StringName &p_name, const StringName &p_th } bool Window::has_theme_font(const StringName &p_name, const StringName &p_theme_type) const { + if (!initialized) { + WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + } + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { if (has_theme_font_override(p_name)) { return true; @@ -1904,6 +1942,10 @@ bool Window::has_theme_font(const StringName &p_name, const StringName &p_theme_ } bool Window::has_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const { + if (!initialized) { + WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + } + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { if (has_theme_font_size_override(p_name)) { return true; @@ -1916,6 +1958,10 @@ bool Window::has_theme_font_size(const StringName &p_name, const StringName &p_t } bool Window::has_theme_color(const StringName &p_name, const StringName &p_theme_type) const { + if (!initialized) { + WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + } + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { if (has_theme_color_override(p_name)) { return true; @@ -1928,6 +1974,10 @@ bool Window::has_theme_color(const StringName &p_name, const StringName &p_theme } bool Window::has_theme_constant(const StringName &p_name, const StringName &p_theme_type) const { + if (!initialized) { + WARN_PRINT_ONCE("Attempting to access theme items too early; prefer NOTIFICATION_POSTINITIALIZE and NOTIFICATION_THEME_CHANGED"); + } + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { if (has_theme_constant_override(p_name)) { return true; diff --git a/scene/main/window.h b/scene/main/window.h index 00f10011d1af..1695a2278883 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -97,6 +97,7 @@ class Window : public Viewport { private: DisplayServer::WindowID window_id = DisplayServer::INVALID_WINDOW_ID; + bool initialized = false; String title; mutable int current_screen = 0; From db2f99cdc0aeac7834bc93c792ebb890077516e2 Mon Sep 17 00:00:00 2001 From: Yuri Sizov Date: Mon, 3 Apr 2023 18:01:10 +0200 Subject: [PATCH 2/4] Implement theme item cache in TextEdit and CodeEdit --- scene/gui/code_edit.cpp | 226 ++++++++++++++++---------------- scene/gui/code_edit.h | 70 ++++++---- scene/gui/text_edit.cpp | 278 +++++++++++++++++++++------------------- scene/gui/text_edit.h | 70 +++++----- 4 files changed, 348 insertions(+), 296 deletions(-) diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index 53e8b651ed62..60fe0c32b679 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -36,44 +36,10 @@ void CodeEdit::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_THEME_CHANGED: - case NOTIFICATION_ENTER_TREE: { - style_normal = get_theme_stylebox(SNAME("normal")); - - font = get_theme_font(SNAME("font")); - font_size = get_theme_font_size(SNAME("font_size")); - - line_spacing = get_theme_constant(SNAME("line_spacing")); - + case NOTIFICATION_THEME_CHANGED: { set_gutter_width(main_gutter, get_line_height()); - set_gutter_width(line_number_gutter, (line_number_digits + 1) * font->get_char_size('0', font_size).width); + set_gutter_width(line_number_gutter, (line_number_digits + 1) * theme_cache.font->get_char_size('0', theme_cache.font_size).width); set_gutter_width(fold_gutter, get_line_height() / 1.2); - - breakpoint_color = get_theme_color(SNAME("breakpoint_color")); - breakpoint_icon = get_theme_icon(SNAME("breakpoint")); - - bookmark_color = get_theme_color(SNAME("bookmark_color")); - bookmark_icon = get_theme_icon(SNAME("bookmark")); - - executing_line_color = get_theme_color(SNAME("executing_line_color")); - executing_line_icon = get_theme_icon(SNAME("executing_line")); - - line_number_color = get_theme_color(SNAME("line_number_color")); - - folding_color = get_theme_color(SNAME("code_folding_color")); - can_fold_icon = get_theme_icon(SNAME("can_fold")); - folded_icon = get_theme_icon(SNAME("folded")); - - code_completion_max_width = get_theme_constant(SNAME("completion_max_width")); - code_completion_max_lines = get_theme_constant(SNAME("completion_lines")); - code_completion_scroll_width = get_theme_constant(SNAME("completion_scroll_width")); - code_completion_scroll_color = get_theme_color(SNAME("completion_scroll_color")); - code_completion_scroll_hovered_color = get_theme_color(SNAME("completion_scroll_hovered_color")); - code_completion_background_color = get_theme_color(SNAME("completion_background_color")); - code_completion_selected_color = get_theme_color(SNAME("completion_selected_color")); - code_completion_existing_color = get_theme_color(SNAME("completion_existing_color")); - - line_length_guideline_color = get_theme_color(SNAME("line_length_guideline_color")); } break; case NOTIFICATION_DRAW: { @@ -84,14 +50,14 @@ void CodeEdit::_notification(int p_what) { const int row_height = get_line_height(); if (line_length_guideline_columns.size() > 0) { - const int xmargin_beg = style_normal->get_margin(SIDE_LEFT) + get_total_gutter_width(); - const int xmargin_end = size.width - style_normal->get_margin(SIDE_RIGHT) - (is_drawing_minimap() ? get_minimap_width() : 0); - const float char_size = font->get_char_size('0', font_size).width; + const int xmargin_beg = theme_cache.style_normal->get_margin(SIDE_LEFT) + get_total_gutter_width(); + const int xmargin_end = size.width - theme_cache.style_normal->get_margin(SIDE_RIGHT) - (is_drawing_minimap() ? get_minimap_width() : 0); + const float char_size = theme_cache.font->get_char_size('0', theme_cache.font_size).width; for (int i = 0; i < line_length_guideline_columns.size(); i++) { const int xoffset = xmargin_beg + char_size * (int)line_length_guideline_columns[i] - get_h_scroll(); if (xoffset > xmargin_beg && xoffset < xmargin_end) { - Color guideline_color = (i == 0) ? line_length_guideline_color : line_length_guideline_color * Color(1, 1, 1, 0.5); + Color guideline_color = (i == 0) ? theme_cache.line_length_guideline_color : theme_cache.line_length_guideline_color * Color(1, 1, 1, 0.5); if (rtl) { RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(size.width - xoffset, 0), Point2(size.width - xoffset, size.height), guideline_color); continue; @@ -103,45 +69,42 @@ void CodeEdit::_notification(int p_what) { bool code_completion_below = false; if (caret_visible && code_completion_active && code_completion_options.size() > 0) { - Ref csb = get_theme_stylebox(SNAME("completion")); - const int code_completion_options_count = code_completion_options.size(); - const int lines = MIN(code_completion_options_count, code_completion_max_lines); - const int icon_hsep = get_theme_constant(SNAME("h_separation"), SNAME("ItemList")); + const int lines = MIN(code_completion_options_count, theme_cache.code_completion_max_lines); const Size2 icon_area_size(row_height, row_height); - code_completion_rect.size.width = code_completion_longest_line + icon_hsep + icon_area_size.width + 2; + code_completion_rect.size.width = code_completion_longest_line + theme_cache.code_completion_icon_separation + icon_area_size.width + 2; code_completion_rect.size.height = lines * row_height; const Point2 caret_pos = get_caret_draw_pos(); - const int total_height = csb->get_minimum_size().y + code_completion_rect.size.height; + const int total_height = theme_cache.code_completion_style->get_minimum_size().y + code_completion_rect.size.height; const bool can_fit_completion_above = (caret_pos.y - row_height > total_height); const bool can_fit_completion_below = (caret_pos.y + row_height + total_height <= get_size().height); if (!can_fit_completion_below && can_fit_completion_above) { - code_completion_rect.position.y = (caret_pos.y - total_height - row_height) + line_spacing; + code_completion_rect.position.y = (caret_pos.y - total_height - row_height) + theme_cache.line_spacing; } else { - code_completion_rect.position.y = caret_pos.y + (line_spacing / 2.0f); + code_completion_rect.position.y = caret_pos.y + (theme_cache.line_spacing / 2.0f); code_completion_below = true; } - const int scroll_width = code_completion_options_count > code_completion_max_lines ? code_completion_scroll_width : 0; - const int code_completion_base_width = font->get_string_size(code_completion_base, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width; + const int scroll_width = code_completion_options_count > theme_cache.code_completion_max_lines ? theme_cache.code_completion_scroll_width : 0; + const int code_completion_base_width = theme_cache.font->get_string_size(code_completion_base, HORIZONTAL_ALIGNMENT_LEFT, -1, theme_cache.font_size).width; if (caret_pos.x - code_completion_base_width + code_completion_rect.size.width + scroll_width > get_size().width) { code_completion_rect.position.x = get_size().width - code_completion_rect.size.width - scroll_width; } else { code_completion_rect.position.x = caret_pos.x - code_completion_base_width; } - draw_style_box(csb, Rect2(code_completion_rect.position - csb->get_offset(), code_completion_rect.size + csb->get_minimum_size() + Size2(scroll_width, 0))); - if (code_completion_background_color.a > 0.01) { - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(code_completion_rect.position, code_completion_rect.size + Size2(scroll_width, 0)), code_completion_background_color); + draw_style_box(theme_cache.code_completion_style, Rect2(code_completion_rect.position - theme_cache.code_completion_style->get_offset(), code_completion_rect.size + theme_cache.code_completion_style->get_minimum_size() + Size2(scroll_width, 0))); + if (theme_cache.code_completion_background_color.a > 0.01) { + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(code_completion_rect.position, code_completion_rect.size + Size2(scroll_width, 0)), theme_cache.code_completion_background_color); } code_completion_scroll_rect.position = code_completion_rect.position + Vector2(code_completion_rect.size.width, 0); code_completion_scroll_rect.size = Vector2(scroll_width, code_completion_rect.size.height); code_completion_line_ofs = CLAMP((code_completion_force_item_center < 0 ? code_completion_current_selected : code_completion_force_item_center) - lines / 2, 0, code_completion_options_count - lines); - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(code_completion_rect.position.x, code_completion_rect.position.y + (code_completion_current_selected - code_completion_line_ofs) * row_height), Size2(code_completion_rect.size.width, row_height)), code_completion_selected_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(code_completion_rect.position.x, code_completion_rect.position.y + (code_completion_current_selected - code_completion_line_ofs) * row_height), Size2(code_completion_rect.size.width, row_height)), theme_cache.code_completion_selected_color); for (int i = 0; i < lines; i++) { int l = code_completion_line_ofs + i; @@ -149,7 +112,7 @@ void CodeEdit::_notification(int p_what) { Ref tl; tl.instantiate(); - tl->add_string(code_completion_options[l].display, font, font_size); + tl->add_string(code_completion_options[l].display, theme_cache.font, theme_cache.font_size); int yofs = (row_height - tl->get_size().y) / 2; Point2 title_pos(code_completion_rect.position.x, code_completion_rect.position.y + i * row_height + yofs); @@ -161,9 +124,9 @@ void CodeEdit::_notification(int p_what) { Size2 icon_size = icon_area.size * 0.7; icon->draw_rect(ci, Rect2(icon_area.position + (icon_area.size - icon_size) / 2, icon_size)); } - title_pos.x = icon_area.position.x + icon_area.size.width + icon_hsep; + title_pos.x = icon_area.position.x + icon_area.size.width + theme_cache.code_completion_icon_separation; - tl->set_width(code_completion_rect.size.width - (icon_area_size.x + icon_hsep)); + tl->set_width(code_completion_rect.size.width - (icon_area_size.x + theme_cache.code_completion_icon_separation)); if (rtl) { if (code_completion_options[l].default_value.get_type() == Variant::COLOR) { draw_rect(Rect2(Point2(code_completion_rect.position.x, icon_area.position.y), icon_area_size), (Color)code_completion_options[l].default_value); @@ -176,14 +139,14 @@ void CodeEdit::_notification(int p_what) { tl->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_LEFT); } - Point2 match_pos = Point2(code_completion_rect.position.x + icon_area_size.x + icon_hsep, code_completion_rect.position.y + i * row_height); + Point2 match_pos = Point2(code_completion_rect.position.x + icon_area_size.x + theme_cache.code_completion_icon_separation, code_completion_rect.position.y + i * row_height); for (int j = 0; j < code_completion_options[l].matches.size(); j++) { Pair match = code_completion_options[l].matches[j]; - int match_offset = font->get_string_size(code_completion_options[l].display.substr(0, match.first), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width; - int match_len = font->get_string_size(code_completion_options[l].display.substr(match.first, match.second), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width; + int match_offset = theme_cache.font->get_string_size(code_completion_options[l].display.substr(0, match.first), HORIZONTAL_ALIGNMENT_LEFT, -1, theme_cache.font_size).width; + int match_len = theme_cache.font->get_string_size(code_completion_options[l].display.substr(match.first, match.second), HORIZONTAL_ALIGNMENT_LEFT, -1, theme_cache.font_size).width; - draw_rect(Rect2(match_pos + Point2(match_offset, 0), Size2(match_len, row_height)), code_completion_existing_color); + draw_rect(Rect2(match_pos + Point2(match_offset, 0), Size2(match_len, row_height)), theme_cache.code_completion_existing_color); } tl->draw(ci, title_pos, code_completion_options[l].font_color); @@ -191,9 +154,9 @@ void CodeEdit::_notification(int p_what) { /* Draw a small scroll rectangle to show a position in the options. */ if (scroll_width) { - Color scroll_color = is_code_completion_scroll_hovered || is_code_completion_scroll_pressed ? code_completion_scroll_hovered_color : code_completion_scroll_color; + Color scroll_color = is_code_completion_scroll_hovered || is_code_completion_scroll_pressed ? theme_cache.code_completion_scroll_hovered_color : theme_cache.code_completion_scroll_color; - float r = (float)code_completion_max_lines / code_completion_options_count; + float r = (float)theme_cache.code_completion_max_lines / code_completion_options_count; float o = (float)code_completion_line_ofs / code_completion_options_count; draw_rect(Rect2(code_completion_rect.position.x + code_completion_rect.size.width, code_completion_rect.position.y + o * code_completion_rect.size.y, scroll_width, code_completion_rect.size.y * r), scroll_color); } @@ -201,31 +164,29 @@ void CodeEdit::_notification(int p_what) { /* Code hint */ if (caret_visible && !code_hint.is_empty() && (!code_completion_active || (code_completion_below != code_hint_draw_below))) { - const int font_height = font->get_height(font_size); - Ref sb = get_theme_stylebox(SNAME("panel"), SNAME("TooltipPanel")); - Color color = get_theme_color(SNAME("font_color"), SNAME("TooltipLabel")); + const int font_height = theme_cache.font->get_height(theme_cache.font_size); Vector code_hint_lines = code_hint.split("\n"); int line_count = code_hint_lines.size(); int max_width = 0; for (int i = 0; i < line_count; i++) { - max_width = MAX(max_width, font->get_string_size(code_hint_lines[i], HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x); + max_width = MAX(max_width, theme_cache.font->get_string_size(code_hint_lines[i], HORIZONTAL_ALIGNMENT_LEFT, -1, theme_cache.font_size).x); } - Size2 minsize = sb->get_minimum_size() + Size2(max_width, line_count * font_height + (line_spacing * line_count - 1)); + Size2 minsize = theme_cache.code_hint_style->get_minimum_size() + Size2(max_width, line_count * font_height + (theme_cache.line_spacing * line_count - 1)); - int offset = font->get_string_size(code_hint_lines[0].substr(0, code_hint_lines[0].find(String::chr(0xFFFF))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x; + int offset = theme_cache.font->get_string_size(code_hint_lines[0].substr(0, code_hint_lines[0].find(String::chr(0xFFFF))), HORIZONTAL_ALIGNMENT_LEFT, -1, theme_cache.font_size).x; if (code_hint_xpos == -0xFFFF) { code_hint_xpos = get_caret_draw_pos().x - offset; } Point2 hint_ofs = Vector2(code_hint_xpos, get_caret_draw_pos().y); if (code_hint_draw_below) { - hint_ofs.y += line_spacing / 2.0f; + hint_ofs.y += theme_cache.line_spacing / 2.0f; } else { - hint_ofs.y -= (minsize.y + row_height) - line_spacing; + hint_ofs.y -= (minsize.y + row_height) - theme_cache.line_spacing; } - draw_style_box(sb, Rect2(hint_ofs, minsize)); + draw_style_box(theme_cache.code_hint_style, Rect2(hint_ofs, minsize)); int yofs = 0; for (int i = 0; i < line_count; i++) { @@ -234,31 +195,80 @@ void CodeEdit::_notification(int p_what) { int begin = 0; int end = 0; if (line.contains(String::chr(0xFFFF))) { - begin = font->get_string_size(line.substr(0, line.find(String::chr(0xFFFF))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x; - end = font->get_string_size(line.substr(0, line.rfind(String::chr(0xFFFF))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x; + begin = theme_cache.font->get_string_size(line.substr(0, line.find(String::chr(0xFFFF))), HORIZONTAL_ALIGNMENT_LEFT, -1, theme_cache.font_size).x; + end = theme_cache.font->get_string_size(line.substr(0, line.rfind(String::chr(0xFFFF))), HORIZONTAL_ALIGNMENT_LEFT, -1, theme_cache.font_size).x; } - Point2 round_ofs = hint_ofs + sb->get_offset() + Vector2(0, font->get_ascent(font_size) + font_height * i + yofs); + Point2 round_ofs = hint_ofs + theme_cache.code_hint_style->get_offset() + Vector2(0, theme_cache.font->get_ascent(theme_cache.font_size) + font_height * i + yofs); round_ofs = round_ofs.round(); - draw_string(font, round_ofs, line.replace(String::chr(0xFFFF), ""), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, color); + draw_string(theme_cache.font, round_ofs, line.replace(String::chr(0xFFFF), ""), HORIZONTAL_ALIGNMENT_LEFT, -1, theme_cache.font_size, theme_cache.code_hint_color); if (end > 0) { // Draw an underline for the currently edited function parameter. - const Vector2 b = hint_ofs + sb->get_offset() + Vector2(begin, font_height + font_height * i + yofs); - draw_line(b, b + Vector2(end - begin, 0), color, 2); + const Vector2 b = hint_ofs + theme_cache.code_hint_style->get_offset() + Vector2(begin, font_height + font_height * i + yofs); + draw_line(b, b + Vector2(end - begin, 0), theme_cache.code_hint_color, 2); // Draw a translucent text highlight as well. const Rect2 highlight_rect = Rect2( b - Vector2(0, font_height), Vector2(end - begin, font_height)); - draw_rect(highlight_rect, color * Color(1, 1, 1, 0.2)); + draw_rect(highlight_rect, theme_cache.code_hint_color * Color(1, 1, 1, 0.2)); } - yofs += line_spacing; + yofs += theme_cache.line_spacing; } } } break; } } +void CodeEdit::_update_theme_item_cache() { + TextEdit::_update_theme_item_cache(); + + /* Gutters */ + theme_cache.code_folding_color = get_theme_color(SNAME("code_folding_color")); + theme_cache.can_fold_icon = get_theme_icon(SNAME("can_fold")); + theme_cache.folded_icon = get_theme_icon(SNAME("folded")); + theme_cache.folded_eol_icon = get_theme_icon(SNAME("folded_eol_icon")); + + theme_cache.breakpoint_color = get_theme_color(SNAME("breakpoint_color")); + theme_cache.breakpoint_icon = get_theme_icon(SNAME("breakpoint")); + + theme_cache.bookmark_color = get_theme_color(SNAME("bookmark_color")); + theme_cache.bookmark_icon = get_theme_icon(SNAME("bookmark")); + + theme_cache.executing_line_color = get_theme_color(SNAME("executing_line_color")); + theme_cache.executing_line_icon = get_theme_icon(SNAME("executing_line")); + + theme_cache.line_number_color = get_theme_color(SNAME("line_number_color")); + + /* Code Completion */ + theme_cache.code_completion_style = get_theme_stylebox(SNAME("completion")); + theme_cache.code_completion_icon_separation = get_theme_constant(SNAME("h_separation"), SNAME("ItemList")); + + theme_cache.code_completion_max_width = get_theme_constant(SNAME("completion_max_width")); + theme_cache.code_completion_max_lines = get_theme_constant(SNAME("completion_lines")); + theme_cache.code_completion_scroll_width = get_theme_constant(SNAME("completion_scroll_width")); + theme_cache.code_completion_scroll_color = get_theme_color(SNAME("completion_scroll_color")); + theme_cache.code_completion_scroll_hovered_color = get_theme_color(SNAME("completion_scroll_hovered_color")); + theme_cache.code_completion_background_color = get_theme_color(SNAME("completion_background_color")); + theme_cache.code_completion_selected_color = get_theme_color(SNAME("completion_selected_color")); + theme_cache.code_completion_existing_color = get_theme_color(SNAME("completion_existing_color")); + + /* Code hint */ + theme_cache.code_hint_style = get_theme_stylebox(SNAME("panel"), SNAME("TooltipPanel")); + theme_cache.code_hint_color = get_theme_color(SNAME("font_color"), SNAME("TooltipLabel")); + + /* Line length guideline */ + theme_cache.line_length_guideline_color = get_theme_color(SNAME("line_length_guideline_color")); + + /* Other visuals */ + theme_cache.style_normal = get_theme_stylebox(SNAME("normal")); + + theme_cache.font = get_theme_font(SNAME("font")); + theme_cache.font_size = get_theme_font_size(SNAME("font_size")); + + theme_cache.line_spacing = get_theme_constant(SNAME("line_spacing")); +} + void CodeEdit::gui_input(const Ref &p_gui_input) { Ref mb = p_gui_input; if (mb.is_valid()) { @@ -355,7 +365,7 @@ void CodeEdit::gui_input(const Ref &p_gui_input) { if (is_line_folded(line)) { int wrap_index = get_line_wrap_index_at_column(line, col); if (wrap_index == get_line_wrap_count(line)) { - int eol_icon_width = folded_eol_icon->get_width(); + int eol_icon_width = theme_cache.folded_eol_icon->get_width(); int left_margin = get_total_gutter_width() + eol_icon_width + get_line_width(line, wrap_index) - get_h_scroll(); if (mpos.x > left_margin && mpos.x <= left_margin + eol_icon_width + 3) { unfold_line(line); @@ -499,14 +509,14 @@ void CodeEdit::gui_input(const Ref &p_gui_input) { return; } if (k->is_action("ui_page_up", true)) { - code_completion_current_selected = MAX(0, code_completion_current_selected - code_completion_max_lines); + code_completion_current_selected = MAX(0, code_completion_current_selected - theme_cache.code_completion_max_lines); code_completion_force_item_center = -1; queue_redraw(); accept_event(); return; } if (k->is_action("ui_page_down", true)) { - code_completion_current_selected = MIN(code_completion_options.size() - 1, code_completion_current_selected + code_completion_max_lines); + code_completion_current_selected = MIN(code_completion_options.size() - 1, code_completion_current_selected + theme_cache.code_completion_max_lines); code_completion_force_item_center = -1; queue_redraw(); accept_event(); @@ -635,7 +645,7 @@ Control::CursorShape CodeEdit::get_cursor_shape(const Point2 &p_pos) const { if (line != -1 && is_line_folded(line)) { int wrap_index = get_line_wrap_index_at_column(line, col); if (wrap_index == get_line_wrap_count(line)) { - int eol_icon_width = folded_eol_icon->get_width(); + int eol_icon_width = theme_cache.folded_eol_icon->get_width(); int left_margin = get_total_gutter_width() + eol_icon_width + get_line_width(line, wrap_index) - get_h_scroll(); if (p_pos.x > left_margin && p_pos.x <= left_margin + eol_icon_width + 3) { return CURSOR_POINTING_HAND; @@ -1246,7 +1256,7 @@ bool CodeEdit::is_drawing_executing_lines_gutter() const { } void CodeEdit::_main_gutter_draw_callback(int p_line, int p_gutter, const Rect2 &p_region) { - if (draw_breakpoints && breakpoint_icon.is_valid()) { + if (draw_breakpoints && theme_cache.breakpoint_icon.is_valid()) { bool breakpointed = is_line_breakpointed(p_line); bool hovering = p_region.has_point(get_local_mouse_pos()); bool shift_pressed = Input::get_singleton()->is_key_pressed(Key::SHIFT); @@ -1254,18 +1264,18 @@ void CodeEdit::_main_gutter_draw_callback(int p_line, int p_gutter, const Rect2 if (breakpointed || (hovering && !is_dragging_cursor() && !shift_pressed)) { int padding = p_region.size.x / 6; - Color use_color = breakpoint_color; + Color use_color = theme_cache.breakpoint_color; if (hovering && !shift_pressed) { use_color = breakpointed ? use_color.lightened(0.3) : use_color.darkened(0.5); } Rect2 icon_region = p_region; icon_region.position += Point2(padding, padding); icon_region.size -= Point2(padding, padding) * 2; - breakpoint_icon->draw_rect(get_canvas_item(), icon_region, false, use_color); + theme_cache.breakpoint_icon->draw_rect(get_canvas_item(), icon_region, false, use_color); } } - if (draw_bookmarks && bookmark_icon.is_valid()) { + if (draw_bookmarks && theme_cache.bookmark_icon.is_valid()) { bool bookmarked = is_line_bookmarked(p_line); bool hovering = p_region.has_point(get_local_mouse_pos()); bool shift_pressed = Input::get_singleton()->is_key_pressed(Key::SHIFT); @@ -1274,25 +1284,25 @@ void CodeEdit::_main_gutter_draw_callback(int p_line, int p_gutter, const Rect2 int horizontal_padding = p_region.size.x / 2; int vertical_padding = p_region.size.y / 4; - Color use_color = bookmark_color; + Color use_color = theme_cache.bookmark_color; if (hovering && shift_pressed) { use_color = bookmarked ? use_color.lightened(0.3) : use_color.darkened(0.5); } Rect2 icon_region = p_region; icon_region.position += Point2(horizontal_padding, 0); icon_region.size -= Point2(horizontal_padding * 1.1, vertical_padding); - bookmark_icon->draw_rect(get_canvas_item(), icon_region, false, use_color); + theme_cache.bookmark_icon->draw_rect(get_canvas_item(), icon_region, false, use_color); } } - if (draw_executing_lines && is_line_executing(p_line) && executing_line_icon.is_valid()) { + if (draw_executing_lines && is_line_executing(p_line) && theme_cache.executing_line_icon.is_valid()) { int horizontal_padding = p_region.size.x / 10; int vertical_padding = p_region.size.y / 4; Rect2 icon_region = p_region; icon_region.position += Point2(horizontal_padding, vertical_padding); icon_region.size -= Point2(horizontal_padding, vertical_padding) * 2; - executing_line_icon->draw_rect(get_canvas_item(), icon_region, false, executing_line_color); + theme_cache.executing_line_icon->draw_rect(get_canvas_item(), icon_region, false, theme_cache.executing_line_color); } } @@ -1416,11 +1426,11 @@ void CodeEdit::_line_number_draw_callback(int p_line, int p_gutter, const Rect2 } Ref tl; tl.instantiate(); - tl->add_string(fc, font, font_size); + tl->add_string(fc, theme_cache.font, theme_cache.font_size); int yofs = p_region.position.y + (get_line_height() - tl->get_size().y) / 2; Color number_color = get_line_gutter_item_color(p_line, line_number_gutter); if (number_color == Color(1, 1, 1)) { - number_color = line_number_color; + number_color = theme_cache.line_number_color; } tl->draw(get_canvas_item(), Point2(p_region.position.x, yofs), number_color); } @@ -1448,10 +1458,10 @@ void CodeEdit::_fold_gutter_draw_callback(int p_line, int p_gutter, Rect2 p_regi p_region.size -= Point2(horizontal_padding, vertical_padding) * 2; if (can_fold_line(p_line)) { - can_fold_icon->draw_rect(get_canvas_item(), p_region, false, folding_color); + theme_cache.can_fold_icon->draw_rect(get_canvas_item(), p_region, false, theme_cache.code_folding_color); return; } - folded_icon->draw_rect(get_canvas_item(), p_region, false, folding_color); + theme_cache.folded_icon->draw_rect(get_canvas_item(), p_region, false, theme_cache.code_folding_color); } /* Line Folding */ @@ -2866,13 +2876,13 @@ void CodeEdit::_filter_code_completion_candidates_impl() { offset = line_height; } - if (font.is_valid()) { - max_width = MAX(max_width, font->get_string_size(option.display, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width + offset); + if (theme_cache.font.is_valid()) { + max_width = MAX(max_width, theme_cache.font->get_string_size(option.display, HORIZONTAL_ALIGNMENT_LEFT, -1, theme_cache.font_size).width + offset); } code_completion_options.push_back(option); } - code_completion_longest_line = MIN(max_width, code_completion_max_width * font_size); + code_completion_longest_line = MIN(max_width, theme_cache.code_completion_max_width * theme_cache.font_size); code_completion_current_selected = 0; code_completion_force_item_center = -1; code_completion_active = true; @@ -2987,8 +2997,8 @@ void CodeEdit::_filter_code_completion_candidates_impl() { if (string_to_complete.length() == 0) { code_completion_options.push_back(option); - if (font.is_valid()) { - max_width = MAX(max_width, font->get_string_size(option.display, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width + offset); + if (theme_cache.font.is_valid()) { + max_width = MAX(max_width, theme_cache.font->get_string_size(option.display, HORIZONTAL_ALIGNMENT_LEFT, -1, theme_cache.font_size).width + offset); } continue; } @@ -3095,8 +3105,8 @@ void CodeEdit::_filter_code_completion_candidates_impl() { option.matches.append_array(ssq_matches); completion_options_subseq.push_back(option); } - if (font.is_valid()) { - max_width = MAX(max_width, font->get_string_size(option.display, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width + offset); + if (theme_cache.font.is_valid()) { + max_width = MAX(max_width, theme_cache.font->get_string_size(option.display, HORIZONTAL_ALIGNMENT_LEFT, -1, theme_cache.font_size).width + offset); } } else if (!*ssq_lower) { // Matched the whole subsequence in s_lower. option.matches.clear(); @@ -3114,8 +3124,8 @@ void CodeEdit::_filter_code_completion_candidates_impl() { option.matches.append_array(ssq_lower_matches); completion_options_subseq_casei.push_back(option); } - if (font.is_valid()) { - max_width = MAX(max_width, font->get_string_size(option.display, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width + offset); + if (theme_cache.font.is_valid()) { + max_width = MAX(max_width, theme_cache.font->get_string_size(option.display, HORIZONTAL_ALIGNMENT_LEFT, -1, theme_cache.font_size).width + offset); } } } @@ -3138,7 +3148,7 @@ void CodeEdit::_filter_code_completion_candidates_impl() { return; } - code_completion_longest_line = MIN(max_width, code_completion_max_width * font_size); + code_completion_longest_line = MIN(max_width, theme_cache.code_completion_max_width * theme_cache.font_size); code_completion_current_selected = 0; code_completion_force_item_center = -1; code_completion_active = true; @@ -3174,8 +3184,8 @@ void CodeEdit::_text_changed() { line_number_digits++; } - if (font.is_valid()) { - set_gutter_width(line_number_gutter, (line_number_digits + 1) * font->get_char_size('0', font_size).width); + if (theme_cache.font.is_valid()) { + set_gutter_width(line_number_gutter, (line_number_digits + 1) * theme_cache.font->get_char_size('0', theme_cache.font_size).width); } lc = get_line_count(); diff --git a/scene/gui/code_edit.h b/scene/gui/code_edit.h index e26697106ede..ee73758bef76 100644 --- a/scene/gui/code_edit.h +++ b/scene/gui/code_edit.h @@ -93,32 +93,22 @@ class CodeEdit : public TextEdit { // breakpoints HashMap breakpointed_lines; bool draw_breakpoints = false; - Color breakpoint_color = Color(1, 1, 1); - Ref breakpoint_icon = Ref(); // bookmarks bool draw_bookmarks = false; - Color bookmark_color = Color(1, 1, 1); - Ref bookmark_icon = Ref(); // executing lines bool draw_executing_lines = false; - Color executing_line_color = Color(1, 1, 1); - Ref executing_line_icon = Ref(); /* Line numbers */ int line_number_gutter = -1; int line_number_digits = 1; String line_number_padding = " "; - Color line_number_color = Color(1, 1, 1); void _line_number_draw_callback(int p_line, int p_gutter, const Rect2 &p_region); /* Fold Gutter */ int fold_gutter = -1; bool draw_fold_gutter = false; - Color folding_color = Color(1, 1, 1); - Ref can_fold_icon = Ref(); - Ref folded_icon = Ref(); void _fold_gutter_draw_callback(int p_line, int p_gutter, Rect2 p_region); void _gutter_clicked(int p_line, int p_gutter); @@ -199,15 +189,6 @@ class CodeEdit : public TextEdit { bool code_completion_enabled = false; bool code_completion_forced = false; - int code_completion_max_width = 0; - int code_completion_max_lines = 7; - int code_completion_scroll_width = 0; - Color code_completion_scroll_color = Color(0, 0, 0, 0); - Color code_completion_scroll_hovered_color = Color(0, 0, 0, 0); - Color code_completion_background_color = Color(0, 0, 0, 0); - Color code_completion_selected_color = Color(0, 0, 0, 0); - Color code_completion_existing_color = Color(0, 0, 0, 0); - bool code_completion_active = false; bool is_code_completion_scroll_hovered = false; bool is_code_completion_scroll_pressed = false; @@ -230,7 +211,6 @@ class CodeEdit : public TextEdit { /* Line length guidelines */ TypedArray line_length_guideline_columns; - Color line_length_guideline_color; /* Symbol lookup */ bool symbol_lookup_on_click_enabled = false; @@ -240,12 +220,51 @@ class CodeEdit : public TextEdit { Point2i symbol_lookup_pos; /* Visual */ - Ref style_normal; + struct ThemeCache { + /* Gutters */ + Color code_folding_color = Color(1, 1, 1); + Ref can_fold_icon; + Ref folded_icon; + Ref folded_eol_icon; + + Color breakpoint_color = Color(1, 1, 1); + Ref breakpoint_icon = Ref(); + + Color bookmark_color = Color(1, 1, 1); + Ref bookmark_icon = Ref(); + + Color executing_line_color = Color(1, 1, 1); + Ref executing_line_icon = Ref(); + + Color line_number_color = Color(1, 1, 1); + + /* Code Completion */ + Ref code_completion_style; + int code_completion_icon_separation = 0; - Ref font; - int font_size = 16; + int code_completion_max_width = 0; + int code_completion_max_lines = 7; + int code_completion_scroll_width = 0; + Color code_completion_scroll_color = Color(0, 0, 0, 0); + Color code_completion_scroll_hovered_color = Color(0, 0, 0, 0); + Color code_completion_background_color = Color(0, 0, 0, 0); + Color code_completion_selected_color = Color(0, 0, 0, 0); + Color code_completion_existing_color = Color(0, 0, 0, 0); - int line_spacing = 1; + /* Code hint */ + Ref code_hint_style; + Color code_hint_color; + + /* Line length guideline */ + Color line_length_guideline_color; + + /* Other visuals */ + Ref style_normal; + + Ref font; + int font_size = 16; + int line_spacing = 1; + } theme_cache; /* Callbacks */ int lines_edited_changed = 0; @@ -258,9 +277,10 @@ class CodeEdit : public TextEdit { protected: void _notification(int p_what); - static void _bind_methods(); + virtual void _update_theme_item_cache() override; + /* Text manipulation */ // Overridable actions diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 3d898214781e..02dbb086ee18 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -417,6 +417,10 @@ void TextEdit::Text::move_gutters(int p_from_line, int p_to_line) { void TextEdit::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_POSTINITIALIZE: { + _update_caches(); + } break; + case NOTIFICATION_ENTER_TREE: { _update_caches(); if (caret_pos_dirty) { @@ -512,28 +516,28 @@ void TextEdit::_notification(int p_what) { RID ci = get_canvas_item(); RenderingServer::get_singleton()->canvas_item_set_clip(get_canvas_item(), true); - int xmargin_beg = style_normal->get_margin(SIDE_LEFT) + gutters_width + gutter_padding; + int xmargin_beg = theme_cache.style_normal->get_margin(SIDE_LEFT) + gutters_width + gutter_padding; - int xmargin_end = size.width - style_normal->get_margin(SIDE_RIGHT); + int xmargin_end = size.width - theme_cache.style_normal->get_margin(SIDE_RIGHT); if (draw_minimap) { xmargin_end -= minimap_width; } // Let's do it easy for now. - style_normal->draw(ci, Rect2(Point2(), size)); + theme_cache.style_normal->draw(ci, Rect2(Point2(), size)); if (!editable) { - style_readonly->draw(ci, Rect2(Point2(), size)); + theme_cache.style_readonly->draw(ci, Rect2(Point2(), size)); draw_caret = false; } if (has_focus()) { - style_focus->draw(ci, Rect2(Point2(), size)); + theme_cache.style_focus->draw(ci, Rect2(Point2(), size)); } int visible_rows = get_visible_line_count() + 1; - Color color = !editable ? font_readonly_color : font_color; + Color color = !editable ? theme_cache.font_readonly_color : theme_cache.font_color; - if (background_color.a > 0.01) { - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(), get_size()), background_color); + if (theme_cache.background_color.a > 0.01) { + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(), get_size()), theme_cache.background_color); } Vector brace_matching; @@ -734,7 +738,7 @@ void TextEdit::_notification(int p_what) { viewport_alpha = 0.1; } - const Color viewport_color = (background_color.get_v() < 0.5) ? Color(1, 1, 1, viewport_alpha) : Color(0, 0, 0, viewport_alpha); + const Color viewport_color = (theme_cache.background_color.get_v() < 0.5) ? Color(1, 1, 1, viewport_alpha) : Color(0, 0, 0, viewport_alpha); if (rtl) { RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - (xmargin_end + 2) - minimap_width, viewport_offset_y, minimap_width, viewport_height), viewport_color); } else { @@ -763,9 +767,9 @@ void TextEdit::_notification(int p_what) { Color line_background_color = text.get_line_background_color(minimap_line); line_background_color.a *= 0.6; - Color current_color = font_color; + Color current_color = theme_cache.font_color; if (!editable) { - current_color = font_readonly_color; + current_color = theme_cache.font_readonly_color; } Vector wrap_rows = get_line_wrapped_text(minimap_line); @@ -793,9 +797,9 @@ void TextEdit::_notification(int p_what) { if (caret_line_wrap_index_map.has(minimap_line) && caret_line_wrap_index_map[minimap_line].has(line_wrap_index) && highlight_current_line) { if (rtl) { - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - (xmargin_end + 2) - minimap_width, i * 3, minimap_width, 2), current_line_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - (xmargin_end + 2) - minimap_width, i * 3, minimap_width, 2), theme_cache.current_line_color); } else { - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2((xmargin_end + 2), i * 3, minimap_width, 2), current_line_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2((xmargin_end + 2), i * 3, minimap_width, 2), theme_cache.current_line_color); } } else if (line_background_color != Color(0, 0, 0, 0)) { if (rtl) { @@ -811,9 +815,9 @@ void TextEdit::_notification(int p_what) { for (int j = 0; j < str.length(); j++) { const Variant *color_data = color_map.getptr(last_wrap_column + j); if (color_data != nullptr) { - current_color = (color_data->operator Dictionary()).get("color", font_color); + current_color = (color_data->operator Dictionary()).get("color", theme_cache.font_color); if (!editable) { - current_color.a = font_readonly_color.a; + current_color.a = theme_cache.font_readonly_color.a; } } color = current_color; @@ -875,16 +879,16 @@ void TextEdit::_notification(int p_what) { int top_limit_y = 0; int bottom_limit_y = get_size().height; if (!editable) { - top_limit_y += style_readonly->get_margin(SIDE_TOP); - bottom_limit_y -= style_readonly->get_margin(SIDE_BOTTOM); + top_limit_y += theme_cache.style_readonly->get_margin(SIDE_TOP); + bottom_limit_y -= theme_cache.style_readonly->get_margin(SIDE_BOTTOM); } else { - top_limit_y += style_normal->get_margin(SIDE_TOP); - bottom_limit_y -= style_normal->get_margin(SIDE_BOTTOM); + top_limit_y += theme_cache.style_normal->get_margin(SIDE_TOP); + bottom_limit_y -= theme_cache.style_normal->get_margin(SIDE_BOTTOM); } // Draw main text. line_drawing_cache.clear(); - int row_height = draw_placeholder ? placeholder_line_height + line_spacing : get_line_height(); + int row_height = draw_placeholder ? placeholder_line_height + theme_cache.line_spacing : get_line_height(); int line = first_vis_line; for (int i = 0; i < draw_amount; i++) { line++; @@ -909,9 +913,9 @@ void TextEdit::_notification(int p_what) { Dictionary color_map = _get_line_syntax_highlighting(line); // Ensure we at least use the font color. - Color current_color = !editable ? font_readonly_color : font_color; + Color current_color = !editable ? theme_cache.font_readonly_color : theme_cache.font_color; if (draw_placeholder) { - current_color = font_placeholder_color; + current_color = theme_cache.font_placeholder_color; } const Ref ldata = draw_placeholder ? placeholder_data_buf : text.get_line_data(line); @@ -933,14 +937,14 @@ void TextEdit::_notification(int p_what) { int ofs_x = 0; int ofs_y = 0; if (!editable) { - ofs_x = style_readonly->get_offset().x / 2; - ofs_x -= style_normal->get_offset().x / 2; - ofs_y = style_readonly->get_offset().y / 2; + ofs_x = theme_cache.style_readonly->get_offset().x / 2; + ofs_x -= theme_cache.style_normal->get_offset().x / 2; + ofs_y = theme_cache.style_readonly->get_offset().y / 2; } else { - ofs_y = style_normal->get_offset().y / 2; + ofs_y = theme_cache.style_normal->get_offset().y / 2; } - ofs_y += i * row_height + line_spacing / 2; + ofs_y += i * row_height + theme_cache.line_spacing / 2; ofs_y -= first_visible_line_wrap_ofs * row_height; ofs_y -= _get_v_scroll_offset() * row_height; @@ -969,20 +973,20 @@ void TextEdit::_notification(int p_what) { // Draw line background if empty as we won't loop at all. if (caret_line_wrap_index_map.has(line) && caret_line_wrap_index_map[line].has(line_wrap_index) && highlight_current_line) { if (rtl) { - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - ofs_x - xmargin_end, ofs_y, xmargin_end, row_height), current_line_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - ofs_x - xmargin_end, ofs_y, xmargin_end, row_height), theme_cache.current_line_color); } else { - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(ofs_x, ofs_y, xmargin_end, row_height), current_line_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(ofs_x, ofs_y, xmargin_end, row_height), theme_cache.current_line_color); } } // Give visual indication of empty selected line. for (int c = 0; c < carets.size(); c++) { if (has_selection(c) && line >= get_selection_from_line(c) && line <= get_selection_to_line(c) && char_margin >= xmargin_beg) { - float char_w = font->get_char_size(' ', font_size).width; + float char_w = theme_cache.font->get_char_size(' ', theme_cache.font_size).width; if (rtl) { - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - xmargin_beg - ofs_x - char_w, ofs_y, char_w, row_height), selection_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - xmargin_beg - ofs_x - char_w, ofs_y, char_w, row_height), theme_cache.selection_color); } else { - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, char_w, row_height), selection_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, char_w, row_height), theme_cache.selection_color); } } } @@ -990,9 +994,9 @@ void TextEdit::_notification(int p_what) { // If it has text, then draw current line marker in the margin, as line number etc will draw over it, draw the rest of line marker later. if (caret_line_wrap_index_map.has(line) && caret_line_wrap_index_map[line].has(line_wrap_index) && highlight_current_line) { if (rtl) { - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - ofs_x - xmargin_end, ofs_y, xmargin_end, row_height), current_line_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - ofs_x - xmargin_end, ofs_y, xmargin_end, row_height), theme_cache.current_line_color); } else { - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(ofs_x, ofs_y, xmargin_end, row_height), current_line_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(ofs_x, ofs_y, xmargin_end, row_height), theme_cache.current_line_color); } } } @@ -1002,7 +1006,7 @@ void TextEdit::_notification(int p_what) { cache_entry.y_offset = ofs_y; - int gutter_offset = style_normal->get_margin(SIDE_LEFT); + int gutter_offset = theme_cache.style_normal->get_margin(SIDE_LEFT); for (int g = 0; g < gutters.size(); g++) { const GutterInfo gutter = gutters[g]; @@ -1019,11 +1023,11 @@ void TextEdit::_notification(int p_what) { Ref tl; tl.instantiate(); - tl->add_string(txt, font, font_size); + tl->add_string(txt, theme_cache.font, theme_cache.font_size); int yofs = ofs_y + (row_height - tl->get_size().y) / 2; - if (outline_size > 0 && outline_color.a > 0) { - tl->draw_outline(ci, Point2(gutter_offset + ofs_x, yofs), outline_size, outline_color); + if (theme_cache.outline_size > 0 && theme_cache.outline_color.a > 0) { + tl->draw_outline(ci, Point2(gutter_offset + ofs_x, yofs), theme_cache.outline_size, theme_cache.outline_color); } tl->draw(ci, Point2(gutter_offset + ofs_x, yofs), get_line_gutter_item_color(line, g)); } break; @@ -1100,7 +1104,7 @@ void TextEdit::_notification(int p_what) { if (rect.position.x + rect.size.x > xmargin_end) { rect.size.x = xmargin_end - rect.position.x; } - draw_rect(rect, selection_color, true); + draw_rect(rect, theme_cache.selection_color, true); } } } @@ -1122,8 +1126,8 @@ void TextEdit::_notification(int p_what) { } else if (rect.position.x + rect.size.x > xmargin_end) { rect.size.x = xmargin_end - rect.position.x; } - draw_rect(rect, search_result_color, true); - draw_rect(rect, search_result_border_color, false); + draw_rect(rect, theme_cache.search_result_color, true); + draw_rect(rect, theme_cache.search_result_border_color, false); } search_text_col = _get_column_pos_of_word(search_text, str, search_flags, search_text_col + search_text_len); @@ -1146,7 +1150,7 @@ void TextEdit::_notification(int p_what) { } else if (rect.position.x + rect.size.x > xmargin_end) { rect.size.x = xmargin_end - rect.position.x; } - draw_rect(rect, word_highlighted_color); + draw_rect(rect, theme_cache.word_highlighted_color); } highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, highlighted_text_col + highlighted_text_len); @@ -1160,7 +1164,7 @@ void TextEdit::_notification(int p_what) { while (lookup_symbol_word_col != -1) { Vector sel = TS->shaped_text_get_selection(rid, lookup_symbol_word_col + start, lookup_symbol_word_col + lookup_symbol_word_len + start); for (int j = 0; j < sel.size(); j++) { - Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y + (line_spacing / 2), sel[j].y - sel[j].x, row_height); + Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y + (theme_cache.line_spacing / 2), sel[j].y - sel[j].x, row_height); if (rect.position.x + rect.size.x <= xmargin_beg || rect.position.x > xmargin_end) { continue; } @@ -1170,8 +1174,8 @@ void TextEdit::_notification(int p_what) { } else if (rect.position.x + rect.size.x > xmargin_end) { rect.size.x = xmargin_end - rect.position.x; } - rect.position.y += ceil(TS->shaped_text_get_ascent(rid)) + ceil(font->get_underline_position(font_size)); - rect.size.y = MAX(1, font->get_underline_thickness(font_size)); + rect.position.y += ceil(TS->shaped_text_get_ascent(rid)) + ceil(theme_cache.font->get_underline_position(theme_cache.font_size)); + rect.size.y = MAX(1, theme_cache.font->get_underline_thickness(theme_cache.font_size)); draw_rect(rect, color); } @@ -1191,12 +1195,12 @@ void TextEdit::_notification(int p_what) { int last_visible_char = TS->shaped_text_get_range(rid).x; float char_ofs = 0; - if (outline_size > 0 && outline_color.a > 0) { + if (theme_cache.outline_size > 0 && theme_cache.outline_color.a > 0) { for (int j = 0; j < gl_size; j++) { for (int k = 0; k < glyphs[j].repeat; k++) { if ((char_ofs + char_margin) >= xmargin_beg && (char_ofs + glyphs[j].advance + char_margin) <= xmargin_end) { if (glyphs[j].font_rid != RID()) { - TS->font_draw_glyph_outline(glyphs[j].font_rid, ci, glyphs[j].font_size, outline_size, Vector2(char_margin + char_ofs + ofs_x + glyphs[j].x_off, ofs_y + glyphs[j].y_off), glyphs[j].index, outline_color); + TS->font_draw_glyph_outline(glyphs[j].font_rid, ci, glyphs[j].font_size, theme_cache.outline_size, Vector2(char_margin + char_ofs + ofs_x + glyphs[j].x_off, ofs_y + glyphs[j].y_off), glyphs[j].index, theme_cache.outline_color); } } char_ofs += glyphs[j].advance; @@ -1218,9 +1222,9 @@ void TextEdit::_notification(int p_what) { } const Variant *color_data = (color_start >= 0) ? color_map.getptr(color_start) : nullptr; if (color_data != nullptr) { - current_color = (color_data->operator Dictionary()).get("color", font_color); - if (!editable && current_color.a > font_readonly_color.a) { - current_color.a = font_readonly_color.a; + current_color = (color_data->operator Dictionary()).get("color", theme_cache.font_color); + if (!editable && current_color.a > theme_cache.font_readonly_color.a) { + current_color.a = theme_cache.font_readonly_color.a; } } Color gl_color = current_color; @@ -1231,7 +1235,7 @@ void TextEdit::_notification(int p_what) { int sel_to = (line < get_selection_to_line(c)) ? TS->shaped_text_get_range(rid).y : get_selection_to_column(c); if (glyphs[j].start >= sel_from && glyphs[j].end <= sel_to && use_selected_font_color) { - gl_color = font_selected_color; + gl_color = theme_cache.font_selected_color; } } } @@ -1243,30 +1247,30 @@ void TextEdit::_notification(int p_what) { if ((brace_matching[c].open_match_line == line && brace_matching[c].open_match_column == glyphs[j].start) || (get_caret_column(c) == glyphs[j].start && get_caret_line(c) == line && carets_wrap_index[c] == line_wrap_index && (brace_matching[c].open_matching || brace_matching[c].open_mismatch))) { if (brace_matching[c].open_mismatch) { - gl_color = brace_mismatch_color; + gl_color = theme_cache.brace_mismatch_color; } - Rect2 rect = Rect2(char_pos, ofs_y + font->get_underline_position(font_size), glyphs[j].advance * glyphs[j].repeat, MAX(font->get_underline_thickness(font_size) * get_theme_default_base_scale(), 1)); + Rect2 rect = Rect2(char_pos, ofs_y + theme_cache.font->get_underline_position(theme_cache.font_size), glyphs[j].advance * glyphs[j].repeat, MAX(theme_cache.font->get_underline_thickness(theme_cache.font_size) * theme_cache.base_scale, 1)); draw_rect(rect, gl_color); } if ((brace_matching[c].close_match_line == line && brace_matching[c].close_match_column == glyphs[j].start) || (get_caret_column(c) == glyphs[j].start + 1 && get_caret_line(c) == line && carets_wrap_index[c] == line_wrap_index && (brace_matching[c].close_matching || brace_matching[c].close_mismatch))) { if (brace_matching[c].close_mismatch) { - gl_color = brace_mismatch_color; + gl_color = theme_cache.brace_mismatch_color; } - Rect2 rect = Rect2(char_pos, ofs_y + font->get_underline_position(font_size), glyphs[j].advance * glyphs[j].repeat, MAX(font->get_underline_thickness(font_size) * get_theme_default_base_scale(), 1)); + Rect2 rect = Rect2(char_pos, ofs_y + theme_cache.font->get_underline_position(theme_cache.font_size), glyphs[j].advance * glyphs[j].repeat, MAX(theme_cache.font->get_underline_thickness(theme_cache.font_size) * theme_cache.base_scale, 1)); draw_rect(rect, gl_color); } } } if (draw_tabs && ((glyphs[j].flags & TextServer::GRAPHEME_IS_TAB) == TextServer::GRAPHEME_IS_TAB)) { - int yofs = (text_height - tab_icon->get_height()) / 2 - ldata->get_line_ascent(line_wrap_index); - tab_icon->draw(ci, Point2(char_pos, ofs_y + yofs), gl_color); + int yofs = (text_height - theme_cache.tab_icon->get_height()) / 2 - ldata->get_line_ascent(line_wrap_index); + theme_cache.tab_icon->draw(ci, Point2(char_pos, ofs_y + yofs), gl_color); } else if (draw_spaces && ((glyphs[j].flags & TextServer::GRAPHEME_IS_SPACE) == TextServer::GRAPHEME_IS_SPACE) && ((glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL)) { - int yofs = (text_height - space_icon->get_height()) / 2 - ldata->get_line_ascent(line_wrap_index); - int xofs = (glyphs[j].advance * glyphs[j].repeat - space_icon->get_width()) / 2; - space_icon->draw(ci, Point2(char_pos + xofs, ofs_y + yofs), gl_color); + int yofs = (text_height - theme_cache.space_icon->get_height()) / 2 - ldata->get_line_ascent(line_wrap_index); + int xofs = (glyphs[j].advance * glyphs[j].repeat - theme_cache.space_icon->get_width()) / 2; + theme_cache.space_icon->draw(ci, Point2(char_pos + xofs, ofs_y + yofs), gl_color); } } @@ -1302,18 +1306,18 @@ void TextEdit::_notification(int p_what) { // is_line_folded if (line_wrap_index == line_wrap_amount && line < text.size() - 1 && _is_line_hidden(line + 1)) { - int xofs = char_ofs + char_margin + ofs_x + (folded_eol_icon->get_width() / 2); + int xofs = char_ofs + char_margin + ofs_x + (theme_cache.folded_eol_icon->get_width() / 2); if (xofs >= xmargin_beg && xofs < xmargin_end) { - int yofs = (text_height - folded_eol_icon->get_height()) / 2 - ldata->get_line_ascent(line_wrap_index); - Color eol_color = code_folding_color; + int yofs = (text_height - theme_cache.folded_eol_icon->get_height()) / 2 - ldata->get_line_ascent(line_wrap_index); + Color eol_color = theme_cache.code_folding_color; eol_color.a = 1; - folded_eol_icon->draw(ci, Point2(xofs, ofs_y + yofs), eol_color); + theme_cache.folded_eol_icon->draw(ci, Point2(xofs, ofs_y + yofs), eol_color); } } // Carets. // Prevent carets from disappearing at theme scales below 1.0 (if the caret width is 1). - const int caret_width = get_theme_constant(SNAME("caret_width")) * MAX(1, get_theme_default_base_scale()); + const int caret_width = theme_cache.caret_width * MAX(1, theme_cache.base_scale); for (int c = 0; c < carets.size(); c++) { if (!clipped && get_caret_line(c) == line && carets_wrap_index[c] == line_wrap_index) { @@ -1327,7 +1331,7 @@ void TextEdit::_notification(int p_what) { ts_caret = TS->shaped_text_get_carets(rid, ime_text.is_empty() ? get_caret_column(c) : get_caret_column(c) + ime_selection.x); } else { // No carets, add one at the start. - int h = font->get_height(font_size); + int h = theme_cache.font->get_height(theme_cache.font_size); if (rtl) { ts_caret.l_dir = TextServer::DIRECTION_RTL; ts_caret.l_caret = Rect2(Vector2(xmargin_end - char_margin + ofs_x, -h / 2), Size2(caret_width * 4, h)); @@ -1348,7 +1352,7 @@ void TextEdit::_notification(int p_what) { if (draw_caret || drag_caret_force_displayed) { if (caret_type == CaretType::CARET_TYPE_BLOCK || overtype_mode) { //Block or underline caret, draw trailing carets at full height. - int h = font->get_height(font_size); + int h = theme_cache.font->get_height(theme_cache.font_size); if (ts_caret.t_caret != Rect2()) { if (overtype_mode) { @@ -1359,17 +1363,17 @@ void TextEdit::_notification(int p_what) { ts_caret.t_caret.size.y = h; } ts_caret.t_caret.position += Vector2(char_margin + ofs_x, ofs_y); - draw_rect(ts_caret.t_caret, caret_color, overtype_mode); + draw_rect(ts_caret.t_caret, theme_cache.caret_color, overtype_mode); if (ts_caret.l_caret != Rect2() && ts_caret.l_dir != ts_caret.t_dir) { // Draw split caret (leading part). ts_caret.l_caret.position += Vector2(char_margin + ofs_x, ofs_y); ts_caret.l_caret.size.x = caret_width; - draw_rect(ts_caret.l_caret, caret_color); + draw_rect(ts_caret.l_caret, theme_cache.caret_color); // Draw extra direction marker on top of split caret. float d = (ts_caret.l_dir == TextServer::DIRECTION_LTR) ? 0.5 : -3; Rect2 trect = Rect2(ts_caret.l_caret.position.x + d * caret_width, ts_caret.l_caret.position.y + ts_caret.l_caret.size.y - caret_width, 3 * caret_width, caret_width); - RenderingServer::get_singleton()->canvas_item_add_rect(ci, trect, caret_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, trect, theme_cache.caret_color); } } else { // End of the line. if (gl_size > 0) { @@ -1386,7 +1390,7 @@ void TextEdit::_notification(int p_what) { ts_caret.l_caret.size.y = caret_width; } if (Math::ceil(ts_caret.l_caret.position.x) >= TS->shaped_text_get_size(rid).x) { - ts_caret.l_caret.size.x = font->get_char_size('m', font_size).x; + ts_caret.l_caret.size.x = theme_cache.font->get_char_size('m', theme_cache.font_size).x; } else { ts_caret.l_caret.size.x = 3 * caret_width; } @@ -1394,7 +1398,7 @@ void TextEdit::_notification(int p_what) { if (ts_caret.l_dir == TextServer::DIRECTION_RTL) { ts_caret.l_caret.position.x -= ts_caret.l_caret.size.x; } - draw_rect(ts_caret.l_caret, caret_color, overtype_mode); + draw_rect(ts_caret.l_caret, theme_cache.caret_color, overtype_mode); } } else { // Normal caret. @@ -1402,28 +1406,28 @@ void TextEdit::_notification(int p_what) { // Draw extra marker on top of mid caret. Rect2 trect = Rect2(ts_caret.l_caret.position.x - 2.5 * caret_width, ts_caret.l_caret.position.y, 6 * caret_width, caret_width); trect.position += Vector2(char_margin + ofs_x, ofs_y); - RenderingServer::get_singleton()->canvas_item_add_rect(ci, trect, caret_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, trect, theme_cache.caret_color); } else if (ts_caret.l_caret != Rect2() && ts_caret.t_caret != Rect2() && ts_caret.l_dir != ts_caret.t_dir) { // Draw extra direction marker on top of split caret. float d = (ts_caret.l_dir == TextServer::DIRECTION_LTR) ? 0.5 : -3; Rect2 trect = Rect2(ts_caret.l_caret.position.x + d * caret_width, ts_caret.l_caret.position.y + ts_caret.l_caret.size.y - caret_width, 3 * caret_width, caret_width); trect.position += Vector2(char_margin + ofs_x, ofs_y); - RenderingServer::get_singleton()->canvas_item_add_rect(ci, trect, caret_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, trect, theme_cache.caret_color); d = (ts_caret.t_dir == TextServer::DIRECTION_LTR) ? 0.5 : -3; trect = Rect2(ts_caret.t_caret.position.x + d * caret_width, ts_caret.t_caret.position.y, 3 * caret_width, caret_width); trect.position += Vector2(char_margin + ofs_x, ofs_y); - RenderingServer::get_singleton()->canvas_item_add_rect(ci, trect, caret_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, trect, theme_cache.caret_color); } ts_caret.l_caret.position += Vector2(char_margin + ofs_x, ofs_y); ts_caret.l_caret.size.x = caret_width; - draw_rect(ts_caret.l_caret, caret_color); + draw_rect(ts_caret.l_caret, theme_cache.caret_color); ts_caret.t_caret.position += Vector2(char_margin + ofs_x, ofs_y); ts_caret.t_caret.size.x = caret_width; - draw_rect(ts_caret.t_caret, caret_color); + draw_rect(ts_caret.t_caret, theme_cache.caret_color); } } } @@ -1444,7 +1448,7 @@ void TextEdit::_notification(int p_what) { rect.size.x = xmargin_end - rect.position.x; } rect.size.y = caret_width; - draw_rect(rect, caret_color); + draw_rect(rect, theme_cache.caret_color); carets.write[c].draw_pos.x = rect.position.x; } } @@ -1463,7 +1467,7 @@ void TextEdit::_notification(int p_what) { rect.size.x = xmargin_end - rect.position.x; } rect.size.y = caret_width * 3; - draw_rect(rect, caret_color); + draw_rect(rect, theme_cache.caret_color); carets.write[c].draw_pos.x = rect.position.x; } } @@ -1711,7 +1715,7 @@ void TextEdit::gui_input(const Ref &p_gui_input) { int row = pos.y; int col = pos.x; - int left_margin = style_normal->get_margin(SIDE_LEFT); + int left_margin = theme_cache.style_normal->get_margin(SIDE_LEFT); for (int i = 0; i < gutters.size(); i++) { if (!gutters[i].draw || gutters[i].width <= 0) { continue; @@ -1956,7 +1960,7 @@ void TextEdit::gui_input(const Ref &p_gui_input) { // Check if user is hovering a different gutter, and update if yes. Vector2i current_hovered_gutter = Vector2i(-1, -1); - int left_margin = style_normal->get_margin(SIDE_LEFT); + int left_margin = theme_cache.style_normal->get_margin(SIDE_LEFT); if (mpos.x <= left_margin + gutters_width + gutter_padding) { int hovered_row = get_line_column_at_pos(mpos).y; for (int i = 0; i < gutters.size(); i++) { @@ -2919,7 +2923,7 @@ void TextEdit::_get_above_below_caret_line_column(int p_old_line, int p_old_wrap } void TextEdit::_update_placeholder() { - if (font.is_null() || font_size <= 0) { + if (theme_cache.font.is_null() || theme_cache.font_size <= 0) { return; // Not in tree? } @@ -2928,7 +2932,7 @@ void TextEdit::_update_placeholder() { placeholder_data_buf->set_width(text.get_width()); placeholder_data_buf->set_direction((TextServer::Direction)text_direction); placeholder_data_buf->set_preserve_control(draw_control_chars); - placeholder_data_buf->add_string(placeholder_text, font, font_size, language); + placeholder_data_buf->add_string(placeholder_text, theme_cache.font, theme_cache.font_size, language); placeholder_bidi_override = structured_text_parser(st_parser, st_args, placeholder_text); if (placeholder_bidi_override.is_empty()) { @@ -2937,13 +2941,13 @@ void TextEdit::_update_placeholder() { if (get_tab_size() > 0) { Vector tabs; - tabs.push_back(font->get_char_size(' ', font_size).width * get_tab_size()); + tabs.push_back(theme_cache.font->get_char_size(' ', theme_cache.font_size).width * get_tab_size()); placeholder_data_buf->tab_align(tabs); } // Update height. const int wrap_amount = placeholder_data_buf->get_line_count() - 1; - placeholder_line_height = font->get_height(font_size); + placeholder_line_height = theme_cache.font->get_height(theme_cache.font_size); for (int i = 0; i <= wrap_amount; i++) { placeholder_line_height = MAX(placeholder_line_height, placeholder_data_buf->get_line_size(i).y); } @@ -2959,48 +2963,55 @@ void TextEdit::_update_placeholder() { } } -void TextEdit::_update_caches() { - /* Internal API for CodeEdit. */ - brace_mismatch_color = get_theme_color(SNAME("brace_mismatch_color"), SNAME("CodeEdit")); - code_folding_color = get_theme_color(SNAME("code_folding_color"), SNAME("CodeEdit")); - folded_eol_icon = get_theme_icon(SNAME("folded_eol_icon"), SNAME("CodeEdit")); +void TextEdit::_update_theme_item_cache() { + Control::_update_theme_item_cache(); + + theme_cache.base_scale = get_theme_default_base_scale(); + + /* Internal API for CodeEdit */ + theme_cache.brace_mismatch_color = get_theme_color(SNAME("brace_mismatch_color"), SNAME("CodeEdit")); + theme_cache.code_folding_color = get_theme_color(SNAME("code_folding_color"), SNAME("CodeEdit")); + theme_cache.folded_eol_icon = get_theme_icon(SNAME("folded_eol_icon"), SNAME("CodeEdit")); /* Search */ - search_result_color = get_theme_color(SNAME("search_result_color")); - search_result_border_color = get_theme_color(SNAME("search_result_border_color")); + theme_cache.search_result_color = get_theme_color(SNAME("search_result_color")); + theme_cache.search_result_border_color = get_theme_color(SNAME("search_result_border_color")); /* Caret */ - caret_color = get_theme_color(SNAME("caret_color")); - caret_background_color = get_theme_color(SNAME("caret_background_color")); + theme_cache.caret_width = get_theme_constant(SNAME("caret_width")); + theme_cache.caret_color = get_theme_color(SNAME("caret_color")); + theme_cache.caret_background_color = get_theme_color(SNAME("caret_background_color")); /* Selection */ - font_selected_color = get_theme_color(SNAME("font_selected_color")); - selection_color = get_theme_color(SNAME("selection_color")); - use_selected_font_color = font_selected_color != Color(0, 0, 0, 0); + theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color")); + theme_cache.selection_color = get_theme_color(SNAME("selection_color")); + use_selected_font_color = theme_cache.font_selected_color != Color(0, 0, 0, 0); - /* Visual. */ - style_normal = get_theme_stylebox(SNAME("normal")); - style_focus = get_theme_stylebox(SNAME("focus")); - style_readonly = get_theme_stylebox(SNAME("read_only")); + /* Other visuals */ + theme_cache.style_normal = get_theme_stylebox(SNAME("normal")); + theme_cache.style_focus = get_theme_stylebox(SNAME("focus")); + theme_cache.style_readonly = get_theme_stylebox(SNAME("read_only")); - tab_icon = get_theme_icon(SNAME("tab")); - space_icon = get_theme_icon(SNAME("space")); + theme_cache.tab_icon = get_theme_icon(SNAME("tab")); + theme_cache.space_icon = get_theme_icon(SNAME("space")); - font = get_theme_font(SNAME("font")); - font_size = get_theme_font_size(SNAME("font_size")); - font_color = get_theme_color(SNAME("font_color")); - font_readonly_color = get_theme_color(SNAME("font_readonly_color")); - font_placeholder_color = get_theme_color(SNAME("font_placeholder_color")); + 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_readonly_color = get_theme_color(SNAME("font_readonly_color")); + theme_cache.font_placeholder_color = get_theme_color(SNAME("font_placeholder_color")); - outline_size = get_theme_constant(SNAME("outline_size")); - outline_color = get_theme_color(SNAME("font_outline_color")); + theme_cache.outline_size = get_theme_constant(SNAME("outline_size")); + theme_cache.outline_color = get_theme_color(SNAME("font_outline_color")); - line_spacing = get_theme_constant(SNAME("line_spacing")); + theme_cache.line_spacing = get_theme_constant(SNAME("line_spacing")); - background_color = get_theme_color(SNAME("background_color")); - current_line_color = get_theme_color(SNAME("current_line_color")); - word_highlighted_color = get_theme_color(SNAME("word_highlighted_color")); + theme_cache.background_color = get_theme_color(SNAME("background_color")); + theme_cache.current_line_color = get_theme_color(SNAME("current_line_color")); + theme_cache.word_highlighted_color = get_theme_color(SNAME("word_highlighted_color")); +} +void TextEdit::_update_caches() { /* Text properties. */ TextServer::Direction dir; if (text_direction == Control::TEXT_DIRECTION_INHERITED) { @@ -3010,8 +3021,8 @@ void TextEdit::_update_caches() { } text.set_direction_and_language(dir, (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale()); text.set_draw_control_chars(draw_control_chars); - text.set_font(font); - text.set_font_size(font_size); + text.set_font(theme_cache.font); + text.set_font_size(theme_cache.font_size); text.invalidate_font(); _update_placeholder(); @@ -3023,7 +3034,7 @@ void TextEdit::_update_caches() { /* General overrides. */ Size2 TextEdit::get_minimum_size() const { - Size2 size = style_normal->get_minimum_size(); + Size2 size = theme_cache.style_normal->get_minimum_size(); if (fit_content_height) { size.y += content_height_cache; } @@ -3119,7 +3130,7 @@ Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const { Point2i pos = get_line_column_at_pos(p_pos); int row = pos.y; - int left_margin = style_normal->get_margin(SIDE_LEFT); + int left_margin = theme_cache.style_normal->get_margin(SIDE_LEFT); int gutter = left_margin + gutters_width; if (p_pos.x < gutter) { for (int i = 0; i < gutters.size(); i++) { @@ -3137,7 +3148,7 @@ Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const { return CURSOR_ARROW; } - int xmargin_end = get_size().width - style_normal->get_margin(SIDE_RIGHT); + int xmargin_end = get_size().width - theme_cache.style_normal->get_margin(SIDE_RIGHT); if (draw_minimap && p_pos.x > xmargin_end - minimap_width && p_pos.x <= xmargin_end) { return CURSOR_ARROW; } @@ -3465,7 +3476,7 @@ int TextEdit::get_line_width(int p_line, int p_wrap_index) const { } int TextEdit::get_line_height() const { - return text.get_line_height() + line_spacing; + return text.get_line_height() + theme_cache.line_spacing; } int TextEdit::get_indent_level(int p_line) const { @@ -4249,7 +4260,7 @@ String TextEdit::get_word_at_pos(const Vector2 &p_pos) const { Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos, bool p_allow_out_of_bounds) const { float rows = p_pos.y; - rows -= style_normal->get_margin(SIDE_TOP); + rows -= theme_cache.style_normal->get_margin(SIDE_TOP); rows /= get_line_height(); rows += _get_v_scroll_offset(); int first_vis_line = get_first_visible_line(); @@ -4284,7 +4295,7 @@ Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos, bool p_allow_out_ } int col = 0; - int colx = p_pos.x - (style_normal->get_margin(SIDE_LEFT) + gutters_width + gutter_padding); + int colx = p_pos.x - (theme_cache.style_normal->get_margin(SIDE_LEFT) + gutters_width + gutter_padding); colx += first_visible_col; col = _get_char_pos_for_line(colx, row, wrap_index); if (get_line_wrapping_mode() != LineWrappingMode::LINE_WRAPPING_NONE && wrap_index < get_line_wrap_count(row)) { @@ -4339,7 +4350,7 @@ Rect2i TextEdit::get_rect_at_line_column(int p_line, int p_column) const { Point2i pos, size; pos.y = cache_entry.y_offset + get_line_height() * wrap_index; - pos.x = get_total_gutter_width() + style_normal->get_margin(SIDE_LEFT) - get_h_scroll(); + pos.x = get_total_gutter_width() + theme_cache.style_normal->get_margin(SIDE_LEFT) - get_h_scroll(); RID text_rid = text.get_line_data(p_line)->get_line_rid(wrap_index); Vector2 col_bounds = TS->shaped_text_get_grapheme_bounds(text_rid, p_column); @@ -4353,7 +4364,7 @@ Rect2i TextEdit::get_rect_at_line_column(int p_line, int p_column) const { int TextEdit::get_minimap_line_at_pos(const Point2i &p_pos) const { float rows = p_pos.y; - rows -= style_normal->get_margin(SIDE_TOP); + rows -= theme_cache.style_normal->get_margin(SIDE_TOP); rows /= (minimap_char_size.y + minimap_line_spacing); rows += _get_v_scroll_offset(); @@ -5519,7 +5530,7 @@ void TextEdit::adjust_viewport_to_caret(int p_caret) { set_line_as_last_visible(cur_line, cur_wrap); } - int visible_width = get_size().width - style_normal->get_minimum_size().width - gutters_width - gutter_padding; + int visible_width = get_size().width - theme_cache.style_normal->get_minimum_size().width - gutters_width - gutter_padding; if (draw_minimap) { visible_width -= minimap_width; } @@ -5573,7 +5584,7 @@ void TextEdit::center_viewport_to_caret(int p_caret) { minimap_clicked = false; set_line_as_center_visible(get_caret_line(p_caret), get_caret_wrap_index(p_caret)); - int visible_width = get_size().width - style_normal->get_minimum_size().width - gutters_width - gutter_padding; + int visible_width = get_size().width - theme_cache.style_normal->get_minimum_size().width - gutters_width - gutter_padding; if (draw_minimap) { visible_width -= minimap_width; } @@ -7191,7 +7202,7 @@ void TextEdit::_post_shift_selection(int p_caret) { /* Line Wrapping */ void TextEdit::_update_wrap_at_column(bool p_force) { - int new_wrap_at = get_size().width - style_normal->get_minimum_size().width - gutters_width - gutter_padding; + int new_wrap_at = get_size().width - theme_cache.style_normal->get_minimum_size().width - gutters_width - gutter_padding; if (draw_minimap) { new_wrap_at -= minimap_width; } @@ -7228,8 +7239,8 @@ void TextEdit::_update_scrollbars() { Size2 hmin = h_scroll->get_combined_minimum_size(); Size2 vmin = v_scroll->get_combined_minimum_size(); - v_scroll->set_begin(Point2(size.width - vmin.width, style_normal->get_margin(SIDE_TOP))); - v_scroll->set_end(Point2(size.width, size.height - style_normal->get_margin(SIDE_TOP) - style_normal->get_margin(SIDE_BOTTOM))); + v_scroll->set_begin(Point2(size.width - vmin.width, theme_cache.style_normal->get_margin(SIDE_TOP))); + v_scroll->set_end(Point2(size.width, size.height - theme_cache.style_normal->get_margin(SIDE_TOP) - theme_cache.style_normal->get_margin(SIDE_BOTTOM))); h_scroll->set_begin(Point2(0, size.height - hmin.height)); h_scroll->set_end(Point2(size.width - vmin.width, size.height)); @@ -7242,7 +7253,7 @@ void TextEdit::_update_scrollbars() { total_rows += visible_rows - 1; } - int visible_width = size.width - style_normal->get_minimum_size().width; + int visible_width = size.width - theme_cache.style_normal->get_minimum_size().width; int total_width = (draw_placeholder ? placeholder_max_width : text.get_max_width()) + vmin.x + gutters_width + gutter_padding; if (draw_minimap) { @@ -7298,7 +7309,7 @@ void TextEdit::_update_scrollbars() { int TextEdit::_get_control_height() const { int control_height = get_size().height; - control_height -= style_normal->get_minimum_size().height; + control_height -= theme_cache.style_normal->get_minimum_size().height; if (h_scroll->is_visible_in_tree()) { control_height -= h_scroll->get_size().height; } @@ -7460,7 +7471,7 @@ void TextEdit::_scroll_lines_down() { void TextEdit::_update_minimap_hover() { const Point2 mp = get_local_mouse_pos(); - const int xmargin_end = get_size().width - style_normal->get_margin(SIDE_RIGHT); + const int xmargin_end = get_size().width - theme_cache.style_normal->get_margin(SIDE_RIGHT); const bool hovering_sidebar = mp.x > xmargin_end - minimap_width && mp.x < xmargin_end; if (!hovering_sidebar) { @@ -7487,7 +7498,7 @@ void TextEdit::_update_minimap_hover() { void TextEdit::_update_minimap_click() { Point2 mp = get_local_mouse_pos(); - int xmargin_end = get_size().width - style_normal->get_margin(SIDE_RIGHT); + int xmargin_end = get_size().width - theme_cache.style_normal->get_margin(SIDE_RIGHT); if (!dragging_minimap && (mp.x < xmargin_end - minimap_width || mp.y > xmargin_end)) { minimap_clicked = false; return; @@ -7777,7 +7788,6 @@ TextEdit::TextEdit(const String &p_placeholder) { clear(); set_focus_mode(FOCUS_ALL); - _update_caches(); set_default_cursor_shape(CURSOR_IBEAM); set_process_unhandled_key_input(true); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 28300f6ee258..6b710ae26fcc 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -356,9 +356,6 @@ class TextEdit : public Control { void _clear_redo(); /* Search */ - Color search_result_color = Color(1, 1, 1); - Color search_result_border_color = Color(1, 1, 1); - String search_text = ""; uint32_t search_flags = 0; @@ -413,9 +410,6 @@ class TextEdit : public Control { bool caret_pos_dirty = false; bool caret_index_edit_dirty = true; - Color caret_color = Color(1, 1, 1); - Color caret_background_color = Color(0, 0, 0); - CaretType caret_type = CaretType::CARET_TYPE_LINE; bool draw_caret = true; @@ -446,8 +440,6 @@ class TextEdit : public Control { bool deselect_on_focus_loss_enabled = true; bool drag_and_drop_selection_enabled = true; - Color font_selected_color = Color(0, 0, 0, 0); - Color selection_color = Color(1, 1, 1); bool use_selected_font_color = false; bool selection_drag_attempt = false; @@ -543,27 +535,50 @@ class TextEdit : public Control { Dictionary _get_line_syntax_highlighting(int p_line); /* Visual. */ - Ref style_normal; - Ref style_focus; - Ref style_readonly; + struct ThemeCache { + float base_scale = 1.0; + + /* Internal API for CodeEdit */ + Color brace_mismatch_color; + Color code_folding_color = Color(1, 1, 1); + Ref folded_eol_icon; - Ref tab_icon; - Ref space_icon; + /* Search */ + Color search_result_color = Color(1, 1, 1); + Color search_result_border_color = Color(1, 1, 1); - Ref font; - int font_size = 16; - Color font_color = Color(1, 1, 1); - Color font_readonly_color = Color(1, 1, 1); - Color font_placeholder_color = Color(1, 1, 1, 0.6); + /* Caret */ + int caret_width = 1; + Color caret_color = Color(1, 1, 1); + Color caret_background_color = Color(0, 0, 0); - int outline_size = 0; - Color outline_color = Color(1, 1, 1); + /* Selection */ + Color font_selected_color = Color(0, 0, 0, 0); + Color selection_color = Color(1, 1, 1); - int line_spacing = 1; + /* Other visuals */ + Ref style_normal; + Ref style_focus; + Ref style_readonly; + + Ref tab_icon; + Ref space_icon; + + Ref font; + int font_size = 16; + Color font_color = Color(1, 1, 1); + Color font_readonly_color = Color(1, 1, 1); + Color font_placeholder_color = Color(1, 1, 1, 0.6); - Color background_color = Color(1, 1, 1); - Color current_line_color = Color(1, 1, 1); - Color word_highlighted_color = Color(1, 1, 1); + int outline_size = 0; + Color outline_color = Color(1, 1, 1); + + int line_spacing = 1; + + Color background_color = Color(1, 1, 1); + Color current_line_color = Color(1, 1, 1); + Color word_highlighted_color = Color(1, 1, 1); + } theme_cache; bool window_has_focus = true; bool first_draw = true; @@ -607,9 +622,10 @@ class TextEdit : public Control { protected: void _notification(int p_what); - static void _bind_methods(); + virtual void _update_theme_item_cache() override; + /* Internal API for CodeEdit, pending public API. */ // brace matching struct BraceMatchingData { @@ -624,12 +640,8 @@ class TextEdit : public Control { }; bool highlight_matching_braces_enabled = false; - Color brace_mismatch_color; // Line hiding. - Color code_folding_color = Color(1, 1, 1); - Ref folded_eol_icon; - bool hiding_enabled = false; void _set_hiding_enabled(bool p_enabled); From e4015402647d54a73103e182b7c8d4714399b71d Mon Sep 17 00:00:00 2001 From: Yuri Sizov Date: Mon, 3 Apr 2023 18:01:11 +0200 Subject: [PATCH 3/4] Implement theme item cache in ColorPicker and friends --- scene/gui/color_picker.cpp | 170 ++++++++++++++++++++++++------------- scene/gui/color_picker.h | 53 +++++++++++- 2 files changed, 165 insertions(+), 58 deletions(-) diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 48e375998167..23b5bb2c7bd1 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -47,36 +47,47 @@ void ColorPicker::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { _update_color(); - [[fallthrough]]; - } + } break; + case NOTIFICATION_THEME_CHANGED: { - btn_pick->set_icon(get_theme_icon(SNAME("screen_picker"), SNAME("ColorPicker"))); + btn_pick->set_icon(theme_cache.screen_picker); _update_drop_down_arrow(btn_preset->is_pressed(), btn_preset); _update_drop_down_arrow(btn_recent_preset->is_pressed(), btn_recent_preset); - btn_add_preset->set_icon(get_theme_icon(SNAME("add_preset"))); + btn_add_preset->set_icon(theme_cache.add_preset); - btn_pick->set_custom_minimum_size(Size2(28 * get_theme_default_base_scale(), 0)); - btn_shape->set_custom_minimum_size(Size2(28 * get_theme_default_base_scale(), 0)); - btn_mode->set_custom_minimum_size(Size2(28 * get_theme_default_base_scale(), 0)); + btn_pick->set_custom_minimum_size(Size2(28 * theme_cache.base_scale, 0)); + btn_shape->set_custom_minimum_size(Size2(28 * theme_cache.base_scale, 0)); + btn_mode->set_custom_minimum_size(Size2(28 * theme_cache.base_scale, 0)); - uv_edit->set_custom_minimum_size(Size2(get_theme_constant(SNAME("sv_width")), get_theme_constant(SNAME("sv_height")))); - w_edit->set_custom_minimum_size(Size2(get_theme_constant(SNAME("h_width")), 0)); + uv_edit->set_custom_minimum_size(Size2(theme_cache.sv_width, theme_cache.sv_height)); + w_edit->set_custom_minimum_size(Size2(theme_cache.h_width, 0)); - wheel_edit->set_custom_minimum_size(Size2(get_theme_constant(SNAME("sv_width")), get_theme_constant(SNAME("sv_height")))); - wheel_margin->add_theme_constant_override("margin_bottom", 8 * get_theme_default_base_scale()); + wheel_edit->set_custom_minimum_size(Size2(theme_cache.sv_width, theme_cache.sv_height)); + wheel_margin->add_theme_constant_override("margin_bottom", 8 * theme_cache.base_scale); for (int i = 0; i < SLIDER_COUNT; i++) { - labels[i]->set_custom_minimum_size(Size2(get_theme_constant(SNAME("label_width")), 0)); - set_offset((Side)i, get_offset((Side)i) + get_theme_constant(SNAME("margin"))); + labels[i]->set_custom_minimum_size(Size2(theme_cache.label_width, 0)); + set_offset((Side)i, get_offset((Side)i) + theme_cache.content_margin); } - alpha_label->set_custom_minimum_size(Size2(get_theme_constant(SNAME("label_width")), 0)); - set_offset((Side)0, get_offset((Side)0) + get_theme_constant(SNAME("margin"))); + alpha_label->set_custom_minimum_size(Size2(theme_cache.label_width, 0)); + set_offset((Side)0, get_offset((Side)0) + theme_cache.content_margin); + + for (int i = 0; i < MODE_BUTTON_COUNT; i++) { + mode_btns[i]->add_theme_style_override("pressed", theme_cache.mode_button_pressed); + mode_btns[i]->add_theme_style_override("normal", theme_cache.mode_button_normal); + mode_btns[i]->add_theme_style_override("hover", theme_cache.mode_button_hover); + } + + shape_popup->set_item_icon(shape_popup->get_item_index(SHAPE_HSV_RECTANGLE), theme_cache.shape_rect); + shape_popup->set_item_icon(shape_popup->get_item_index(SHAPE_HSV_WHEEL), theme_cache.shape_rect_wheel); + shape_popup->set_item_icon(shape_popup->get_item_index(SHAPE_VHS_CIRCLE), theme_cache.shape_circle); + shape_popup->set_item_icon(shape_popup->get_item_index(SHAPE_OKHSL_CIRCLE), theme_cache.shape_circle); - _reset_theme(); + _reset_sliders_theme(); if (Engine::get_singleton()->is_editor_hint()) { // Adjust for the width of the "Script" icon. - text_type->set_custom_minimum_size(Size2(28 * get_theme_default_base_scale(), 0)); + text_type->set_custom_minimum_size(Size2(28 * theme_cache.base_scale, 0)); } _update_presets(); @@ -87,7 +98,7 @@ void ColorPicker::_notification(int p_what) { case NOTIFICATION_VISIBILITY_CHANGED: { Popup *p = Object::cast_to(get_parent()); if (p && is_visible_in_tree()) { - p->set_size(Size2(get_combined_minimum_size().width + get_theme_constant(SNAME("margin")) * 2, get_combined_minimum_size().height + get_theme_constant(SNAME("margin")) * 2)); + p->set_size(Size2(get_combined_minimum_size().width + theme_cache.content_margin * 2, get_combined_minimum_size().height + theme_cache.content_margin * 2)); } } break; @@ -99,6 +110,38 @@ void ColorPicker::_notification(int p_what) { } } +void ColorPicker::_update_theme_item_cache() { + VBoxContainer::_update_theme_item_cache(); + + theme_cache.base_scale = get_theme_default_base_scale(); + + theme_cache.content_margin = get_theme_constant(SNAME("margin")); + theme_cache.label_width = get_theme_constant(SNAME("label_width")); + + theme_cache.sv_width = get_theme_constant(SNAME("sv_width")); + theme_cache.sv_height = get_theme_constant(SNAME("sv_height")); + theme_cache.h_width = get_theme_constant(SNAME("h_width")); + + theme_cache.screen_picker = get_theme_icon(SNAME("screen_picker")); + theme_cache.expanded_arrow = get_theme_icon(SNAME("expanded_arrow")); + theme_cache.folded_arrow = get_theme_icon(SNAME("folded_arrow")); + theme_cache.add_preset = get_theme_icon(SNAME("add_preset")); + + theme_cache.shape_rect = get_theme_icon(SNAME("shape_rect")); + theme_cache.shape_rect_wheel = get_theme_icon(SNAME("shape_rect_wheel")); + theme_cache.shape_circle = get_theme_icon(SNAME("shape_circle")); + + theme_cache.bar_arrow = get_theme_icon(SNAME("bar_arrow")); + theme_cache.sample_background_icon = get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")); + theme_cache.overbright_indicator = get_theme_icon(SNAME("overbright_indicator"), SNAME("ColorPicker")); + theme_cache.picker_cursor = get_theme_icon(SNAME("picker_cursor")); + theme_cache.color_hue_icon = get_theme_icon(SNAME("color_hue")); + + theme_cache.mode_button_normal = get_theme_stylebox("tab_unselected", "TabContainer"); + theme_cache.mode_button_pressed = get_theme_stylebox("tab_selected", "TabContainer"); + theme_cache.mode_button_hover = get_theme_stylebox("tab_selected", "TabContainer"); +} + Ref ColorPicker::wheel_shader; Ref ColorPicker::circle_shader; Ref ColorPicker::circle_ok_color_shader; @@ -475,21 +518,21 @@ ColorPicker::PickerShapeType ColorPicker::_get_actual_shape() const { return modes[current_mode]->get_shape_override() != SHAPE_MAX ? modes[current_mode]->get_shape_override() : current_shape; } -void ColorPicker::_reset_theme() { +void ColorPicker::_reset_sliders_theme() { Ref style_box_flat(memnew(StyleBoxFlat)); - style_box_flat->set_content_margin(SIDE_TOP, 16 * get_theme_default_base_scale()); + style_box_flat->set_content_margin(SIDE_TOP, 16 * theme_cache.base_scale); style_box_flat->set_bg_color(Color(0.2, 0.23, 0.31).lerp(Color(0, 0, 0, 1), 0.3).clamp()); for (int i = 0; i < SLIDER_COUNT; i++) { - sliders[i]->add_theme_icon_override("grabber", get_theme_icon(SNAME("bar_arrow"), SNAME("ColorPicker"))); - sliders[i]->add_theme_icon_override("grabber_highlight", get_theme_icon(SNAME("bar_arrow"), SNAME("ColorPicker"))); - sliders[i]->add_theme_constant_override("grabber_offset", 8 * get_theme_default_base_scale()); + sliders[i]->add_theme_icon_override("grabber", theme_cache.bar_arrow); + sliders[i]->add_theme_icon_override("grabber_highlight", theme_cache.bar_arrow); + sliders[i]->add_theme_constant_override("grabber_offset", 8 * theme_cache.base_scale); if (!colorize_sliders) { sliders[i]->add_theme_style_override("slider", style_box_flat); } } - alpha_slider->add_theme_icon_override("grabber", get_theme_icon(SNAME("bar_arrow"), SNAME("ColorPicker"))); - alpha_slider->add_theme_icon_override("grabber_highlight", get_theme_icon(SNAME("bar_arrow"), SNAME("ColorPicker"))); - alpha_slider->add_theme_constant_override("grabber_offset", 8 * get_theme_default_base_scale()); + alpha_slider->add_theme_icon_override("grabber", theme_cache.bar_arrow); + alpha_slider->add_theme_icon_override("grabber_highlight", theme_cache.bar_arrow); + alpha_slider->add_theme_constant_override("grabber_offset", 8 * theme_cache.base_scale); if (!colorize_sliders) { alpha_slider->add_theme_style_override("slider", style_box_flat); } @@ -676,9 +719,9 @@ void ColorPicker::_show_hide_preset(const bool &p_is_btn_pressed, Button *p_btn_ void ColorPicker::_update_drop_down_arrow(const bool &p_is_btn_pressed, Button *p_btn_preset) { if (p_is_btn_pressed) { - p_btn_preset->set_icon(get_theme_icon(SNAME("expanded_arrow"), SNAME("ColorPicker"))); + p_btn_preset->set_icon(theme_cache.expanded_arrow); } else { - p_btn_preset->set_icon(get_theme_icon(SNAME("folded_arrow"), SNAME("ColorPicker"))); + p_btn_preset->set_icon(theme_cache.folded_arrow); } } @@ -851,7 +894,7 @@ void ColorPicker::set_color_mode(ColorModeType p_mode) { } if (slider_theme_modified) { - _reset_theme(); + _reset_sliders_theme(); } mode_popup->set_item_checked(current_mode, false); @@ -896,7 +939,7 @@ void ColorPicker::set_colorize_sliders(bool p_colorize_sliders) { alpha_slider->add_theme_style_override("slider", style_box_empty); } else { Ref style_box_flat(memnew(StyleBoxFlat)); - style_box_flat->set_content_margin(SIDE_TOP, 16 * get_theme_default_base_scale()); + style_box_flat->set_content_margin(SIDE_TOP, 16 * theme_cache.base_scale); style_box_flat->set_bg_color(Color(0.2, 0.23, 0.31).lerp(Color(0, 0, 0, 1), 0.3).clamp()); if (!slider_theme_modified) { @@ -966,28 +1009,28 @@ void ColorPicker::_sample_draw() { const Rect2 rect_old = Rect2(Point2(), Size2(sample->get_size().width * 0.5, sample->get_size().height * 0.95)); if (old_color.a < 1.0) { - sample->draw_texture_rect(get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), rect_old, true); + sample->draw_texture_rect(theme_cache.sample_background_icon, rect_old, true); } sample->draw_rect(rect_old, old_color); if (old_color.r > 1 || old_color.g > 1 || old_color.b > 1) { // Draw an indicator to denote that the old color is "overbright" and can't be displayed accurately in the preview. - sample->draw_texture(get_theme_icon(SNAME("overbright_indicator"), SNAME("ColorPicker")), Point2()); + sample->draw_texture(theme_cache.overbright_indicator, Point2()); } } else { rect_new = Rect2(Point2(), Size2(sample->get_size().width, sample->get_size().height * 0.95)); } if (color.a < 1.0) { - sample->draw_texture_rect(get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), rect_new, true); + sample->draw_texture_rect(theme_cache.sample_background_icon, rect_new, true); } sample->draw_rect(rect_new, color); if (color.r > 1 || color.g > 1 || color.b > 1) { // Draw an indicator to denote that the new color is "overbright" and can't be displayed accurately in the preview. - sample->draw_texture(get_theme_icon(SNAME("overbright_indicator"), SNAME("ColorPicker")), Point2(uv_edit->get_size().width * 0.5, 0)); + sample->draw_texture(theme_cache.overbright_indicator, Point2(uv_edit->get_size().width * 0.5, 0)); } } @@ -1063,21 +1106,21 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) { default: { } } - Ref cursor = get_theme_icon(SNAME("picker_cursor"), SNAME("ColorPicker")); + int x; int y; if (actual_shape == SHAPE_VHS_CIRCLE || actual_shape == SHAPE_OKHSL_CIRCLE) { - x = center.x + (center.x * Math::cos(h * Math_TAU) * s) - (cursor->get_width() / 2); - y = center.y + (center.y * Math::sin(h * Math_TAU) * s) - (cursor->get_height() / 2); + x = center.x + (center.x * Math::cos(h * Math_TAU) * s) - (theme_cache.picker_cursor->get_width() / 2); + y = center.y + (center.y * Math::sin(h * Math_TAU) * s) - (theme_cache.picker_cursor->get_height() / 2); } else { real_t corner_x = (c == wheel_uv) ? center.x - Math_SQRT12 * c->get_size().width * 0.42 : 0; real_t corner_y = (c == wheel_uv) ? center.y - Math_SQRT12 * c->get_size().height * 0.42 : 0; Size2 real_size(c->get_size().x - corner_x * 2, c->get_size().y - corner_y * 2); - x = CLAMP(real_size.x * s, 0, real_size.x) + corner_x - (cursor->get_width() / 2); - y = CLAMP(real_size.y - real_size.y * v, 0, real_size.y) + corner_y - (cursor->get_height() / 2); + x = CLAMP(real_size.x * s, 0, real_size.x) + corner_x - (theme_cache.picker_cursor->get_width() / 2); + y = CLAMP(real_size.y - real_size.y * v, 0, real_size.y) + corner_y - (theme_cache.picker_cursor->get_height() / 2); } - c->draw_texture(cursor, Point2(x, y)); + c->draw_texture(theme_cache.picker_cursor, Point2(x, y)); col.set_hsv(h, 1, 1); if (actual_shape == SHAPE_HSV_WHEEL) { @@ -1093,9 +1136,8 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) { } else if (p_which == 1) { if (actual_shape == SHAPE_HSV_RECTANGLE) { - Ref hue = get_theme_icon(SNAME("color_hue"), SNAME("ColorPicker")); c->draw_set_transform(Point2(), -Math_PI / 2, Size2(c->get_size().x, -c->get_size().y)); - c->draw_texture_rect(hue, Rect2(Point2(), Size2(1, 1))); + c->draw_texture_rect(theme_cache.color_hue_icon, Rect2(Point2(), Size2(1, 1))); c->draw_set_transform(Point2(), 0, Size2(1, 1)); int y = c->get_size().y - c->get_size().y * (1.0 - h); Color col; @@ -1663,10 +1705,10 @@ ColorPicker::ColorPicker() { current_shape = SHAPE_HSV_RECTANGLE; shape_popup = btn_shape->get_popup(); - shape_popup->add_icon_radio_check_item(get_theme_icon(SNAME("shape_rect"), SNAME("ColorPicker")), "HSV Rectangle", SHAPE_HSV_RECTANGLE); - shape_popup->add_icon_radio_check_item(get_theme_icon(SNAME("shape_rect_wheel"), SNAME("ColorPicker")), "HSV Wheel", SHAPE_HSV_WHEEL); - shape_popup->add_icon_radio_check_item(get_theme_icon(SNAME("shape_circle"), SNAME("ColorPicker")), "VHS Circle", SHAPE_VHS_CIRCLE); - shape_popup->add_icon_radio_check_item(get_theme_icon(SNAME("shape_circle"), SNAME("ColorPicker")), "OKHSL Circle", SHAPE_OKHSL_CIRCLE); + shape_popup->add_radio_check_item("HSV Rectangle", SHAPE_HSV_RECTANGLE); + shape_popup->add_radio_check_item("HSV Wheel", SHAPE_HSV_WHEEL); + shape_popup->add_radio_check_item("VHS Circle", SHAPE_VHS_CIRCLE); + shape_popup->add_radio_check_item("OKHSL Circle", SHAPE_OKHSL_CIRCLE); shape_popup->set_item_checked(current_shape, true); shape_popup->connect("id_pressed", callable_mp(this, &ColorPicker::set_picker_shape)); @@ -1687,9 +1729,6 @@ ColorPicker::ColorPicker() { mode_hbc->add_child(mode_btns[i]); mode_btns[i]->set_focus_mode(FOCUS_NONE); mode_btns[i]->set_h_size_flags(SIZE_EXPAND_FILL); - mode_btns[i]->add_theme_style_override("pressed", get_theme_stylebox("tab_selected", "TabContainer")); - mode_btns[i]->add_theme_style_override("normal", get_theme_stylebox("tab_unselected", "TabContainer")); - mode_btns[i]->add_theme_style_override("hover", get_theme_stylebox("tab_selected", "TabContainer")); mode_btns[i]->set_toggle_mode(true); mode_btns[i]->set_text(modes[i]->get_name()); mode_btns[i]->set_button_group(mode_group); @@ -1901,14 +1940,13 @@ void ColorPickerButton::pressed() { void ColorPickerButton::_notification(int p_what) { switch (p_what) { case NOTIFICATION_DRAW: { - const Ref normal = get_theme_stylebox(SNAME("normal")); - const Rect2 r = Rect2(normal->get_offset(), get_size() - normal->get_minimum_size()); - draw_texture_rect(Control::get_theme_icon(SNAME("bg"), SNAME("ColorPickerButton")), r, true); + const Rect2 r = Rect2(theme_cache.normal_style->get_offset(), get_size() - theme_cache.normal_style->get_minimum_size()); + draw_texture_rect(theme_cache.background_icon, r, true); draw_rect(r, color); if (color.r > 1 || color.g > 1 || color.b > 1) { // Draw an indicator to denote that the color is "overbright" and can't be displayed accurately in the preview - draw_texture(Control::get_theme_icon(SNAME("overbright_indicator"), SNAME("ColorPicker")), normal->get_offset()); + draw_texture(theme_cache.overbright_indicator, theme_cache.normal_style->get_offset()); } } break; @@ -1926,6 +1964,15 @@ void ColorPickerButton::_notification(int p_what) { } } +void ColorPickerButton::_update_theme_item_cache() { + Button::_update_theme_item_cache(); + + theme_cache.normal_style = get_theme_stylebox(SNAME("normal")); + theme_cache.background_icon = get_theme_icon(SNAME("bg")); + + theme_cache.overbright_indicator = get_theme_icon(SNAME("overbright_indicator"), SNAME("ColorPicker")); +} + void ColorPickerButton::set_pick_color(const Color &p_color) { if (color == p_color) { return; @@ -2012,7 +2059,7 @@ void ColorPresetButton::_notification(int p_what) { switch (p_what) { case NOTIFICATION_DRAW: { const Rect2 r = Rect2(Point2(0, 0), get_size()); - Ref sb_raw = get_theme_stylebox(SNAME("preset_fg"), SNAME("ColorPresetButton"))->duplicate(); + Ref sb_raw = theme_cache.foreground_style->duplicate(); Ref sb_flat = sb_raw; Ref sb_texture = sb_raw; @@ -2034,7 +2081,7 @@ void ColorPresetButton::_notification(int p_what) { bg_texture_rect = bg_texture_rect.grow_side(SIDE_TOP, -sb_flat->get_margin(SIDE_TOP)); bg_texture_rect = bg_texture_rect.grow_side(SIDE_BOTTOM, -sb_flat->get_margin(SIDE_BOTTOM)); - draw_texture_rect(get_theme_icon(SNAME("preset_bg"), SNAME("ColorPresetButton")), bg_texture_rect, true); + draw_texture_rect(theme_cache.background_icon, bg_texture_rect, true); sb_flat->set_bg_color(preset_color); } sb_flat->set_bg_color(preset_color); @@ -2043,7 +2090,7 @@ void ColorPresetButton::_notification(int p_what) { if (preset_color.a < 1) { // Draw a background pattern when the color is transparent. bool use_tile_texture = (sb_texture->get_h_axis_stretch_mode() == StyleBoxTexture::AxisStretchMode::AXIS_STRETCH_MODE_TILE) || (sb_texture->get_h_axis_stretch_mode() == StyleBoxTexture::AxisStretchMode::AXIS_STRETCH_MODE_TILE_FIT); - draw_texture_rect(get_theme_icon(SNAME("preset_bg"), SNAME("ColorPresetButton")), r, use_tile_texture); + draw_texture_rect(theme_cache.background_icon, r, use_tile_texture); } sb_texture->set_modulate(preset_color); sb_texture->draw(get_canvas_item(), r); @@ -2052,13 +2099,22 @@ void ColorPresetButton::_notification(int p_what) { } if (preset_color.r > 1 || preset_color.g > 1 || preset_color.b > 1) { // Draw an indicator to denote that the color is "overbright" and can't be displayed accurately in the preview - draw_texture(Control::get_theme_icon(SNAME("overbright_indicator"), SNAME("ColorPresetButton")), Vector2(0, 0)); + draw_texture(theme_cache.overbright_indicator, Vector2(0, 0)); } } break; } } +void ColorPresetButton::_update_theme_item_cache() { + BaseButton::_update_theme_item_cache(); + + theme_cache.foreground_style = get_theme_stylebox(SNAME("preset_fg")); + + theme_cache.background_icon = get_theme_icon(SNAME("preset_bg")); + theme_cache.overbright_indicator = get_theme_icon(SNAME("overbright_indicator")); +} + void ColorPresetButton::set_preset_color(const Color &p_color) { preset_color = p_color; } diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index d02c3278e6ac..6e894efb00ed 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -58,7 +58,16 @@ class ColorPresetButton : public BaseButton { Color preset_color; + struct ThemeCache { + Ref foreground_style; + + Ref background_icon; + Ref overbright_indicator; + } theme_cache; + protected: + virtual void _update_theme_item_cache() override; + void _notification(int); public: @@ -194,12 +203,43 @@ class ColorPicker : public VBoxContainer { float v = 0.0; Color last_color; + struct ThemeCache { + float base_scale = 1.0; + + int content_margin = 0; + int label_width = 0; + + int sv_height = 0; + int sv_width = 0; + int h_width = 0; + + Ref screen_picker; + Ref expanded_arrow; + Ref folded_arrow; + Ref add_preset; + + Ref shape_rect; + Ref shape_rect_wheel; + Ref shape_circle; + + Ref bar_arrow; + Ref sample_background_icon; + Ref overbright_indicator; + Ref picker_cursor; + Ref color_hue_icon; + + /* Mode buttons */ + Ref mode_button_normal; + Ref mode_button_pressed; + Ref mode_button_hover; + } theme_cache; + void _copy_color_to_hsv(); void _copy_hsv_to_color(); PickerShapeType _get_actual_shape() const; void create_slider(GridContainer *gc, int idx); - void _reset_theme(); + void _reset_sliders_theme(); void _html_submitted(const String &p_html); void _value_changed(double); void _update_controls(); @@ -237,6 +277,8 @@ class ColorPicker : public VBoxContainer { void _drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from_control); protected: + virtual void _update_theme_item_cache() override; + void _notification(int); static void _bind_methods(); @@ -326,6 +368,13 @@ class ColorPickerButton : public Button { Color color; bool edit_alpha = true; + struct ThemeCache { + Ref normal_style; + Ref background_icon; + + Ref overbright_indicator; + } theme_cache; + void _about_to_popup(); void _color_changed(const Color &p_color); void _modal_closed(); @@ -335,6 +384,8 @@ class ColorPickerButton : public Button { void _update_picker(); protected: + virtual void _update_theme_item_cache() override; + void _notification(int); static void _bind_methods(); From 9b500ab53c4aff51d93a87f412f66a8dcc3bb227 Mon Sep 17 00:00:00 2001 From: Yuri Sizov Date: Mon, 3 Apr 2023 18:01:11 +0200 Subject: [PATCH 4/4] Fix premature theme item access in editor tools --- .../debugger/editor_performance_profiler.cpp | 14 +++++- editor/debugger/editor_performance_profiler.h | 3 ++ editor/editor_audio_buses.cpp | 29 ++++++----- editor/editor_audio_buses.h | 12 ++++- editor/editor_run_native.cpp | 2 +- .../import/dynamic_font_import_settings.cpp | 6 +-- editor/import/scene_import_settings.cpp | 9 ++-- editor/inspector_dock.cpp | 11 ++--- editor/plugins/tiles/tile_atlas_view.cpp | 18 ++++--- editor/plugins/tiles/tile_atlas_view.h | 7 +++ .../editor/editor_network_profiler.cpp | 49 +++++++++++++------ .../editor/editor_network_profiler.h | 19 ++++++- 12 files changed, 121 insertions(+), 58 deletions(-) diff --git a/editor/debugger/editor_performance_profiler.cpp b/editor/debugger/editor_performance_profiler.cpp index e8fd6ef8efdb..641c7d31140c 100644 --- a/editor/debugger/editor_performance_profiler.cpp +++ b/editor/debugger/editor_performance_profiler.cpp @@ -234,7 +234,9 @@ TreeItem *EditorPerformanceProfiler::_get_monitor_base(const StringName &p_base_ base->set_editable(0, false); base->set_selectable(0, false); base->set_expand_right(0, true); - base->set_custom_font(0, get_theme_font(SNAME("bold"), SNAME("EditorFonts"))); + if (is_inside_tree()) { + base->set_custom_font(0, get_theme_font(SNAME("bold"), SNAME("EditorFonts"))); + } base_map.insert(p_base_name, base); return base; } @@ -368,6 +370,16 @@ List *EditorPerformanceProfiler::get_monitor_data(const StringName &p_nam return nullptr; } +void EditorPerformanceProfiler::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_THEME_CHANGED: { + for (KeyValue &E : base_map) { + E.value->set_custom_font(0, get_theme_font(SNAME("bold"), SNAME("EditorFonts"))); + } + } break; + } +} + EditorPerformanceProfiler::EditorPerformanceProfiler() { set_name(TTR("Monitors")); set_split_offset(340 * EDSCALE); diff --git a/editor/debugger/editor_performance_profiler.h b/editor/debugger/editor_performance_profiler.h index 74bb92a95eb4..6211cc39a47a 100644 --- a/editor/debugger/editor_performance_profiler.h +++ b/editor/debugger/editor_performance_profiler.h @@ -79,6 +79,9 @@ class EditorPerformanceProfiler : public HSplitContainer { TreeItem *_create_monitor_item(const StringName &p_monitor_name, TreeItem *p_base); void _marker_input(const Ref &p_event); +protected: + void _notification(int p_what); + public: void reset(); void update_monitors(const Vector &p_names); diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index ece5537ff3ee..f2a0ec901f85 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -1436,6 +1436,15 @@ Size2 EditorAudioMeterNotches::get_minimum_size() const { return Size2(width, height); } +void EditorAudioMeterNotches::_update_theme_item_cache() { + Control::_update_theme_item_cache(); + + theme_cache.notch_color = get_theme_color(SNAME("font_color"), SNAME("Editor")); + + theme_cache.font = get_theme_font(SNAME("font"), SNAME("Label")); + theme_cache.font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label")); +} + void EditorAudioMeterNotches::_bind_methods() { ClassDB::bind_method("add_notch", &EditorAudioMeterNotches::add_notch); ClassDB::bind_method("_draw_audio_notches", &EditorAudioMeterNotches::_draw_audio_notches); @@ -1443,10 +1452,6 @@ void EditorAudioMeterNotches::_bind_methods() { void EditorAudioMeterNotches::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_THEME_CHANGED: { - notch_color = get_theme_color(SNAME("font_color"), SNAME("Editor")); - } break; - case NOTIFICATION_DRAW: { _draw_audio_notches(); } break; @@ -1454,28 +1459,22 @@ void EditorAudioMeterNotches::_notification(int p_what) { } void EditorAudioMeterNotches::_draw_audio_notches() { - Ref font = get_theme_font(SNAME("font"), SNAME("Label")); - int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label")); - float font_height = font->get_height(font_size); + float font_height = theme_cache.font->get_height(theme_cache.font_size); for (int i = 0; i < notches.size(); i++) { AudioNotch n = notches[i]; draw_line(Vector2(0, (1.0f - n.relative_position) * (get_size().y - btm_padding - top_padding) + top_padding), Vector2(line_length * EDSCALE, (1.0f - n.relative_position) * (get_size().y - btm_padding - top_padding) + top_padding), - notch_color, + theme_cache.notch_color, Math::round(EDSCALE)); if (n.render_db_value) { - draw_string(font, + draw_string(theme_cache.font, Vector2((line_length + label_space) * EDSCALE, (1.0f - n.relative_position) * (get_size().y - btm_padding - top_padding) + (font_height / 4) + top_padding), String::num(Math::abs(n.db_value)) + "dB", - HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, - notch_color); + HORIZONTAL_ALIGNMENT_LEFT, -1, theme_cache.font_size, + theme_cache.notch_color); } } } - -EditorAudioMeterNotches::EditorAudioMeterNotches() { - notch_color = get_theme_color(SNAME("font_color"), SNAME("Editor")); -} diff --git a/editor/editor_audio_buses.h b/editor/editor_audio_buses.h index 9ff5afac6622..51f858dd111d 100644 --- a/editor/editor_audio_buses.h +++ b/editor/editor_audio_buses.h @@ -244,23 +244,31 @@ class EditorAudioMeterNotches : public Control { List notches; + struct ThemeCache { + Color notch_color; + + Ref font; + int font_size = 0; + } theme_cache; + public: const float line_length = 5.0f; const float label_space = 2.0f; const float btm_padding = 9.0f; const float top_padding = 5.0f; - Color notch_color; void add_notch(float p_normalized_offset, float p_db_value, bool p_render_value = false); Size2 get_minimum_size() const override; private: + virtual void _update_theme_item_cache() override; + static void _bind_methods(); void _notification(int p_what); void _draw_audio_notches(); public: - EditorAudioMeterNotches(); + EditorAudioMeterNotches() {} }; class AudioBusesEditorPlugin : public EditorPlugin { diff --git a/editor/editor_run_native.cpp b/editor/editor_run_native.cpp index 0628dc711653..815d4fab9c4a 100644 --- a/editor/editor_run_native.cpp +++ b/editor/editor_run_native.cpp @@ -40,6 +40,7 @@ void EditorRunNative::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { remote_debug->set_icon(get_theme_icon(SNAME("PlayRemote"), SNAME("EditorIcons"))); } break; + case NOTIFICATION_PROCESS: { bool changed = EditorExport::get_singleton()->poll_export_platforms() || first; @@ -155,7 +156,6 @@ bool EditorRunNative::is_deploy_debug_remote_enabled() const { EditorRunNative::EditorRunNative() { remote_debug = memnew(MenuButton); remote_debug->get_popup()->connect("id_pressed", callable_mp(this, &EditorRunNative::run_native)); - remote_debug->set_icon(get_theme_icon(SNAME("PlayRemote"), SNAME("EditorIcons"))); remote_debug->set_tooltip_text(TTR("Remote Debug")); remote_debug->set_disabled(true); diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp index b34656c481f6..6be6682232e1 100644 --- a/editor/import/dynamic_font_import_settings.cpp +++ b/editor/import/dynamic_font_import_settings.cpp @@ -924,9 +924,9 @@ void DynamicFontImportSettings::_notification(int p_what) { connect("confirmed", callable_mp(this, &DynamicFontImportSettings::_re_import)); } break; - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { add_var->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); + label_warn->add_theme_color_override("font_color", get_theme_color(SNAME("warning_color"), SNAME("Editor"))); } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { @@ -1284,8 +1284,6 @@ DynamicFontImportSettings::DynamicFontImportSettings() { options_variations.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "variation_face_index"), 0)); options_variations.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::TRANSFORM2D, "variation_transform"), Transform2D())); - Color warn_color = (EditorNode::get_singleton()) ? EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("warning_color"), SNAME("Editor")) : Color(1, 1, 0); - // Root layout VBoxContainer *root_vb = memnew(VBoxContainer); @@ -1302,7 +1300,6 @@ DynamicFontImportSettings::DynamicFontImportSettings() { label_warn->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); label_warn->set_text(""); root_vb->add_child(label_warn); - label_warn->add_theme_color_override("font_color", warn_color); label_warn->hide(); // Page 1 layout: Rendering Options @@ -1379,7 +1376,6 @@ DynamicFontImportSettings::DynamicFontImportSettings() { add_var = memnew(Button); page2_hb_vars->add_child(add_var); add_var->set_tooltip_text(TTR("Add configuration")); - add_var->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); add_var->connect("pressed", callable_mp(this, &DynamicFontImportSettings::_variation_add)); vars_list = memnew(Tree); diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp index 204a8494e6b8..4dd3de8ca27d 100644 --- a/editor/import/scene_import_settings.cpp +++ b/editor/import/scene_import_settings.cpp @@ -1001,6 +1001,12 @@ void SceneImportSettings::_notification(int p_what) { connect("confirmed", callable_mp(this, &SceneImportSettings::_re_import)); } break; + case NOTIFICATION_THEME_CHANGED: { + action_menu->add_theme_style_override("normal", get_theme_stylebox("normal", "Button")); + action_menu->add_theme_style_override("hover", get_theme_stylebox("hover", "Button")); + action_menu->add_theme_style_override("pressed", get_theme_stylebox("pressed", "Button")); + } break; + case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { inspector->set_property_name_style(EditorPropertyNameProcessor::get_settings_style()); } break; @@ -1288,9 +1294,6 @@ SceneImportSettings::SceneImportSettings() { action_menu->set_text(TTR("Actions...")); // Style the MenuButton like a regular Button to make it more noticeable. action_menu->set_flat(false); - action_menu->add_theme_style_override("normal", get_theme_stylebox("normal", "Button")); - action_menu->add_theme_style_override("hover", get_theme_stylebox("hover", "Button")); - action_menu->add_theme_style_override("pressed", get_theme_stylebox("pressed", "Button")); action_menu->set_focus_mode(Control::FOCUS_ALL); menu_hb->add_child(action_menu); diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index b9efe7d2ea3f..f7bbeb92c6f2 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -420,12 +420,9 @@ Container *InspectorDock::get_addon_area() { void InspectorDock::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_THEME_CHANGED: case NOTIFICATION_TRANSLATION_CHANGED: - case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: - case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - set_theme(EditorNode::get_singleton()->get_gui_base()->get_theme()); - + case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: { resource_new_button->set_icon(get_theme_icon(SNAME("New"), SNAME("EditorIcons"))); resource_load_button->set_icon(get_theme_icon(SNAME("Load"), SNAME("EditorIcons"))); resource_save_button->set_icon(get_theme_icon(SNAME("Save"), SNAME("EditorIcons"))); @@ -659,8 +656,8 @@ InspectorDock::InspectorDock(EditorData &p_editor_data) { resource_extra_button->set_tooltip_text(TTR("Extra resource options.")); general_options_hb->add_child(resource_extra_button); resource_extra_button->connect("about_to_popup", callable_mp(this, &InspectorDock::_prepare_resource_extra_popup)); - resource_extra_button->get_popup()->add_icon_shortcut(get_theme_icon(SNAME("ActionPaste"), SNAME("EditorIcons")), ED_SHORTCUT("property_editor/paste_resource", TTR("Edit Resource from Clipboard")), RESOURCE_EDIT_CLIPBOARD); - resource_extra_button->get_popup()->add_icon_shortcut(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")), ED_SHORTCUT("property_editor/copy_resource", TTR("Copy Resource")), RESOURCE_COPY); + resource_extra_button->get_popup()->add_shortcut(ED_SHORTCUT("property_editor/paste_resource", TTR("Edit Resource from Clipboard")), RESOURCE_EDIT_CLIPBOARD); + resource_extra_button->get_popup()->add_shortcut(ED_SHORTCUT("property_editor/copy_resource", TTR("Copy Resource")), RESOURCE_COPY); resource_extra_button->get_popup()->set_item_disabled(1, true); resource_extra_button->get_popup()->add_separator(); resource_extra_button->get_popup()->add_shortcut(ED_SHORTCUT("property_editor/show_in_filesystem", TTR("Show in FileSystem")), RESOURCE_SHOW_IN_FILESYSTEM); diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp index 43c6d1a48b16..168304875f52 100644 --- a/editor/plugins/tiles/tile_atlas_view.cpp +++ b/editor/plugins/tiles/tile_atlas_view.cpp @@ -394,13 +394,11 @@ void TileAtlasView::_draw_alternatives() { } void TileAtlasView::_draw_background_left() { - Ref texture = get_theme_icon(SNAME("Checkerboard"), SNAME("EditorIcons")); - background_left->draw_texture_rect(texture, Rect2(Vector2(), background_left->get_size()), true); + background_left->draw_texture_rect(theme_cache.checkerboard, Rect2(Vector2(), background_left->get_size()), true); } void TileAtlasView::_draw_background_right() { - Ref texture = get_theme_icon(SNAME("Checkerboard"), SNAME("EditorIcons")); - background_right->draw_texture_rect(texture, Rect2(Vector2(), background_right->get_size()), true); + background_right->draw_texture_rect(theme_cache.checkerboard, Rect2(Vector2(), background_right->get_size()), true); } void TileAtlasView::set_atlas_source(TileSet *p_tile_set, TileSetAtlasSource *p_tile_set_atlas_source, int p_source_id) { @@ -539,6 +537,13 @@ void TileAtlasView::queue_redraw() { background_right->queue_redraw(); } +void TileAtlasView::_update_theme_item_cache() { + Control::_update_theme_item_cache(); + + theme_cache.center_view_icon = get_theme_icon(SNAME("CenterView"), SNAME("EditorIcons")); + theme_cache.checkerboard = get_theme_icon(SNAME("Checkerboard"), SNAME("EditorIcons")); +} + void TileAtlasView::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: @@ -546,8 +551,8 @@ void TileAtlasView::_notification(int p_what) { panner->setup((ViewPanner::ControlScheme)EDITOR_GET("editors/panning/sub_editors_panning_scheme").operator int(), ED_GET_SHORTCUT("canvas_item_editor/pan_view"), bool(EDITOR_GET("editors/panning/simple_panning"))); } break; - case NOTIFICATION_READY: { - button_center_view->set_icon(get_theme_icon(SNAME("CenterView"), SNAME("EditorIcons"))); + case NOTIFICATION_THEME_CHANGED: { + button_center_view->set_icon(theme_cache.center_view_icon); } break; } } @@ -574,7 +579,6 @@ TileAtlasView::TileAtlasView() { zoom_widget->set_shortcut_context(this); button_center_view = memnew(Button); - button_center_view->set_icon(get_theme_icon(SNAME("CenterView"), SNAME("EditorIcons"))); button_center_view->set_anchors_and_offsets_preset(Control::PRESET_TOP_RIGHT, Control::PRESET_MODE_MINSIZE, 5); button_center_view->connect("pressed", callable_mp(this, &TileAtlasView::_center_view)); button_center_view->set_flat(true); diff --git a/editor/plugins/tiles/tile_atlas_view.h b/editor/plugins/tiles/tile_atlas_view.h index 4a7547f34bc6..2be3fadd21e3 100644 --- a/editor/plugins/tiles/tile_atlas_view.h +++ b/editor/plugins/tiles/tile_atlas_view.h @@ -110,7 +110,14 @@ class TileAtlasView : public Control { Size2i _compute_alternative_tiles_control_size(); + struct ThemeCache { + Ref center_view_icon; + Ref checkerboard; + } theme_cache; + protected: + virtual void _update_theme_item_cache() override; + void _notification(int p_what); static void _bind_methods(); diff --git a/modules/multiplayer/editor/editor_network_profiler.cpp b/modules/multiplayer/editor/editor_network_profiler.cpp index f8e75d5ef5b7..c2cb0a3d1a78 100644 --- a/modules/multiplayer/editor/editor_network_profiler.cpp +++ b/modules/multiplayer/editor/editor_network_profiler.cpp @@ -41,25 +41,42 @@ void EditorNetworkProfiler::_bind_methods() { void EditorNetworkProfiler::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - node_icon = get_theme_icon(SNAME("Node"), SNAME("EditorIcons")); if (activate->is_pressed()) { - activate->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons"))); + activate->set_icon(theme_cache.stop_icon); } else { - activate->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons"))); + activate->set_icon(theme_cache.play_icon); } - clear_button->set_icon(get_theme_icon(SNAME("Clear"), SNAME("EditorIcons"))); - incoming_bandwidth_text->set_right_icon(get_theme_icon(SNAME("ArrowDown"), SNAME("EditorIcons"))); - outgoing_bandwidth_text->set_right_icon(get_theme_icon(SNAME("ArrowUp"), SNAME("EditorIcons"))); + clear_button->set_icon(theme_cache.clear_icon); + + incoming_bandwidth_text->set_right_icon(theme_cache.incoming_bandwidth_icon); + outgoing_bandwidth_text->set_right_icon(theme_cache.outgoing_bandwidth_icon); // This needs to be done here to set the faded color when the profiler is first opened - incoming_bandwidth_text->add_theme_color_override("font_uneditable_color", get_theme_color(SNAME("font_color"), SNAME("Editor")) * Color(1, 1, 1, 0.5)); - outgoing_bandwidth_text->add_theme_color_override("font_uneditable_color", get_theme_color(SNAME("font_color"), SNAME("Editor")) * Color(1, 1, 1, 0.5)); + incoming_bandwidth_text->add_theme_color_override("font_uneditable_color", theme_cache.incoming_bandwidth_color * Color(1, 1, 1, 0.5)); + outgoing_bandwidth_text->add_theme_color_override("font_uneditable_color", theme_cache.outgoing_bandwidth_color * Color(1, 1, 1, 0.5)); } break; } } +void EditorNetworkProfiler::_update_theme_item_cache() { + VBoxContainer::_update_theme_item_cache(); + + theme_cache.node_icon = get_theme_icon(SNAME("Node"), SNAME("EditorIcons")); + theme_cache.stop_icon = get_theme_icon(SNAME("Stop"), SNAME("EditorIcons")); + theme_cache.play_icon = get_theme_icon(SNAME("Play"), SNAME("EditorIcons")); + theme_cache.clear_icon = get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")); + + theme_cache.multiplayer_synchronizer_icon = get_theme_icon("MultiplayerSynchronizer", SNAME("EditorIcons")); + theme_cache.instance_options_icon = get_theme_icon(SNAME("InstanceOptions"), SNAME("EditorIcons")); + + theme_cache.incoming_bandwidth_icon = get_theme_icon(SNAME("ArrowDown"), SNAME("EditorIcons")); + theme_cache.outgoing_bandwidth_icon = get_theme_icon(SNAME("ArrowUp"), SNAME("EditorIcons")); + + theme_cache.incoming_bandwidth_color = get_theme_color(SNAME("font_color"), SNAME("Editor")); + theme_cache.outgoing_bandwidth_color = get_theme_color(SNAME("font_color"), SNAME("Editor")); +} + void EditorNetworkProfiler::_refresh() { if (!dirty) { return; @@ -111,11 +128,11 @@ void EditorNetworkProfiler::refresh_replication_data() { const NodeInfo &cfg_info = node_data[E.value.config]; node->set_text(0, root_info.path.get_file()); - node->set_icon(0, has_theme_icon(root_info.type, SNAME("EditorIcons")) ? get_theme_icon(root_info.type, SNAME("EditorIcons")) : node_icon); + node->set_icon(0, has_theme_icon(root_info.type, SNAME("EditorIcons")) ? get_theme_icon(root_info.type, SNAME("EditorIcons")) : theme_cache.node_icon); node->set_tooltip_text(0, root_info.path); node->set_text(1, sync_info.path.get_file()); - node->set_icon(1, get_theme_icon("MultiplayerSynchronizer", SNAME("EditorIcons"))); + node->set_icon(1, theme_cache.multiplayer_synchronizer_icon); node->set_tooltip_text(1, sync_info.path); int cfg_idx = cfg_info.path.find("::"); @@ -123,7 +140,7 @@ void EditorNetworkProfiler::refresh_replication_data() { String res_idstr = cfg_info.path.substr(cfg_idx + 2).replace("SceneReplicationConfig_", ""); String scene_path = cfg_info.path.substr(0, cfg_idx); node->set_text(2, vformat("%s (%s)", res_idstr, scene_path.get_file())); - node->add_button(2, get_theme_icon(SNAME("InstanceOptions"), SNAME("EditorIcons"))); + node->add_button(2, theme_cache.instance_options_icon); node->set_tooltip_text(2, cfg_info.path); node->set_metadata(2, scene_path); } else { @@ -154,11 +171,11 @@ void EditorNetworkProfiler::add_node_data(const NodeInfo &p_info) { void EditorNetworkProfiler::_activate_pressed() { if (activate->is_pressed()) { refresh_timer->start(); - activate->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons"))); + activate->set_icon(theme_cache.stop_icon); activate->set_text(TTR("Stop")); } else { refresh_timer->stop(); - activate->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons"))); + activate->set_icon(theme_cache.play_icon); activate->set_text(TTR("Start")); } emit_signal(SNAME("enable_profiling"), activate->is_pressed()); @@ -224,10 +241,10 @@ void EditorNetworkProfiler::set_bandwidth(int p_incoming, int p_outgoing) { // Make labels more prominent when the bandwidth is greater than 0 to attract user attention incoming_bandwidth_text->add_theme_color_override( "font_uneditable_color", - get_theme_color(SNAME("font_color"), SNAME("Editor")) * Color(1, 1, 1, p_incoming > 0 ? 1 : 0.5)); + theme_cache.incoming_bandwidth_color * Color(1, 1, 1, p_incoming > 0 ? 1 : 0.5)); outgoing_bandwidth_text->add_theme_color_override( "font_uneditable_color", - get_theme_color(SNAME("font_color"), SNAME("Editor")) * Color(1, 1, 1, p_outgoing > 0 ? 1 : 0.5)); + theme_cache.outgoing_bandwidth_color * Color(1, 1, 1, p_outgoing > 0 ? 1 : 0.5)); } bool EditorNetworkProfiler::is_profiling() { diff --git a/modules/multiplayer/editor/editor_network_profiler.h b/modules/multiplayer/editor/editor_network_profiler.h index e8702371e023..1a38890574fe 100644 --- a/modules/multiplayer/editor/editor_network_profiler.h +++ b/modules/multiplayer/editor/editor_network_profiler.h @@ -73,7 +73,22 @@ class EditorNetworkProfiler : public VBoxContainer { HashMap sync_data; HashMap node_data; HashSet missing_node_data; - Ref node_icon; + + struct ThemeCache { + Ref node_icon; + Ref stop_icon; + Ref play_icon; + Ref clear_icon; + + Ref multiplayer_synchronizer_icon; + Ref instance_options_icon; + + Ref incoming_bandwidth_icon; + Ref outgoing_bandwidth_icon; + + Color incoming_bandwidth_color; + Color outgoing_bandwidth_color; + } theme_cache; void _activate_pressed(); void _clear_pressed(); @@ -81,6 +96,8 @@ class EditorNetworkProfiler : public VBoxContainer { void _replication_button_clicked(TreeItem *p_item, int p_column, int p_idx, MouseButton p_button); protected: + virtual void _update_theme_item_cache() override; + void _notification(int p_what); static void _bind_methods();