From 6d17fc1f736c648234f5f83564dfd3c1653c2d5c Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Thu, 25 Jan 2024 17:51:18 +0200 Subject: [PATCH] [RTL] Connect image update signals. --- scene/gui/rich_text_label.cpp | 123 +++++++++++++++++++++++++++------- scene/gui/rich_text_label.h | 22 +++++- 2 files changed, 119 insertions(+), 26 deletions(-) diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index fd481e10675..b6dd953d505 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -239,7 +239,8 @@ void RichTextLabel::_update_line_font(ItemFrame *p_frame, int p_line, const Ref< RID t = l.text_buf->get_rid(); int spans = TS->shaped_get_span_count(t); for (int i = 0; i < spans; i++) { - ItemText *it = reinterpret_cast((uint64_t)TS->shaped_get_span_meta(t, i)); + Item *it_span = items.get_or_null(TS->shaped_get_span_meta(t, i)); + ItemText *it = reinterpret_cast(it_span); if (it) { Ref font = p_base_font; int font_size = p_base_font_size; @@ -307,7 +308,7 @@ float RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Refsize; if (img->size_in_percent) { img_size = _get_image_size(img->image, p_width * img->rq_size.width / 100.f, p_width * img->rq_size.height / 100.f, img->region); - l.text_buf->resize_object((uint64_t)it, img_size, img->inline_align); + l.text_buf->resize_object(it->rid, img_size, img->inline_align); } } break; case ITEM_TABLE: { @@ -455,9 +456,9 @@ float RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Refalign_to_row < 0) ? table->rows_baseline.size() - 1 : table->align_to_row; if (table->rows_baseline.size() != 0 && row_idx < (int)table->rows_baseline.size() - 1) { - l.text_buf->resize_object((uint64_t)it, Size2(table->total_width, table->total_height), table->inline_align, Math::round(table->rows_baseline[row_idx])); + l.text_buf->resize_object(it->rid, Size2(table->total_width, table->total_height), table->inline_align, Math::round(table->rows_baseline[row_idx])); } else { - l.text_buf->resize_object((uint64_t)it, Size2(table->total_width, table->total_height), table->inline_align); + l.text_buf->resize_object(it->rid, Size2(table->total_width, table->total_height), table->inline_align); } } break; default: @@ -578,7 +579,7 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref } remaining_characters -= tx.length(); - l.text_buf->add_string(tx, font, font_size, lang, (uint64_t)it); + l.text_buf->add_string(tx, font, font_size, lang, it->rid); txt += tx; l.char_count += tx.length(); } break; @@ -588,7 +589,7 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref if (img->size_in_percent) { img_size = _get_image_size(img->image, p_width * img->rq_size.width / 100.f, p_width * img->rq_size.height / 100.f, img->region); } - l.text_buf->add_object((uint64_t)it, img_size, img->inline_align, 1); + l.text_buf->add_object(it->rid, img_size, img->inline_align, 1); txt += String::chr(0xfffc); l.char_count++; remaining_characters--; @@ -753,9 +754,9 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref } int row_idx = (table->align_to_row < 0) ? table->rows_baseline.size() - 1 : table->align_to_row; if (table->rows_baseline.size() != 0 && row_idx < (int)table->rows_baseline.size() - 1) { - l.text_buf->add_object((uint64_t)it, Size2(table->total_width, table->total_height), table->inline_align, t_char_count, Math::round(table->rows_baseline[row_idx])); + l.text_buf->add_object(it->rid, Size2(table->total_width, table->total_height), table->inline_align, t_char_count, Math::round(table->rows_baseline[row_idx])); } else { - l.text_buf->add_object((uint64_t)it, Size2(table->total_width, table->total_height), table->inline_align, t_char_count); + l.text_buf->add_object(it->rid, Size2(table->total_width, table->total_height), table->inline_align, t_char_count); } txt += String::chr(0xfffc).repeat(t_char_count); } break; @@ -932,7 +933,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o // Draw inlined objects. Array objects = TS->shaped_text_get_objects(rid); for (int i = 0; i < objects.size(); i++) { - Item *it = reinterpret_cast((uint64_t)objects[i]); + Item *it = items.get_or_null(objects[i]); if (it != nullptr) { Rect2 rect = TS->shaped_text_get_object_rect(rid, objects[i]); //draw_rect(rect, Color(1,0,0), false, 2); //DEBUG_RECTS @@ -1601,7 +1602,7 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V Array objects = TS->shaped_text_get_objects(rid); for (int i = 0; i < objects.size(); i++) { - Item *it = reinterpret_cast((uint64_t)objects[i]); + Item *it = items.get_or_null(objects[i]); if (it != nullptr) { Rect2 rect = TS->shaped_text_get_object_rect(rid, objects[i]); rect.position += p_ofs + off; @@ -3054,6 +3055,19 @@ void RichTextLabel::_invalidate_current_line(ItemFrame *p_frame) { } } +void RichTextLabel::_texture_changed(RID p_item) { + Item *it = items.get_or_null(p_item); + if (it && it->type == ITEM_IMAGE) { + ItemImage *img = reinterpret_cast(it); + Size2 new_size = _get_image_size(img->image, img->rq_size.width, img->rq_size.height, img->region); + if (img->size != new_size) { + main->first_invalid_line.store(0); + img->size = new_size; + } + } + queue_redraw(); +} + void RichTextLabel::add_text(const String &p_text) { _stop_thread(); MutexLock data_lock(data_mutex); @@ -3090,6 +3104,8 @@ void RichTextLabel::add_text(const String &p_text) { } else { //append item condition ItemText *item = memnew(ItemText); + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->text = line; _add_item(item, false); } @@ -3097,6 +3113,8 @@ void RichTextLabel::add_text(const String &p_text) { if (eol) { ItemNewline *item = memnew(ItemNewline); + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->line = current_frame->lines.size(); _add_item(item, false); current_frame->lines.resize(current_frame->lines.size() + 1); @@ -3174,6 +3192,7 @@ void RichTextLabel::_remove_item(Item *p_item, const int p_line) { // Then remove the provided item itself. p_item->parent->subitems.erase(p_item); } + items.free(p_item->rid); memdelete(p_item); } @@ -3231,6 +3250,8 @@ void RichTextLabel::add_image(const Ref &p_image, int p_width, int p_ ERR_FAIL_COND(p_height < 0); ItemImage *item = memnew(ItemImage); + item->owner = get_instance_id(); + item->rid = items.make_rid(item); if (p_region.has_area()) { Ref atlas_tex = memnew(AtlasTexture); @@ -3250,6 +3271,8 @@ void RichTextLabel::add_image(const Ref &p_image, int p_width, int p_ item->key = p_key; item->tooltip = p_tooltip; + item->image->connect_changed(callable_mp(this, &RichTextLabel::_texture_changed).bind(item->rid), CONNECT_REFERENCE_COUNTED); + _add_item(item, false); } @@ -3278,6 +3301,9 @@ void RichTextLabel::update_image(const Variant &p_key, BitField item->region = p_region; } if (p_mask & UPDATE_TEXTURE) { + if (item->image.is_valid()) { + item->image->disconnect_changed(callable_mp(this, &RichTextLabel::_texture_changed)); + } if (item->region.has_area()) { Ref atlas_tex = memnew(AtlasTexture); atlas_tex->set_atlas(p_image); @@ -3286,6 +3312,7 @@ void RichTextLabel::update_image(const Variant &p_key, BitField } else { item->image = p_image; } + item->image->connect_changed(callable_mp(this, &RichTextLabel::_texture_changed).bind(item->rid), CONNECT_REFERENCE_COUNTED); } if (p_mask & UPDATE_COLOR) { item->color = p_color; @@ -3345,6 +3372,8 @@ void RichTextLabel::add_newline() { return; } ItemNewline *item = memnew(ItemNewline); + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->line = current_frame->lines.size(); _add_item(item, false); current_frame->lines.resize(current_frame->lines.size() + 1); @@ -3413,7 +3442,8 @@ void RichTextLabel::push_dropcap(const String &p_string, const Ref &p_font ERR_FAIL_COND(p_size <= 0); ItemDropcap *item = memnew(ItemDropcap); - + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->text = p_string; item->font = p_font; item->font_size = p_size; @@ -3430,7 +3460,8 @@ void RichTextLabel::_push_def_font_var(DefaultFont p_def_font, const Ref & ERR_FAIL_COND(current->type == ITEM_TABLE); ItemFont *item = memnew(ItemFont); - + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->def_font = p_def_font; item->variation = true; item->font = p_font; @@ -3445,7 +3476,8 @@ void RichTextLabel::_push_def_font(DefaultFont p_def_font) { ERR_FAIL_COND(current->type == ITEM_TABLE); ItemFont *item = memnew(ItemFont); - + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->def_font = p_def_font; item->def_size = true; _add_item(item, true); @@ -3458,7 +3490,8 @@ void RichTextLabel::push_font(const Ref &p_font, int p_size) { ERR_FAIL_COND(current->type == ITEM_TABLE); ERR_FAIL_COND(p_font.is_null()); ItemFont *item = memnew(ItemFont); - + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->font = p_font; item->font_size = p_size; _add_item(item, true); @@ -3502,7 +3535,8 @@ void RichTextLabel::push_font_size(int p_font_size) { ERR_FAIL_COND(current->type == ITEM_TABLE); ItemFontSize *item = memnew(ItemFontSize); - + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->font_size = p_font_size; _add_item(item, true); } @@ -3513,7 +3547,8 @@ void RichTextLabel::push_outline_size(int p_ol_size) { ERR_FAIL_COND(current->type == ITEM_TABLE); ItemOutlineSize *item = memnew(ItemOutlineSize); - + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->outline_size = p_ol_size; _add_item(item, true); } @@ -3524,7 +3559,8 @@ void RichTextLabel::push_color(const Color &p_color) { ERR_FAIL_COND(current->type == ITEM_TABLE); ItemColor *item = memnew(ItemColor); - + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->color = p_color; _add_item(item, true); } @@ -3535,7 +3571,8 @@ void RichTextLabel::push_outline_color(const Color &p_color) { ERR_FAIL_COND(current->type == ITEM_TABLE); ItemOutlineColor *item = memnew(ItemOutlineColor); - + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->color = p_color; _add_item(item, true); } @@ -3546,6 +3583,8 @@ void RichTextLabel::push_underline() { ERR_FAIL_COND(current->type == ITEM_TABLE); ItemUnderline *item = memnew(ItemUnderline); + item->owner = get_instance_id(); + item->rid = items.make_rid(item); _add_item(item, true); } @@ -3556,6 +3595,8 @@ void RichTextLabel::push_strikethrough() { ERR_FAIL_COND(current->type == ITEM_TABLE); ItemStrikethrough *item = memnew(ItemStrikethrough); + item->owner = get_instance_id(); + item->rid = items.make_rid(item); _add_item(item, true); } @@ -3567,6 +3608,8 @@ void RichTextLabel::push_paragraph(HorizontalAlignment p_alignment, Control::Tex ERR_FAIL_COND(current->type == ITEM_TABLE); ItemParagraph *item = memnew(ItemParagraph); + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->alignment = p_alignment; item->direction = p_direction; item->language = p_language; @@ -3584,6 +3627,8 @@ void RichTextLabel::push_indent(int p_level) { ERR_FAIL_COND(p_level < 0); ItemIndent *item = memnew(ItemIndent); + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->level = p_level; _add_item(item, true, true); } @@ -3596,7 +3641,8 @@ void RichTextLabel::push_list(int p_level, ListType p_list, bool p_capitalize, c ERR_FAIL_COND(p_level < 0); ItemList *item = memnew(ItemList); - + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->list_type = p_list; item->level = p_level; item->capitalize = p_capitalize; @@ -3610,7 +3656,8 @@ void RichTextLabel::push_meta(const Variant &p_meta) { ERR_FAIL_COND(current->type == ITEM_TABLE); ItemMeta *item = memnew(ItemMeta); - + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->meta = p_meta; _add_item(item, true); } @@ -3621,7 +3668,8 @@ void RichTextLabel::push_language(const String &p_language) { ERR_FAIL_COND(current->type == ITEM_TABLE); ItemLanguage *item = memnew(ItemLanguage); - + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->language = p_language; _add_item(item, true); } @@ -3632,7 +3680,8 @@ void RichTextLabel::push_hint(const String &p_string) { ERR_FAIL_COND(current->type == ITEM_TABLE); ItemHint *item = memnew(ItemHint); - + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->description = p_string; _add_item(item, true); } @@ -3644,7 +3693,8 @@ void RichTextLabel::push_table(int p_columns, InlineAlignment p_alignment, int p ERR_FAIL_COND(current->type == ITEM_TABLE); ERR_FAIL_COND(p_columns < 1); ItemTable *item = memnew(ItemTable); - + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->columns.resize(p_columns); item->total_width = 0; item->inline_align = p_alignment; @@ -3662,6 +3712,8 @@ void RichTextLabel::push_fade(int p_start_index, int p_length) { ERR_FAIL_COND(current->type == ITEM_TABLE); ItemFade *item = memnew(ItemFade); + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->starting_index = p_start_index; item->length = p_length; _add_item(item, true); @@ -3673,6 +3725,8 @@ void RichTextLabel::push_shake(int p_strength = 10, float p_rate = 24.0f, bool p ERR_FAIL_COND(current->type == ITEM_TABLE); ItemShake *item = memnew(ItemShake); + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->strength = p_strength; item->rate = p_rate; item->connected = p_connected; @@ -3685,6 +3739,8 @@ void RichTextLabel::push_wave(float p_frequency = 1.0f, float p_amplitude = 10.0 ERR_FAIL_COND(current->type == ITEM_TABLE); ItemWave *item = memnew(ItemWave); + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->frequency = p_frequency; item->amplitude = p_amplitude; item->connected = p_connected; @@ -3697,6 +3753,8 @@ void RichTextLabel::push_tornado(float p_frequency = 1.0f, float p_radius = 10.0 ERR_FAIL_COND(current->type == ITEM_TABLE); ItemTornado *item = memnew(ItemTornado); + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->frequency = p_frequency; item->radius = p_radius; item->connected = p_connected; @@ -3709,6 +3767,8 @@ void RichTextLabel::push_rainbow(float p_saturation, float p_value, float p_freq ERR_FAIL_COND(current->type == ITEM_TABLE); ItemRainbow *item = memnew(ItemRainbow); + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->frequency = p_frequency; item->saturation = p_saturation; item->value = p_value; @@ -3720,6 +3780,8 @@ void RichTextLabel::push_pulse(const Color &p_color, float p_frequency, float p_ MutexLock data_lock(data_mutex); ItemPulse *item = memnew(ItemPulse); + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->color = p_color; item->frequency = p_frequency; item->ease = p_ease; @@ -3732,7 +3794,8 @@ void RichTextLabel::push_bgcolor(const Color &p_color) { ERR_FAIL_COND(current->type == ITEM_TABLE); ItemBGColor *item = memnew(ItemBGColor); - + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->color = p_color; _add_item(item, true); } @@ -3743,7 +3806,8 @@ void RichTextLabel::push_fgcolor(const Color &p_color) { ERR_FAIL_COND(current->type == ITEM_TABLE); ItemFGColor *item = memnew(ItemFGColor); - + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->color = p_color; _add_item(item, true); } @@ -3754,6 +3818,8 @@ void RichTextLabel::push_customfx(Ref p_custom_effect, Dictionar ERR_FAIL_COND(current->type == ITEM_TABLE); ItemCustomFX *item = memnew(ItemCustomFX); + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->custom_effect = p_custom_effect; item->char_fx_transform->environment = p_environment; _add_item(item, true); @@ -3767,6 +3833,8 @@ void RichTextLabel::push_context() { ERR_FAIL_COND(current->type == ITEM_TABLE); ItemContext *item = memnew(ItemContext); + item->owner = get_instance_id(); + item->rid = items.make_rid(item); _add_item(item, true); } @@ -3835,6 +3903,8 @@ void RichTextLabel::push_cell() { ERR_FAIL_COND(current->type != ITEM_TABLE); ItemFrame *item = memnew(ItemFrame); + item->owner = get_instance_id(); + item->rid = items.make_rid(item); item->parent_frame = current_frame; _add_item(item, true); current_frame = item; @@ -6388,6 +6458,8 @@ Dictionary RichTextLabel::parse_expressions_for_values(Vector p_expressi RichTextLabel::RichTextLabel(const String &p_text) { main = memnew(ItemFrame); + main->owner = get_instance_id(); + main->rid = items.make_rid(main); main->index = 0; current = main; main->lines.resize(1); @@ -6418,5 +6490,6 @@ RichTextLabel::RichTextLabel(const String &p_text) { RichTextLabel::~RichTextLabel() { _stop_thread(); + items.free(main->rid); memdelete(main); } diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index 5c8585565d7..0070027a7e0 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -32,6 +32,7 @@ #define RICH_TEXT_LABEL_H #include "core/object/worker_thread_pool.h" +#include "core/templates/rid_owner.h" #include "scene/gui/popup_menu.h" #include "scene/gui/scroll_bar.h" #include "scene/resources/text_paragraph.h" @@ -149,11 +150,18 @@ private: ItemType type = ITEM_FRAME; List subitems; List::Element *E = nullptr; + ObjectID owner; int line = 0; + RID rid; void _clear_children() { + RichTextLabel *owner_rtl = Object::cast_to(ObjectDB::get_instance(owner)); while (subitems.size()) { - memdelete(subitems.front()->get()); + Item *subitem = subitems.front()->get(); + if (subitem && subitem->rid.is_valid() && owner_rtl) { + owner_rtl->items.free(subitem->rid); + } + memdelete(subitem); subitems.pop_front(); } } @@ -214,6 +222,14 @@ private: Variant key; String tooltip; ItemImage() { type = ITEM_IMAGE; } + ~ItemImage() { + if (image.is_valid()) { + RichTextLabel *owner_rtl = Object::cast_to(ObjectDB::get_instance(owner)); + if (owner_rtl) { + image->disconnect_changed(callable_mp(owner_rtl, &RichTextLabel::_texture_changed)); + } + } + } }; struct ItemFont : public Item { @@ -463,6 +479,10 @@ private: void _add_item(Item *p_item, bool p_enter = false, bool p_ensure_newline = false); void _remove_item(Item *p_item, const int p_line); + void _texture_changed(RID p_item); + + RID_PtrOwner items; + String language; TextDirection text_direction = TEXT_DIRECTION_AUTO; TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;