diff options
Diffstat (limited to 'scene/gui')
| -rw-r--r-- | scene/gui/code_edit.cpp | 23 | ||||
| -rw-r--r-- | scene/gui/code_edit.h | 2 | ||||
| -rw-r--r-- | scene/gui/color_picker.cpp | 6 | ||||
| -rw-r--r-- | scene/gui/label.cpp | 85 | ||||
| -rw-r--r-- | scene/gui/menu_button.cpp | 6 | ||||
| -rw-r--r-- | scene/gui/option_button.cpp | 2 | ||||
| -rw-r--r-- | scene/gui/rich_text_label.cpp | 114 | ||||
| -rw-r--r-- | scene/gui/rich_text_label.h | 18 |
8 files changed, 127 insertions, 129 deletions
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index e7769f9372..4dfd6902e6 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -467,7 +467,7 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) { } /* MISC */ - if (k->is_action("ui_cancel", true)) { + if (!code_hint.is_empty() && k->is_action("ui_cancel", true)) { set_code_hint(""); accept_event(); return; @@ -1725,14 +1725,17 @@ bool CodeEdit::is_code_completion_enabled() const { void CodeEdit::set_code_completion_prefixes(const TypedArray<String> &p_prefixes) { code_completion_prefixes.clear(); for (int i = 0; i < p_prefixes.size(); i++) { - code_completion_prefixes.insert(p_prefixes[i]); + const String prefix = p_prefixes[i]; + + ERR_CONTINUE_MSG(prefix.is_empty(), "Code completion prefix cannot be empty."); + code_completion_prefixes.insert(prefix[0]); } } TypedArray<String> CodeEdit::get_code_completion_prefixes() const { TypedArray<String> prefixes; - for (Set<String>::Element *E = code_completion_prefixes.front(); E; E = E->next()) { - prefixes.push_back(E->get()); + for (const Set<char32_t>::Element *E = code_completion_prefixes.front(); E; E = E->next()) { + prefixes.push_back(String::chr(E->get())); } return prefixes; } @@ -1795,9 +1798,9 @@ void CodeEdit::request_code_completion(bool p_force) { String line = get_line(get_caret_line()); int ofs = CLAMP(get_caret_column(), 0, line.length()); - if (ofs > 0 && (is_in_string(get_caret_line(), ofs) != -1 || _is_char(line[ofs - 1]) || code_completion_prefixes.has(String::chr(line[ofs - 1])))) { + if (ofs > 0 && (is_in_string(get_caret_line(), ofs) != -1 || _is_char(line[ofs - 1]) || code_completion_prefixes.has(line[ofs - 1]))) { emit_signal(SNAME("request_code_completion")); - } else if (ofs > 1 && line[ofs - 1] == ' ' && code_completion_prefixes.has(String::chr(line[ofs - 2]))) { + } else if (ofs > 1 && line[ofs - 1] == ' ' && code_completion_prefixes.has(line[ofs - 2])) { emit_signal(SNAME("request_code_completion")); } } @@ -1969,7 +1972,7 @@ void CodeEdit::confirm_code_completion(bool p_replace) { end_complex_operation(); cancel_code_completion(); - if (code_completion_prefixes.has(String::chr(last_completion_char))) { + if (code_completion_prefixes.has(last_completion_char)) { request_code_completion(); } } @@ -2764,7 +2767,7 @@ void CodeEdit::_filter_code_completion_candidates_impl() { bool prev_is_word = false; /* Cancel if we are at the close of a string. */ - if (in_string == -1 && first_quote_col == cofs - 1) { + if (caret_column > 0 && in_string == -1 && first_quote_col == cofs - 1) { cancel_code_completion(); return; /* In a string, therefore we are trying to complete the string text. */ @@ -2790,9 +2793,9 @@ void CodeEdit::_filter_code_completion_candidates_impl() { /* If all else fails, check for a prefix. */ /* Single space between caret and prefix is okay. */ bool prev_is_prefix = false; - if (cofs > 0 && code_completion_prefixes.has(String::chr(line[cofs - 1]))) { + if (cofs > 0 && code_completion_prefixes.has(line[cofs - 1])) { prev_is_prefix = true; - } else if (cofs > 1 && line[cofs - 1] == ' ' && code_completion_prefixes.has(String::chr(line[cofs - 2]))) { + } else if (cofs > 1 && line[cofs - 1] == ' ' && code_completion_prefixes.has(line[cofs - 2])) { prev_is_prefix = true; } diff --git a/scene/gui/code_edit.h b/scene/gui/code_edit.h index 740548d559..d8eccb7d32 100644 --- a/scene/gui/code_edit.h +++ b/scene/gui/code_edit.h @@ -214,7 +214,7 @@ private: int code_completion_longest_line = 0; Rect2i code_completion_rect; - Set<String> code_completion_prefixes; + Set<char32_t> code_completion_prefixes; List<ScriptCodeCompletionOption> code_completion_option_submitted; List<ScriptCodeCompletionOption> code_completion_option_sources; String code_completion_base; diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 1afb0b8e9d..efb6b7d200 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -1308,6 +1308,8 @@ void ColorPickerButton::_modal_closed() { void ColorPickerButton::pressed() { _update_picker(); + Size2 size = get_size() * get_viewport()->get_canvas_transform().get_scale(); + popup->set_as_minsize(); picker->_update_presets(); @@ -1319,13 +1321,13 @@ void ColorPickerButton::pressed() { if (i > 1) { cp_rect.position.y = get_screen_position().y - cp_rect.size.y; } else { - cp_rect.position.y = get_screen_position().y + get_size().height; + cp_rect.position.y = get_screen_position().y + size.height; } if (i & 1) { cp_rect.position.x = get_screen_position().x; } else { - cp_rect.position.x = get_screen_position().x - MAX(0, (cp_rect.size.x - get_size().x)); + cp_rect.position.x = get_screen_position().x - MAX(0, (cp_rect.size.x - size.x)); } if (usable_rect.encloses(cp_rect)) { diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index 5600816b2d..560bcd8e61 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -92,8 +92,12 @@ void Label::_shape() { const Ref<Font> &font = get_theme_font(SNAME("font")); int font_size = get_theme_font_size(SNAME("font_size")); ERR_FAIL_COND(font.is_null()); - TS->shaped_text_add_string(text_rid, (uppercase) ? xl_text.to_upper() : xl_text, font->get_rids(), font_size, opentype_features, (language != "") ? language : TranslationServer::get_singleton()->get_tool_locale()); - TS->shaped_text_set_bidi_override(text_rid, structured_text_parser(st_parser, st_args, xl_text)); + String text = (uppercase) ? xl_text.to_upper() : xl_text; + if (visible_chars >= 0) { + text = text.substr(0, visible_chars); + } + TS->shaped_text_add_string(text_rid, text, font->get_rids(), font_size, opentype_features, (language != "") ? language : TranslationServer::get_singleton()->get_tool_locale()); + TS->shaped_text_set_bidi_override(text_rid, structured_text_parser(st_parser, st_args, text)); dirty = false; lines_dirty = true; } @@ -258,6 +262,9 @@ void Label::_notification(int p_what) { return; // Nothing new. } xl_text = new_text; + if (percent_visible < 1) { + visible_chars = get_total_character_count() * percent_visible; + } dirty = true; update(); @@ -342,24 +349,6 @@ void Label::_notification(int p_what) { } } - int visible_glyphs = -1; - int glyhps_drawn = 0; - if (percent_visible < 1) { - int total_glyphs = 0; - for (int i = lines_skipped; i < last_line; i++) { - const Vector<TextServer::Glyph> visual = TS->shaped_text_get_glyphs(lines_rid[i]); - const TextServer::Glyph *glyphs = visual.ptr(); - int gl_size = visual.size(); - for (int j = 0; j < gl_size; j++) { - if ((glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) { - total_glyphs++; - } - } - } - - visible_glyphs = MIN(total_glyphs, visible_chars); - } - Vector2 ofs; ofs.y = style->get_offset().y + vbegin; for (int i = lines_skipped; i < last_line; i++) { @@ -407,14 +396,6 @@ void Label::_notification(int p_what) { // Draw main text. for (int j = 0; j < gl_size; j++) { for (int k = 0; k < glyphs[j].repeat; k++) { - if (visible_glyphs != -1) { - if ((glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) { - if (glyhps_drawn >= visible_glyphs) { - return; - } - } - } - // Trim when necessary. if (trim_data.trim_pos >= 0) { if (rtl) { @@ -431,7 +412,6 @@ void Label::_notification(int p_what) { // Draw glyph outlines and shadow. draw_glyph_outline(glyphs[j], ci, font_color, font_shadow_color, font_outline_color, shadow_outline_size, outline_size, offset, shadow_ofs); offset.x += glyphs[j].advance; - glyhps_drawn++; } } // Draw LTR ellipsis string when necessary. @@ -462,14 +442,6 @@ void Label::_notification(int p_what) { // Draw main text. for (int j = 0; j < gl_size; j++) { for (int k = 0; k < glyphs[j].repeat; k++) { - if (visible_glyphs != -1) { - if ((glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) { - if (glyhps_drawn >= visible_glyphs) { - return; - } - } - } - // Trim when necessary. if (trim_data.trim_pos >= 0) { if (rtl) { @@ -486,7 +458,6 @@ void Label::_notification(int p_what) { // Draw glyph outlines and shadow. draw_glyph(glyphs[j], ci, font_color, ofs); ofs.x += glyphs[j].advance; - glyhps_drawn++; } } // Draw LTR ellipsis string when necessary. @@ -709,16 +680,16 @@ String Label::get_text() const { } void Label::set_visible_characters(int p_amount) { - visible_chars = p_amount; - if (get_total_character_count() > 0) { - percent_visible = (float)p_amount / (float)get_total_character_count(); - } else { - percent_visible = 1.0; - } - if (p_amount == -1) { - lines_dirty = true; + if (visible_chars != p_amount) { + visible_chars = p_amount; + if (get_total_character_count() > 0) { + percent_visible = (float)p_amount / (float)get_total_character_count(); + } else { + percent_visible = 1.0; + } + dirty = true; + update(); } - update(); } int Label::get_visible_characters() const { @@ -726,15 +697,17 @@ int Label::get_visible_characters() const { } void Label::set_percent_visible(float p_percent) { - if (p_percent < 0 || p_percent >= 1) { - visible_chars = -1; - percent_visible = 1; - lines_dirty = true; - } else { - visible_chars = get_total_character_count() * p_percent; - percent_visible = p_percent; + if (percent_visible != p_percent) { + if (p_percent < 0 || p_percent >= 1) { + visible_chars = -1; + percent_visible = 1; + } else { + visible_chars = get_total_character_count() * p_percent; + percent_visible = p_percent; + } + dirty = true; + update(); } - update(); } float Label::get_percent_visible() const { @@ -889,7 +862,7 @@ void Label::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_text"), "set_clip_text", "is_clipping_text"); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_overrun_behavior", PROPERTY_HINT_ENUM, "Trim Nothing,Trim Characters,Trim Words,Ellipsis,Word Ellipsis"), "set_text_overrun_behavior", "get_text_overrun_behavior"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uppercase"), "set_uppercase", "is_uppercase"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters", PROPERTY_HINT_RANGE, "-1,128000,1", PROPERTY_USAGE_EDITOR), "set_visible_characters", "get_visible_characters"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters", PROPERTY_HINT_RANGE, "-1,128000,1"), "set_visible_characters", "get_visible_characters"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "percent_visible", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_percent_visible", "get_percent_visible"); ADD_PROPERTY(PropertyInfo(Variant::INT, "lines_skipped", PROPERTY_HINT_RANGE, "0,999,1"), "set_lines_skipped", "get_lines_skipped"); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_lines_visible", PROPERTY_HINT_RANGE, "-1,999,1"), "set_max_lines_visible", "get_max_lines_visible"); diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index 737ba84617..0cc53a7832 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -87,15 +87,15 @@ void MenuButton::_popup_visibility_changed(bool p_visible) { void MenuButton::pressed() { emit_signal(SNAME("about_to_popup")); - Size2 size = get_size(); + Size2 size = get_size() * get_viewport()->get_canvas_transform().get_scale(); Point2 gp = get_screen_position(); - gp.y += get_size().y; + gp.y += size.y; popup->set_position(gp); popup->set_size(Size2(size.width, 0)); - popup->set_parent_rect(Rect2(Point2(gp - popup->get_position()), get_size())); + popup->set_parent_rect(Rect2(Point2(gp - popup->get_position()), size)); popup->take_mouse_focus(); popup->popup(); } diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index d16e96dbec..2adeb2d947 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -115,7 +115,7 @@ void OptionButton::_selected(int p_which) { } void OptionButton::pressed() { - Size2 size = get_size(); + Size2 size = get_size() * get_viewport()->get_canvas_transform().get_scale(); popup->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y)); popup->set_size(Size2(size.width, 0)); popup->popup(); diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 562bac60c2..2314b7a1da 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -399,8 +399,9 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> // Shape current paragraph. String text; Item *it_to = (p_line + 1 < p_frame->lines.size()) ? p_frame->lines[p_line + 1].from : nullptr; + int remaining_characters = visible_characters - l.char_offset; for (Item *it = l.from; it && it != it_to; it = _get_next_item(it)) { - if (visible_characters >= 0 && l.char_offset + l.char_count > visible_characters) { + if (visible_characters >= 0 && remaining_characters <= 0) { break; } switch (it->type) { @@ -427,7 +428,8 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> } l.text_buf->add_string("\n", font, font_size, Dictionary(), ""); text += "\n"; - l.char_count += 1; + l.char_count++; + remaining_characters--; } break; case ITEM_TEXT: { ItemText *t = (ItemText *)it; @@ -442,9 +444,10 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> Dictionary font_ftr = _find_font_features(it); String lang = _find_language(it); String tx = t->text; - if (visible_characters >= 0 && l.char_offset + l.char_count + tx.length() > visible_characters) { - tx = tx.substr(0, l.char_offset + l.char_count + tx.length() - visible_characters); + if (visible_characters >= 0 && remaining_characters >= 0) { + tx = tx.substr(0, remaining_characters); } + remaining_characters -= tx.length(); l.text_buf->add_string(tx, font, font_size, font_ftr, lang); text += tx; @@ -454,7 +457,8 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> ItemImage *img = (ItemImage *)it; l.text_buf->add_object((uint64_t)it, img->image->get_size(), img->inline_align, 1); text += String::chr(0xfffc); - l.char_count += 1; + l.char_count++; + remaining_characters--; } break; case ITEM_TABLE: { ItemTable *table = static_cast<ItemTable *>(it); @@ -483,6 +487,7 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> int cell_ch = (char_offset - (l.char_offset + l.char_count)); l.char_count += cell_ch; t_char_count += cell_ch; + remaining_characters -= cell_ch; table->columns.write[column].min_width = MAX(table->columns[column].min_width, ceil(frame->lines[i].text_buf->get_size().x)); table->columns.write[column].max_width = MAX(table->columns[column].max_width, ceil(frame->lines[i].text_buf->get_non_wraped_size().x)); @@ -1374,8 +1379,8 @@ void RichTextLabel::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: case NOTIFICATION_ENTER_TREE: { - if (bbcode != "") { - set_bbcode(bbcode); + if (text != "") { + set_text(text); } main->first_invalid_line = 0; //invalidate ALL @@ -2767,10 +2772,10 @@ bool RichTextLabel::is_scroll_following() const { Error RichTextLabel::parse_bbcode(const String &p_bbcode) { clear(); - return append_bbcode(p_bbcode); + return append_text(p_bbcode); } -Error RichTextLabel::append_bbcode(const String &p_bbcode) { +Error RichTextLabel::append_text(const String &p_bbcode) { int pos = 0; List<String> tag_stack; @@ -3824,8 +3829,8 @@ int RichTextLabel::get_selection_to() const { return selection.to_frame->lines[selection.to_line].char_offset + selection.to_char - 1; } -void RichTextLabel::set_bbcode(const String &p_bbcode) { - bbcode = p_bbcode; +void RichTextLabel::set_text(const String &p_bbcode) { + text = p_bbcode; if (is_inside_tree() && use_bbcode) { parse_bbcode(p_bbcode); } else { // raw text @@ -3834,8 +3839,8 @@ void RichTextLabel::set_bbcode(const String &p_bbcode) { } } -String RichTextLabel::get_bbcode() const { - return bbcode; +String RichTextLabel::get_text() const { + return text; } void RichTextLabel::set_use_bbcode(bool p_enable) { @@ -3843,19 +3848,24 @@ void RichTextLabel::set_use_bbcode(bool p_enable) { return; } use_bbcode = p_enable; - set_bbcode(bbcode); notify_property_list_changed(); + set_text(text); } bool RichTextLabel::is_using_bbcode() const { return use_bbcode; } -String RichTextLabel::get_text() { +String RichTextLabel::get_parsed_text() const { String text = ""; Item *it = main; while (it) { - if (it->type == ITEM_TEXT) { + if (it->type == ITEM_DROPCAP) { + const ItemDropcap *dc = (ItemDropcap *)it; + if (dc != nullptr) { + text += dc->text; + } + } else if (it->type == ITEM_TEXT) { ItemText *t = static_cast<ItemText *>(it); text += t->text; } else if (it->type == ITEM_NEWLINE) { @@ -3870,11 +3880,6 @@ String RichTextLabel::get_text() { return text; } -void RichTextLabel::set_text(const String &p_string) { - clear(); - add_text(p_string); -} - void RichTextLabel::set_text_direction(Control::TextDirection p_text_direction) { ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3); if (text_direction != p_text_direction) { @@ -3931,7 +3936,6 @@ void RichTextLabel::set_percent_visible(float p_percent) { if (p_percent < 0 || p_percent >= 1) { visible_characters = -1; percent_visible = 1; - } else { visible_characters = get_total_character_count() * p_percent; percent_visible = p_percent; @@ -3948,8 +3952,8 @@ float RichTextLabel::get_percent_visible() const { void RichTextLabel::set_effects(Array p_effects) { custom_effects = p_effects; - if ((bbcode != "") && use_bbcode) { - parse_bbcode(bbcode); + if ((text != "") && use_bbcode) { + parse_bbcode(text); } } @@ -3963,8 +3967,8 @@ void RichTextLabel::install_effect(const Variant effect) { if (rteffect.is_valid()) { custom_effects.push_back(effect); - if ((bbcode != "") && use_bbcode) { - parse_bbcode(bbcode); + if ((text != "") && use_bbcode) { + parse_bbcode(text); } } } @@ -3977,14 +3981,20 @@ int RichTextLabel::get_content_height() const { return total_height; } -void RichTextLabel::_validate_property(PropertyInfo &property) const { - if (!use_bbcode && property.name == "bbcode_text") { - property.usage = PROPERTY_USAGE_NOEDITOR; +#ifndef DISABLE_DEPRECATED +// People will be very angry, if their texts get erased, because of #39148. (3.x -> 4.0) +// Altough some people may not used bbcode_text, so we only overwrite, if bbcode_text is not empty +bool RichTextLabel::_set(const StringName &p_name, const Variant &p_value) { + if (p_name == "bbcode_text" && !((String)p_value).is_empty()) { + set_text(p_value); + return true; } + return false; } +#endif void RichTextLabel::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_text"), &RichTextLabel::get_text); + 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_ALIGN_CENTER)); @@ -4062,10 +4072,9 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("get_selected_text"), &RichTextLabel::get_selected_text); ClassDB::bind_method(D_METHOD("parse_bbcode", "bbcode"), &RichTextLabel::parse_bbcode); - ClassDB::bind_method(D_METHOD("append_bbcode", "bbcode"), &RichTextLabel::append_bbcode); + ClassDB::bind_method(D_METHOD("append_text", "bbcode"), &RichTextLabel::append_text); - ClassDB::bind_method(D_METHOD("set_bbcode", "text"), &RichTextLabel::set_bbcode); - ClassDB::bind_method(D_METHOD("get_bbcode"), &RichTextLabel::get_bbcode); + ClassDB::bind_method(D_METHOD("get_text"), &RichTextLabel::get_text); ClassDB::bind_method(D_METHOD("set_visible_characters", "amount"), &RichTextLabel::set_visible_characters); ClassDB::bind_method(D_METHOD("get_visible_characters"), &RichTextLabel::get_visible_characters); @@ -4092,16 +4101,13 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("get_effects"), &RichTextLabel::get_effects); ClassDB::bind_method(D_METHOD("install_effect", "effect"), &RichTextLabel::install_effect); - ADD_GROUP("BBCode", "bbcode_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bbcode_enabled"), "set_use_bbcode", "is_using_bbcode"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "bbcode_text", PROPERTY_HINT_MULTILINE_TEXT), "set_bbcode", "get_bbcode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters", PROPERTY_HINT_RANGE, "-1,128000,1"), "set_visible_characters", "get_visible_characters"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "percent_visible", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_percent_visible", "get_percent_visible"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "meta_underlined"), "set_meta_underline", "is_meta_underlined"); ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_size", PROPERTY_HINT_RANGE, "0,24,1"), "set_tab_size", "get_tab_size"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT), "set_text", "get_text"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bbcode_enabled"), "set_use_bbcode", "is_using_bbcode"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fit_content_height"), "set_fit_content_height", "is_fit_content_height_enabled"); @@ -4163,16 +4169,20 @@ void RichTextLabel::_bind_methods() { } void RichTextLabel::set_visible_characters(int p_visible) { - visible_characters = p_visible; - if (p_visible == -1) { - percent_visible = 1; - } else { - int total_char_count = get_total_character_count(); - if (total_char_count > 0) { - percent_visible = (float)p_visible / (float)total_char_count; + if (visible_characters != p_visible) { + visible_characters = p_visible; + if (p_visible == -1) { + percent_visible = 1; + } else { + int total_char_count = get_total_character_count(); + if (total_char_count > 0) { + percent_visible = (float)p_visible / (float)total_char_count; + } } + main->first_invalid_line = 0; //invalidate ALL + _validate_line_caches(main); + update(); } - update(); } int RichTextLabel::get_visible_characters() const { @@ -4180,9 +4190,19 @@ int RichTextLabel::get_visible_characters() const { } int RichTextLabel::get_total_character_count() const { + // Note: Do not use line buffer "char_count", it includes only visible characters. int tc = 0; - for (int i = 0; i < current_frame->lines.size(); i++) { - tc += current_frame->lines[i].char_count; + Item *it = main; + while (it) { + if (it->type == ITEM_TEXT) { + ItemText *t = static_cast<ItemText *>(it); + tc += t->text.length(); + } else if (it->type == ITEM_NEWLINE) { + tc++; + } else if (it->type == ITEM_IMAGE) { + tc++; + } + it = _get_next_item(it, true); } return tc; diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index f25a8bf193..806f684b67 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -85,7 +85,6 @@ public: protected: void _notification(int p_what); static void _bind_methods(); - void _validate_property(PropertyInfo &property) const override; private: struct Item; @@ -452,16 +451,19 @@ private: virtual Dictionary parse_expressions_for_values(Vector<String> p_expressions); void _draw_fbg_boxes(RID p_ci, RID p_rid, Vector2 line_off, Item *it_from, Item *it_to, int start, int end, int fbg_flag); - +#ifndef DISABLE_DEPRECATED + // Kept for compatibility from 3.x to 4.0. + bool _set(const StringName &p_name, const Variant &p_value); +#endif bool use_bbcode = false; - String bbcode; + String text; int fixed_width = -1; bool fit_content_height = false; public: - String get_text(); + 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), InlineAlign p_align = INLINE_ALIGN_CENTER); void add_newline(); @@ -548,15 +550,13 @@ public: void selection_copy(); Error parse_bbcode(const String &p_bbcode); - Error append_bbcode(const String &p_bbcode); + Error append_text(const String &p_bbcode); void set_use_bbcode(bool p_enable); bool is_using_bbcode() const; - void set_bbcode(const String &p_bbcode); - String get_bbcode() const; - - void set_text(const String &p_string); + void set_text(const String &p_bbcode); + String get_text() const; void set_text_direction(TextDirection p_text_direction); TextDirection get_text_direction() const; |