diff options
Diffstat (limited to 'scene/gui')
| -rw-r--r-- | scene/gui/code_edit.cpp | 32 | ||||
| -rw-r--r-- | scene/gui/color_picker.cpp | 4 | ||||
| -rw-r--r-- | scene/gui/control.cpp | 4 | ||||
| -rw-r--r-- | scene/gui/label.cpp | 34 | ||||
| -rw-r--r-- | scene/gui/label.h | 1 | ||||
| -rw-r--r-- | scene/gui/popup.cpp | 38 | ||||
| -rw-r--r-- | scene/gui/popup.h | 1 | ||||
| -rw-r--r-- | scene/gui/rich_text_label.cpp | 49 | ||||
| -rw-r--r-- | scene/gui/rich_text_label.h | 2 | ||||
| -rw-r--r-- | scene/gui/text_edit.cpp | 35 | ||||
| -rw-r--r-- | scene/gui/text_edit.h | 3 | ||||
| -rw-r--r-- | scene/gui/tree.cpp | 1 |
12 files changed, 158 insertions, 46 deletions
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index 70707dba11..8a5d04f49c 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -1248,37 +1248,41 @@ bool CodeEdit::is_drawing_executing_lines_gutter() const { } void CodeEdit::_main_gutter_draw_callback(int p_line, int p_gutter, const Rect2 &p_region) { - bool shift_pressed = Input::get_singleton()->is_key_pressed(Key::SHIFT); - if (draw_breakpoints && breakpoint_icon.is_valid()) { - bool hovering = p_region.has_point(get_local_mouse_pos()); 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); if (breakpointed || (hovering && !is_dragging_cursor() && !shift_pressed)) { int padding = p_region.size.x / 6; + + Color use_color = 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; - - // Darken icon when hovering, shift not pressed & not yet breakpointed. - Color use_color = hovering && !breakpointed && !shift_pressed ? breakpoint_color.darkened(0.4) : breakpoint_color; breakpoint_icon->draw_rect(get_canvas_item(), icon_region, false, use_color); } } if (draw_bookmarks && bookmark_icon.is_valid()) { - bool hovering = p_region.has_point(get_local_mouse_pos()); 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); if (bookmarked || (hovering && !is_dragging_cursor() && shift_pressed)) { int horizontal_padding = p_region.size.x / 2; int vertical_padding = p_region.size.y / 4; + + Color use_color = 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); - - // Darken icon when hovering, shift pressed & not yet bookmarked. - Color use_color = hovering && !bookmarked && shift_pressed ? bookmark_color.darkened(0.4) : bookmark_color; bookmark_icon->draw_rect(get_canvas_item(), icon_region, false, use_color); } } @@ -1287,10 +1291,10 @@ void CodeEdit::_main_gutter_draw_callback(int p_line, int p_gutter, const Rect2 int horizontal_padding = p_region.size.x / 10; int vertical_padding = p_region.size.y / 4; - Rect2 executing_line_region = p_region; - executing_line_region.position += Point2(horizontal_padding, vertical_padding); - executing_line_region.size -= Point2(horizontal_padding, vertical_padding) * 2; - executing_line_icon->draw_rect(get_canvas_item(), executing_line_region, false, executing_line_color); + 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); } } diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index f1e18640e6..a2c138c0b2 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -1403,9 +1403,7 @@ void ColorPicker::_screen_pick_pressed() { screen->show(); } screen->move_to_front(); -#ifndef _MSC_VER -#warning show modal no longer works, needs to be converted to a popup -#endif + // TODO: show modal no longer works, needs to be converted to a popup. //screen->show_modal(); } diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 2dcae2553c..488ae762c5 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -2885,8 +2885,8 @@ void Control::_notification(int p_notification) { if (data.parent_canvas_item) { data.parent_canvas_item->disconnect("item_rect_changed", callable_mp(this, &Control::_size_changed)); data.parent_canvas_item = nullptr; - } else if (!is_set_as_top_level()) { - //disconnect viewport + } else { + // Disconnect viewport. Viewport *viewport = get_viewport(); ERR_FAIL_COND(!viewport); viewport->disconnect("size_changed", callable_mp(this, &Control::_size_changed)); diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index bf7c59d1cd..2203573bbc 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -117,7 +117,7 @@ void Label::_shape() { for (int i = 0; i < TextServer::SPACING_MAX; i++) { TS->shaped_text_set_spacing(text_rid, TextServer::SpacingType(i), font->get_spacing(TextServer::SpacingType(i))); } - TS->shaped_text_set_bidi_override(text_rid, structured_text_parser(st_parser, st_args, text)); + TS->shaped_text_set_bidi_override(text_rid, structured_text_parser(st_parser, st_args, txt)); dirty = false; font_dirty = false; lines_dirty = true; @@ -288,6 +288,36 @@ void Label::_update_theme_item_cache() { theme_cache.font_shadow_outline_size = get_theme_constant(SNAME("shadow_outline_size")); } +PackedStringArray Label::get_configuration_warnings() const { + PackedStringArray warnings = Control::get_configuration_warnings(); + + // Ensure that the font can render all of the required glyphs. + Ref<Font> font; + if (settings.is_valid()) { + font = settings->get_font(); + } + if (font.is_null()) { + font = theme_cache.font; + } + + if (font.is_valid()) { + if (dirty || font_dirty || lines_dirty) { + const_cast<Label *>(this)->_shape(); + } + + const Glyph *glyph = TS->shaped_text_get_glyphs(text_rid); + int64_t glyph_count = TS->shaped_text_get_glyph_count(text_rid); + for (int64_t i = 0; i < glyph_count; i++) { + if (glyph[i].font_rid == RID()) { + warnings.push_back(RTR("The current font does not support rendering one or more characters used in this Label's text.")); + break; + } + } + } + + return warnings; +} + void Label::_notification(int p_what) { switch (p_what) { case NOTIFICATION_TRANSLATION_CHANGED: { @@ -302,6 +332,7 @@ void Label::_notification(int p_what) { dirty = true; queue_redraw(); + update_configuration_warnings(); } break; case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: { @@ -674,6 +705,7 @@ void Label::set_text(const String &p_string) { } queue_redraw(); update_minimum_size(); + update_configuration_warnings(); } void Label::_invalidate() { diff --git a/scene/gui/label.h b/scene/gui/label.h index b79c94a5ba..41d7049b22 100644 --- a/scene/gui/label.h +++ b/scene/gui/label.h @@ -93,6 +93,7 @@ protected: public: virtual Size2 get_minimum_size() const override; + virtual PackedStringArray get_configuration_warnings() const override; void set_horizontal_alignment(HorizontalAlignment p_alignment); HorizontalAlignment get_horizontal_alignment() const; diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index a6915f9e61..434eb87e7a 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -77,28 +77,36 @@ void Popup::_update_theme_item_cache() { void Popup::_notification(int p_what) { switch (p_what) { case NOTIFICATION_VISIBILITY_CHANGED: { - if (is_visible()) { - _initialize_visible_parents(); - } else { - _deinitialize_visible_parents(); - emit_signal(SNAME("popup_hide")); - popped_up = false; + if (!is_in_edited_scene_root()) { + if (is_visible()) { + _initialize_visible_parents(); + } else { + _deinitialize_visible_parents(); + emit_signal(SNAME("popup_hide")); + popped_up = false; + } } } break; case NOTIFICATION_WM_WINDOW_FOCUS_IN: { - if (has_focus()) { - popped_up = true; + if (!is_in_edited_scene_root()) { + if (has_focus()) { + popped_up = true; + } } } break; case NOTIFICATION_EXIT_TREE: { - _deinitialize_visible_parents(); + if (!is_in_edited_scene_root()) { + _deinitialize_visible_parents(); + } } break; case NOTIFICATION_WM_CLOSE_REQUEST: case NOTIFICATION_APPLICATION_FOCUS_OUT: { - _close_pressed(); + if (!is_in_edited_scene_root()) { + _close_pressed(); + } } break; } } @@ -126,6 +134,16 @@ void Popup::_bind_methods() { ADD_SIGNAL(MethodInfo("popup_hide")); } +void Popup::_validate_property(PropertyInfo &p_property) const { + if ( + p_property.name == "transient" || + p_property.name == "exclusive" || + p_property.name == "popup_window" || + p_property.name == "unfocusable") { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; + } +} + Rect2i Popup::_popup_adjust_rect() const { ERR_FAIL_COND_V(!is_inside_tree(), Rect2()); Rect2i parent_rect = get_usable_parent_rect(); diff --git a/scene/gui/popup.h b/scene/gui/popup.h index 0d6ca25c18..57b811cadb 100644 --- a/scene/gui/popup.h +++ b/scene/gui/popup.h @@ -59,6 +59,7 @@ protected: virtual void _update_theme_item_cache() override; void _notification(int p_what); static void _bind_methods(); + void _validate_property(PropertyInfo &p_property) const; virtual void _parent_focused(); diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 5060bacba5..9217f31310 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -2956,7 +2956,7 @@ void RichTextLabel::_remove_item(Item *p_item, const int p_line, const int p_sub memdelete(p_item); } -void RichTextLabel::add_image(const Ref<Texture2D> &p_image, const int p_width, const int p_height, const Color &p_color, InlineAlignment p_alignment) { +void RichTextLabel::add_image(const Ref<Texture2D> &p_image, const int p_width, const int p_height, const Color &p_color, InlineAlignment p_alignment, const Rect2 &p_region) { _stop_thread(); MutexLock data_lock(data_mutex); @@ -2969,7 +2969,15 @@ void RichTextLabel::add_image(const Ref<Texture2D> &p_image, const int p_width, ERR_FAIL_COND(p_image->get_height() == 0); ItemImage *item = memnew(ItemImage); - item->image = p_image; + if (p_region.has_area()) { + Ref<AtlasTexture> atlas_tex = memnew(AtlasTexture); + atlas_tex->set_atlas(p_image); + atlas_tex->set_region(p_region); + item->image = atlas_tex; + } else { + item->image = p_image; + } + item->color = p_color; item->inline_align = p_alignment; @@ -2981,17 +2989,30 @@ void RichTextLabel::add_image(const Ref<Texture2D> &p_image, const int p_width, item->size.height = p_height; } else { // calculate height to keep aspect ratio - item->size.height = p_image->get_height() * p_width / p_image->get_width(); + if (p_region.has_area()) { + item->size.height = p_region.get_size().height * p_width / p_region.get_size().width; + } else { + item->size.height = p_image->get_height() * p_width / p_image->get_width(); + } } } else { if (p_height > 0) { // custom height item->size.height = p_height; // calculate width to keep aspect ratio - item->size.width = p_image->get_width() * p_height / p_image->get_height(); + if (p_region.has_area()) { + item->size.width = p_region.get_size().width * p_height / p_region.get_size().height; + } else { + item->size.width = p_image->get_width() * p_height / p_image->get_height(); + } } else { - // keep original width and height - item->size = p_image->get_size(); + if (p_region.has_area()) { + // if the image has a region, keep the region size + item->size = p_region.get_size(); + } else { + // keep original width and height + item->size = p_image->get_size(); + } } } @@ -4126,6 +4147,18 @@ void RichTextLabel::append_text(const String &p_bbcode) { Ref<Texture2D> texture = ResourceLoader::load(image, "Texture2D"); if (texture.is_valid()) { + Rect2 region; + OptionMap::Iterator region_option = bbcode_options.find("region"); + if (region_option) { + Vector<String> region_values = region_option->value.split(",", false); + if (region_values.size() == 4) { + region.position.x = region_values[0].to_float(); + region.position.y = region_values[1].to_float(); + region.size.x = region_values[2].to_float(); + region.size.y = region_values[3].to_float(); + } + } + Color color = Color(1.0, 1.0, 1.0); OptionMap::Iterator color_option = bbcode_options.find("color"); if (color_option) { @@ -4154,7 +4187,7 @@ void RichTextLabel::append_text(const String &p_bbcode) { } } - add_image(texture, width, height, color, (InlineAlignment)alignment); + add_image(texture, width, height, color, (InlineAlignment)alignment, region); } pos = end; @@ -5209,7 +5242,7 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("get_parsed_text"), &RichTextLabel::get_parsed_text); ClassDB::bind_method(D_METHOD("add_text", "text"), &RichTextLabel::add_text); ClassDB::bind_method(D_METHOD("set_text", "text"), &RichTextLabel::set_text); - ClassDB::bind_method(D_METHOD("add_image", "image", "width", "height", "color", "inline_align"), &RichTextLabel::add_image, DEFVAL(0), DEFVAL(0), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(INLINE_ALIGNMENT_CENTER)); + ClassDB::bind_method(D_METHOD("add_image", "image", "width", "height", "color", "inline_align", "region"), &RichTextLabel::add_image, DEFVAL(0), DEFVAL(0), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(INLINE_ALIGNMENT_CENTER), DEFVAL(Rect2(0, 0, 0, 0))); ClassDB::bind_method(D_METHOD("newline"), &RichTextLabel::add_newline); ClassDB::bind_method(D_METHOD("remove_line", "line"), &RichTextLabel::remove_line); ClassDB::bind_method(D_METHOD("push_font", "font", "font_size"), &RichTextLabel::push_font); diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index 73b7676c22..04a682349d 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -569,7 +569,7 @@ private: public: String get_parsed_text() const; void add_text(const String &p_text); - void add_image(const Ref<Texture2D> &p_image, const int p_width = 0, const int p_height = 0, const Color &p_color = Color(1.0, 1.0, 1.0), InlineAlignment p_alignment = INLINE_ALIGNMENT_CENTER); + void add_image(const Ref<Texture2D> &p_image, const int p_width = 0, const int p_height = 0, const Color &p_color = Color(1.0, 1.0, 1.0), InlineAlignment p_alignment = INLINE_ALIGNMENT_CENTER, const Rect2 &p_region = Rect2(0, 0, 0, 0)); void add_newline(); bool remove_line(const int p_line); void push_dropcap(const String &p_string, const Ref<Font> &p_font, int p_size, const Rect2 &p_dropcap_margins = Rect2(), const Color &p_color = Color(1, 1, 1), int p_ol_size = 0, const Color &p_ol_color = Color(0, 0, 0, 0)); diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index f8501f3570..4cd244306c 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1692,7 +1692,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { continue; } - if (mpos.x > left_margin && mpos.x <= (left_margin + gutters[i].width) - 3) { + if (mpos.x >= left_margin && mpos.x <= left_margin + gutters[i].width) { emit_signal(SNAME("gutter_clicked"), row, i); return; } @@ -1933,7 +1933,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { continue; } - if (mpos.x > left_margin && mpos.x <= (left_margin + gutters[i].width) - 3) { + if (mpos.x >= left_margin && mpos.x < left_margin + gutters[i].width) { // We are in this gutter i's horizontal area. current_hovered_gutter = Vector2i(i, hovered_row); break; @@ -2192,8 +2192,17 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { return; } - // Handle Unicode (if no modifiers active). Tab has a value of 0x09. - if (allow_unicode_handling && editable && (k->get_unicode() >= 32 || k->get_keycode() == Key::TAB)) { + // Handle tab as it has no set unicode value. + if (k->is_action("ui_text_indent", true)) { + if (editable) { + insert_text_at_caret("\t"); + } + accept_event(); + return; + } + + // Handle Unicode (if no modifiers active). + if (allow_unicode_handling && editable && k->get_unicode() >= 32) { handle_unicode_input(k->get_unicode()); accept_event(); return; @@ -2997,7 +3006,7 @@ Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const { continue; } - if (p_pos.x > left_margin && p_pos.x <= (left_margin + gutters[i].width) - 3) { + if (p_pos.x >= left_margin && p_pos.x < left_margin + gutters[i].width) { if (gutters[i].clickable || is_line_gutter_clickable(row, i)) { return CURSOR_POINTING_HAND; } @@ -4380,7 +4389,7 @@ int TextEdit::add_caret(int p_line, int p_col) { } void TextEdit::remove_caret(int p_caret) { - ERR_FAIL_COND(carets.size() <= 0); + ERR_FAIL_COND_MSG(carets.size() <= 1, "The main caret should not be removed."); ERR_FAIL_INDEX(p_caret, carets.size()); carets.remove_at(p_caret); caret_index_edit_dirty = true; @@ -4816,10 +4825,11 @@ void TextEdit::select_word_under_caret(int p_caret) { continue; } - select(get_caret_line(c), begin, get_caret_column(c), end, c); + select(get_caret_line(c), begin, get_caret_line(c), end, c); // Move the caret to the end of the word for easier editing. set_caret_column(end, false, c); } + merge_overlapping_carets(); } void TextEdit::select(int p_from_line, int p_from_column, int p_to_line, int p_to_column, int p_caret) { @@ -5088,6 +5098,14 @@ bool TextEdit::is_scroll_past_end_of_file_enabled() const { return scroll_past_end_of_file_enabled; } +VScrollBar *TextEdit::get_v_scroll_bar() const { + return v_scroll; +} + +HScrollBar *TextEdit::get_h_scroll_bar() const { + return h_scroll; +} + void TextEdit::set_v_scroll(double p_scroll) { v_scroll->set_value(p_scroll); int max_v_scroll = v_scroll->get_max() - v_scroll->get_page(); @@ -6020,6 +6038,9 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("set_smooth_scroll_enabled", "enable"), &TextEdit::set_smooth_scroll_enabled); ClassDB::bind_method(D_METHOD("is_smooth_scroll_enabled"), &TextEdit::is_smooth_scroll_enabled); + ClassDB::bind_method(D_METHOD("get_v_scroll_bar"), &TextEdit::get_v_scroll_bar); + ClassDB::bind_method(D_METHOD("get_h_scroll_bar"), &TextEdit::get_h_scroll_bar); + ClassDB::bind_method(D_METHOD("set_v_scroll", "value"), &TextEdit::set_v_scroll); ClassDB::bind_method(D_METHOD("get_v_scroll"), &TextEdit::get_v_scroll); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index a8e087909e..e4af621b73 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -886,6 +886,9 @@ public: void set_scroll_past_end_of_file_enabled(const bool p_enabled); bool is_scroll_past_end_of_file_enabled() const; + VScrollBar *get_v_scroll_bar() const; + HScrollBar *get_h_scroll_bar() const; + void set_v_scroll(double p_scroll); double get_v_scroll() const; diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index acf398305c..2e8fa1e606 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -1504,6 +1504,7 @@ void TreeItem::_bind_methods() { ClassDB::bind_method(D_METHOD("set_button", "column", "button_idx", "button"), &TreeItem::set_button); ClassDB::bind_method(D_METHOD("erase_button", "column", "button_idx"), &TreeItem::erase_button); ClassDB::bind_method(D_METHOD("set_button_disabled", "column", "button_idx", "disabled"), &TreeItem::set_button_disabled); + ClassDB::bind_method(D_METHOD("set_button_color", "column", "button_idx", "color"), &TreeItem::set_button_color); ClassDB::bind_method(D_METHOD("is_button_disabled", "column", "button_idx"), &TreeItem::is_button_disabled); ClassDB::bind_method(D_METHOD("set_tooltip_text", "column", "tooltip"), &TreeItem::set_tooltip_text); |