diff options
Diffstat (limited to 'scene/gui')
| -rw-r--r-- | scene/gui/color_picker.cpp | 6 | ||||
| -rw-r--r-- | scene/gui/control.cpp | 12 | ||||
| -rw-r--r-- | scene/gui/control.h | 2 | ||||
| -rw-r--r-- | scene/gui/graph_edit.cpp | 2 | ||||
| -rw-r--r-- | scene/gui/item_list.cpp | 8 | ||||
| -rw-r--r-- | scene/gui/label.cpp | 15 | ||||
| -rw-r--r-- | scene/gui/popup_menu.cpp | 6 | ||||
| -rw-r--r-- | scene/gui/rich_text_label.cpp | 94 | ||||
| -rw-r--r-- | scene/gui/tree.cpp | 2 |
9 files changed, 102 insertions, 45 deletions
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 669ce11e5d..f250662be0 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -89,6 +89,10 @@ void ColorPicker::_notification(int p_what) { 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); + if (current_shape != SHAPE_NONE) { + btn_shape->set_icon(shape_popup->get_item_icon(current_shape)); + } + internal_margin->begin_bulk_theme_override(); internal_margin->add_theme_constant_override(SNAME("margin_bottom"), theme_cache.content_margin); internal_margin->add_theme_constant_override(SNAME("margin_left"), theme_cache.content_margin); @@ -1792,8 +1796,6 @@ ColorPicker::ColorPicker() { shape_popup->set_item_checked(current_shape, true); shape_popup->connect("id_pressed", callable_mp(this, &ColorPicker::set_picker_shape)); - btn_shape->set_icon(shape_popup->get_item_icon(current_shape)); - add_mode(new ColorModeRGB(this)); add_mode(new ColorModeHSV(this)); add_mode(new ColorModeRAW(this)); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index c7ff5980cb..ed54bd000c 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -1653,6 +1653,7 @@ void Control::set_custom_minimum_size(const Size2 &p_custom) { data.custom_minimum_size = p_custom; update_minimum_size(); + update_configuration_warnings(); } Size2 Control::get_custom_minimum_size() const { @@ -1831,9 +1832,18 @@ bool Control::has_point(const Point2 &p_point) const { void Control::set_mouse_filter(MouseFilter p_filter) { ERR_MAIN_THREAD_GUARD; ERR_FAIL_INDEX(p_filter, 3); + + if (data.mouse_filter == p_filter) { + return; + } + data.mouse_filter = p_filter; notify_property_list_changed(); update_configuration_warnings(); + + if (get_viewport()) { + get_viewport()->_gui_update_mouse_over(); + } } Control::MouseFilter Control::get_mouse_filter() const { @@ -3568,6 +3578,8 @@ void Control::_bind_methods() { BIND_CONSTANT(NOTIFICATION_RESIZED); BIND_CONSTANT(NOTIFICATION_MOUSE_ENTER); BIND_CONSTANT(NOTIFICATION_MOUSE_EXIT); + BIND_CONSTANT(NOTIFICATION_MOUSE_ENTER_SELF); + BIND_CONSTANT(NOTIFICATION_MOUSE_EXIT_SELF); BIND_CONSTANT(NOTIFICATION_FOCUS_ENTER); BIND_CONSTANT(NOTIFICATION_FOCUS_EXIT); BIND_CONSTANT(NOTIFICATION_THEME_CHANGED); diff --git a/scene/gui/control.h b/scene/gui/control.h index abbdc42fa4..db1bd3a346 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -368,6 +368,8 @@ public: NOTIFICATION_SCROLL_BEGIN = 47, NOTIFICATION_SCROLL_END = 48, NOTIFICATION_LAYOUT_DIRECTION_CHANGED = 49, + NOTIFICATION_MOUSE_ENTER_SELF = 60, + NOTIFICATION_MOUSE_EXIT_SELF = 61, }; // Editor plugin interoperability. diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 8dddbf78cf..69023d2056 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -2015,7 +2015,7 @@ GraphEdit::GraphEdit() { top_layer->connect("focus_exited", callable_mp(panner.ptr(), &ViewPanner::release_pan_key)); connections_layer = memnew(Control); - add_child(connections_layer, false); + add_child(connections_layer, false, INTERNAL_MODE_FRONT); connections_layer->connect("draw", callable_mp(this, &GraphEdit::_connections_layer_draw)); connections_layer->set_name("_connection_layer"); connections_layer->set_disable_visibility_clip(true); // Necessary, so it can draw freely and be offset. diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 343301e9c4..02d44caa1c 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -1431,11 +1431,11 @@ void ItemList::force_update_list_size() { } } - for (int j = items.size() - 1; j >= 0 && col > 0; j--, col--) { - items.write[j].rect_cache.size.y = max_h; - } - if (all_fit) { + for (int j = items.size() - 1; j >= 0 && col > 0; j--, col--) { + items.write[j].rect_cache.size.y = max_h; + } + float page = MAX(0, size.height - theme_cache.panel_style->get_minimum_size().height); float max = MAX(page, ofs.y + max_h); if (auto_height) { diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index 0d48cb1549..2fbd29b048 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -33,6 +33,7 @@ #include "core/config/project_settings.h" #include "core/string/print_string.h" #include "core/string/translation.h" +#include "scene/gui/container.h" #include "scene/theme/theme_db.h" #include "servers/text_server.h" @@ -44,6 +45,7 @@ void Label::set_autowrap_mode(TextServer::AutowrapMode p_mode) { autowrap_mode = p_mode; lines_dirty = true; queue_redraw(); + update_configuration_warnings(); if (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) { update_minimum_size(); @@ -327,6 +329,19 @@ inline void draw_glyph_outline(const Glyph &p_gl, const RID &p_canvas, const Col PackedStringArray Label::get_configuration_warnings() const { PackedStringArray warnings = Control::get_configuration_warnings(); + // FIXME: This is not ideal and the sizing model should be fixed, + // but for now we have to warn about this impossible to resolve combination. + // See GH-83546. + if (is_inside_tree() && get_tree()->get_edited_scene_root() != this) { + // If the Label happens to be the root node of the edited scene, we don't need + // to check what its parent is. It's going to be some node from the editor tree + // and it can be a container, but that makes no difference to the user. + Container *parent_container = Object::cast_to<Container>(get_parent_control()); + if (parent_container && autowrap_mode != TextServer::AUTOWRAP_OFF && get_custom_minimum_size() == Size2()) { + warnings.push_back(RTR("Labels with autowrapping enabled must have a custom minimum size configured to work correctly inside a container.")); + } + } + // Ensure that the font can render all of the required glyphs. Ref<Font> font; if (settings.is_valid()) { diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 0cda27ec24..d6b8dd0202 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -1487,7 +1487,11 @@ void PopupMenu::add_icon_radio_check_shortcut(const Ref<Texture2D> &p_icon, cons } void PopupMenu::add_submenu_item(const String &p_label, const String &p_submenu, int p_id) { - ERR_FAIL_COND_MSG(p_submenu.validate_node_name() != p_submenu, "Invalid node name for submenu, the following characters are not allowed:\n" + String::get_invalid_node_name_characters()); + String submenu_name_safe = p_submenu.replace("@", "_"); // Allow special characters for auto-generated names. + if (submenu_name_safe.validate_node_name() != submenu_name_safe) { + ERR_FAIL_MSG(vformat("Invalid node name '%s' for a submenu, the following characters are not allowed:\n%s", p_submenu, String::get_invalid_node_name_characters(true))); + } + Item item; item.text = p_label; item.xl_text = atr(p_label); diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 40f8736244..35d3a4dc14 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -830,37 +830,6 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o prefix = segment + prefix; } } - if (!prefix.is_empty()) { - Ref<Font> font = theme_cache.normal_font; - int font_size = theme_cache.normal_font_size; - - ItemFont *font_it = _find_font(l.from); - if (font_it) { - if (font_it->font.is_valid()) { - font = font_it->font; - } - if (font_it->font_size > 0) { - font_size = font_it->font_size; - } - } - ItemFontSize *font_size_it = _find_font_size(l.from); - if (font_size_it && font_size_it->font_size > 0) { - font_size = font_size_it->font_size; - } - if (rtl) { - float offx = 0.0f; - if (!lrtl && p_frame == main) { // Skip Scrollbar. - offx -= scroll_w; - } - font->draw_string(ci, p_ofs + Vector2(p_width - l.offset.x + offx, l.text_buf->get_line_ascent(0)), " " + prefix, HORIZONTAL_ALIGNMENT_LEFT, l.offset.x, font_size, _find_color(l.from, p_base_color)); - } else { - float offx = 0.0f; - if (lrtl && p_frame == main) { // Skip Scrollbar. - offx += scroll_w; - } - font->draw_string(ci, p_ofs + Vector2(offx, l.text_buf->get_line_ascent(0)), prefix + " ", HORIZONTAL_ALIGNMENT_RIGHT, l.offset.x, font_size, _find_color(l.from, p_base_color)); - } - } // Draw dropcap. int dc_lines = l.text_buf->get_dropcap_lines(); @@ -924,6 +893,30 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o } break; } + if (!prefix.is_empty() && line == 0) { + Ref<Font> font = theme_cache.normal_font; + int font_size = theme_cache.normal_font_size; + + ItemFont *font_it = _find_font(l.from); + if (font_it) { + if (font_it->font.is_valid()) { + font = font_it->font; + } + if (font_it->font_size > 0) { + font_size = font_it->font_size; + } + } + ItemFontSize *font_size_it = _find_font_size(l.from); + if (font_size_it && font_size_it->font_size > 0) { + font_size = font_size_it->font_size; + } + if (rtl) { + font->draw_string(ci, p_ofs + Vector2(off.x + length, l.text_buf->get_line_ascent(0)), " " + prefix, HORIZONTAL_ALIGNMENT_LEFT, l.offset.x, font_size, _find_color(l.from, p_base_color)); + } else { + font->draw_string(ci, p_ofs + Vector2(off.x - l.offset.x, l.text_buf->get_line_ascent(0)), prefix + " ", HORIZONTAL_ALIGNMENT_RIGHT, l.offset.x, font_size, _find_color(l.from, p_base_color)); + } + } + if (line <= dc_lines) { if (rtl) { off.x -= h_off; @@ -977,11 +970,20 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o coff.x = rect.size.width - table->columns[col].width - coff.x; } if (row % 2 == 0) { - draw_rect(Rect2(p_ofs + rect.position + off + coff - frame->padding.position, Size2(table->columns[col].width + h_separation + frame->padding.position.x + frame->padding.size.x, table->rows[row])), (frame->odd_row_bg != Color(0, 0, 0, 0) ? frame->odd_row_bg : odd_row_bg), true); + Color c = frame->odd_row_bg != Color(0, 0, 0, 0) ? frame->odd_row_bg : odd_row_bg; + if (c.a > 0.0) { + draw_rect(Rect2(p_ofs + rect.position + off + coff - frame->padding.position, Size2(table->columns[col].width + h_separation + frame->padding.position.x + frame->padding.size.x, table->rows[row])), c, true); + } } else { - draw_rect(Rect2(p_ofs + rect.position + off + coff - frame->padding.position, Size2(table->columns[col].width + h_separation + frame->padding.position.x + frame->padding.size.x, table->rows[row])), (frame->even_row_bg != Color(0, 0, 0, 0) ? frame->even_row_bg : even_row_bg), true); + Color c = frame->even_row_bg != Color(0, 0, 0, 0) ? frame->even_row_bg : even_row_bg; + if (c.a > 0.0) { + draw_rect(Rect2(p_ofs + rect.position + off + coff - frame->padding.position, Size2(table->columns[col].width + h_separation + frame->padding.position.x + frame->padding.size.x, table->rows[row])), c, true); + } + } + Color bc = frame->border != Color(0, 0, 0, 0) ? frame->border : border; + if (bc.a > 0.0) { + draw_rect(Rect2(p_ofs + rect.position + off + coff - frame->padding.position, Size2(table->columns[col].width + h_separation + frame->padding.position.x + frame->padding.size.x, table->rows[row])), bc, false); } - draw_rect(Rect2(p_ofs + rect.position + off + coff - frame->padding.position, Size2(table->columns[col].width + h_separation + frame->padding.position.x + frame->padding.size.x, table->rows[row])), (frame->border != Color(0, 0, 0, 0) ? frame->border : border), false); } for (int j = 0; j < (int)frame->lines.size(); j++) { @@ -1204,14 +1206,17 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o Vector2 ul_start; bool ul_started = false; + Color ul_color_prev; Color ul_color; Vector2 dot_ul_start; bool dot_ul_started = false; + Color dot_ul_color_prev; Color dot_ul_color; Vector2 st_start; bool st_started = false; + Color st_color_prev; Color st_color; for (int i = 0; i < gl_size; i++) { @@ -1219,16 +1224,18 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o Item *it = _get_item_at_pos(it_from, it_to, glyphs[i].start); Color font_color = _find_color(it, p_base_color); if (_find_underline(it) || (_find_meta(it, nullptr) && underline_meta)) { - if (ul_started && font_color != ul_color) { + if (ul_started && font_color != ul_color_prev) { float y_off = TS->shaped_text_get_underline_position(rid); float underline_width = MAX(1.0, TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale); draw_line(ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), ul_color, underline_width); ul_start = p_ofs + Vector2(off.x, off.y); + ul_color_prev = font_color; ul_color = font_color; ul_color.a *= 0.5; } else if (!ul_started) { ul_started = true; ul_start = p_ofs + Vector2(off.x, off.y); + ul_color_prev = font_color; ul_color = font_color; ul_color.a *= 0.5; } @@ -1239,16 +1246,18 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o draw_line(ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), ul_color, underline_width); } if (_find_hint(it, nullptr) && underline_hint) { - if (dot_ul_started && font_color != dot_ul_color) { + if (dot_ul_started && font_color != dot_ul_color_prev) { float y_off = TS->shaped_text_get_underline_position(rid); float underline_width = MAX(1.0, TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale); draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, MAX(2.0, underline_width * 2)); dot_ul_start = p_ofs + Vector2(off.x, off.y); + dot_ul_color_prev = font_color; dot_ul_color = font_color; dot_ul_color.a *= 0.5; } else if (!dot_ul_started) { dot_ul_started = true; dot_ul_start = p_ofs + Vector2(off.x, off.y); + dot_ul_color_prev = font_color; dot_ul_color = font_color; dot_ul_color.a *= 0.5; } @@ -1259,16 +1268,18 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, MAX(2.0, underline_width * 2)); } if (_find_strikethrough(it)) { - if (st_started && font_color != st_color) { + if (st_started && font_color != st_color_prev) { float y_off = -TS->shaped_text_get_ascent(rid) + TS->shaped_text_get_size(rid).y / 2; float underline_width = MAX(1.0, TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale); draw_line(st_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), st_color, underline_width); st_start = p_ofs + Vector2(off.x, off.y); + st_color_prev = font_color; st_color = font_color; st_color.a *= 0.5; } else if (!st_started) { st_started = true; st_start = p_ofs + Vector2(off.x, off.y); + st_color_prev = font_color; st_color = font_color; st_color.a *= 0.5; } @@ -3214,6 +3225,9 @@ void RichTextLabel::add_image(const Ref<Texture2D> &p_image, int p_width, int p_ ERR_FAIL_COND(p_image.is_null()); ERR_FAIL_COND(p_image->get_width() == 0); ERR_FAIL_COND(p_image->get_height() == 0); + ERR_FAIL_COND(p_width < 0); + ERR_FAIL_COND(p_height < 0); + ItemImage *item = memnew(ItemImage); if (p_region.has_area()) { @@ -3247,6 +3261,9 @@ void RichTextLabel::update_image(const Variant &p_key, BitField<ImageUpdateMask> ERR_FAIL_COND(p_image->get_height() == 0); } + ERR_FAIL_COND(p_width < 0); + ERR_FAIL_COND(p_height < 0); + bool reshape = false; Item *it = main; @@ -3298,6 +3315,9 @@ void RichTextLabel::update_image(const Variant &p_key, BitField<ImageUpdateMask> } } if ((p_mask & UPDATE_SIZE) || (p_mask & UPDATE_REGION) || (p_mask & UPDATE_TEXTURE)) { + ERR_FAIL_COND(item->image.is_null()); + ERR_FAIL_COND(item->image->get_width() == 0); + ERR_FAIL_COND(item->image->get_height() == 0); Size2 new_size = _get_image_size(item->image, item->rq_size.width, item->rq_size.height, item->region); if (item->size != new_size) { reshape = true; diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index a4c239cf53..1d06ce05ae 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -4544,6 +4544,8 @@ TreeItem *Tree::get_selected() const { void Tree::set_selected(TreeItem *p_item, int p_column) { ERR_FAIL_INDEX(p_column, columns.size()); ERR_FAIL_NULL(p_item); + ERR_FAIL_COND_MSG(p_item->get_tree() != this, "The provided TreeItem does not belong to this Tree. Ensure that the TreeItem is a part of the Tree before setting it as selected."); + select_single_item(p_item, get_root(), p_column); } |
