diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml index c9b7c19a8d3..941d6dba644 100644 --- a/doc/classes/RichTextLabel.xml +++ b/doc/classes/RichTextLabel.xml @@ -442,6 +442,7 @@ + Adds a meta tag to the tag stack. Similar to the BBCode [code skip-lint][url=something]{text}[/url][/code], but supports non-[String] metadata types. If [member meta_underlined] is [code]true[/code], meta tags display an underline. This behavior can be customized with [param underline_mode]. diff --git a/misc/extension_api_validation/4.2-stable_4.3-stable.expected b/misc/extension_api_validation/4.2-stable_4.3-stable.expected index b6ad086792a..085af9f83db 100644 --- a/misc/extension_api_validation/4.2-stable_4.3-stable.expected +++ b/misc/extension_api_validation/4.2-stable_4.3-stable.expected @@ -207,7 +207,7 @@ Compatibility method registered. GH-89024 -------- -Validate extension JSON: Error: Field 'classes/RichTextLabel/methods/push_meta/arguments': size changed value in new API, from 1 to 2. +Validate extension JSON: Error: Field 'classes/RichTextLabel/methods/push_meta/arguments': size changed value in new API, from 1 to 3. Added optional argument. Compatibility method registered. diff --git a/misc/extension_api_validation/4.3-stable.expected b/misc/extension_api_validation/4.3-stable.expected index 4cbeebc3b46..c2b54b1e689 100644 --- a/misc/extension_api_validation/4.3-stable.expected +++ b/misc/extension_api_validation/4.3-stable.expected @@ -198,3 +198,10 @@ Validate extension JSON: JSON file: Field was added in a way that breaks compati Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/FileAccess/methods/store_var': return_value Added return values. Compatibility method registered. + + +GH-99481 +-------- +Validate extension JSON: Error: Field 'classes/RichTextLabel/methods/push_meta/arguments': size changed value in new API, from 2 to 3. + +Optional argument added to set tooltip. Compatibility method registered. diff --git a/scene/gui/rich_text_label.compat.inc b/scene/gui/rich_text_label.compat.inc index 97739c4b790..7812ab05bc0 100644 --- a/scene/gui/rich_text_label.compat.inc +++ b/scene/gui/rich_text_label.compat.inc @@ -30,8 +30,12 @@ #ifndef DISABLE_DEPRECATED +void RichTextLabel::_push_meta_bind_compat_99481(const Variant &p_meta, MetaUnderline p_underline_mode) { + push_meta(p_meta, p_underline_mode, String()); +} + void RichTextLabel::_push_meta_bind_compat_89024(const Variant &p_meta) { - push_meta(p_meta, RichTextLabel::MetaUnderline::META_UNDERLINE_ALWAYS); + push_meta(p_meta, RichTextLabel::MetaUnderline::META_UNDERLINE_ALWAYS, String()); } void RichTextLabel::_add_image_bind_compat_80410(const Ref &p_image, const int p_width, const int p_height, const Color &p_color, InlineAlignment p_alignment, const Rect2 &p_region) { @@ -43,6 +47,7 @@ bool RichTextLabel::_remove_paragraph_bind_compat_91098(int p_paragraph) { } void RichTextLabel::_bind_compatibility_methods() { + ClassDB::bind_compatibility_method(D_METHOD("push_meta", "data", "underline_mode"), &RichTextLabel::_push_meta_bind_compat_99481, DEFVAL(META_UNDERLINE_ALWAYS)); ClassDB::bind_compatibility_method(D_METHOD("push_meta", "data"), &RichTextLabel::_push_meta_bind_compat_89024); ClassDB::bind_compatibility_method(D_METHOD("add_image", "image", "width", "height", "color", "inline_align", "region"), &RichTextLabel::_add_image_bind_compat_80410, DEFVAL(0), DEFVAL(0), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(INLINE_ALIGNMENT_CENTER), DEFVAL(Rect2())); ClassDB::bind_compatibility_method(D_METHOD("remove_paragraph", "paragraph"), &RichTextLabel::_remove_paragraph_bind_compat_91098); diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 8a856efce34..61ce602b8e2 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -2311,10 +2311,13 @@ String RichTextLabel::get_tooltip(const Point2 &p_pos) const { String description; if (c_item && !outside) { + ItemMeta *meta = nullptr; if (const_cast(this)->_find_hint(c_item, &description)) { return description; } else if (c_item->type == ITEM_IMAGE && !static_cast(c_item)->tooltip.is_empty()) { return static_cast(c_item)->tooltip; + } else if (const_cast(this)->_find_meta(c_item, nullptr, &meta) && meta && !meta->tooltip.is_empty()) { + return meta->tooltip; } } @@ -3778,7 +3781,7 @@ void RichTextLabel::push_list(int p_level, ListType p_list, bool p_capitalize, c _add_item(item, true, true); } -void RichTextLabel::push_meta(const Variant &p_meta, MetaUnderline p_underline_mode) { +void RichTextLabel::push_meta(const Variant &p_meta, MetaUnderline p_underline_mode, const String &p_tooltip) { _stop_thread(); MutexLock data_lock(data_mutex); @@ -3788,6 +3791,7 @@ void RichTextLabel::push_meta(const Variant &p_meta, MetaUnderline p_underline_m item->rid = items.make_rid(item); item->meta = p_meta; item->underline = p_underline_mode; + item->tooltip = p_tooltip; _add_item(item, true); } @@ -4787,6 +4791,34 @@ void RichTextLabel::append_text(const String &p_bbcode) { pos = brk_end + 1; tag_stack.push_front(tag); + } else if (tag.begins_with("url ")) { + String url; + MetaUnderline underline = META_UNDERLINE_ALWAYS; + String tooltip; + + OptionMap::Iterator underline_option = bbcode_options.find("underline"); + if (underline_option) { + if (underline_option->value == "never") { + underline = META_UNDERLINE_NEVER; + } else if (underline_option->value == "always") { + underline = META_UNDERLINE_ALWAYS; + } else if (underline_option->value == "hover") { + underline = META_UNDERLINE_ON_HOVER; + } + } + OptionMap::Iterator tooltip_option = bbcode_options.find("tooltip"); + if (tooltip_option) { + tooltip = tooltip_option->value; + } + OptionMap::Iterator href_option = bbcode_options.find("href"); + if (href_option) { + url = href_option->value; + } + + push_meta(url, underline, tooltip); + + pos = brk_end + 1; + tag_stack.push_front("url"); } else if (tag.begins_with("url=")) { String url = _get_tag_value(tag).unquote(); push_meta(url, META_UNDERLINE_ALWAYS); @@ -6267,7 +6299,7 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("push_paragraph", "alignment", "base_direction", "language", "st_parser", "justification_flags", "tab_stops"), &RichTextLabel::push_paragraph, DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(""), DEFVAL(TextServer::STRUCTURED_TEXT_DEFAULT), DEFVAL(TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_SKIP_LAST_LINE | TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE), DEFVAL(PackedFloat32Array())); ClassDB::bind_method(D_METHOD("push_indent", "level"), &RichTextLabel::push_indent); ClassDB::bind_method(D_METHOD("push_list", "level", "type", "capitalize", "bullet"), &RichTextLabel::push_list, DEFVAL(String::utf8("•"))); - ClassDB::bind_method(D_METHOD("push_meta", "data", "underline_mode"), &RichTextLabel::push_meta, DEFVAL(META_UNDERLINE_ALWAYS)); + ClassDB::bind_method(D_METHOD("push_meta", "data", "underline_mode", "tooltip"), &RichTextLabel::push_meta, DEFVAL(META_UNDERLINE_ALWAYS), DEFVAL(String())); ClassDB::bind_method(D_METHOD("push_hint", "description"), &RichTextLabel::push_hint); ClassDB::bind_method(D_METHOD("push_language", "language"), &RichTextLabel::push_language); ClassDB::bind_method(D_METHOD("push_underline"), &RichTextLabel::push_underline); diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index 2e181f18876..37edf3418fb 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -132,6 +132,7 @@ protected: static void _bind_methods(); #ifndef DISABLE_DEPRECATED + void _push_meta_bind_compat_99481(const Variant &p_meta, MetaUnderline p_underline_mode); void _push_meta_bind_compat_89024(const Variant &p_meta); void _add_image_bind_compat_80410(const Ref &p_image, const int p_width, const int p_height, const Color &p_color, InlineAlignment p_alignment, const Rect2 &p_region); bool _remove_paragraph_bind_compat_91098(int p_paragraph); @@ -291,6 +292,7 @@ private: struct ItemMeta : public Item { Variant meta; MetaUnderline underline = META_UNDERLINE_ALWAYS; + String tooltip; ItemMeta() { type = ITEM_META; } }; @@ -702,7 +704,7 @@ public: void push_paragraph(HorizontalAlignment p_alignment, Control::TextDirection p_direction = Control::TEXT_DIRECTION_INHERITED, const String &p_language = "", TextServer::StructuredTextParser p_st_parser = TextServer::STRUCTURED_TEXT_DEFAULT, BitField p_jst_flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_SKIP_LAST_LINE | TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE, const PackedFloat32Array &p_tab_stops = PackedFloat32Array()); void push_indent(int p_level); void push_list(int p_level, ListType p_list, bool p_capitalize, const String &p_bullet = String::utf8("•")); - void push_meta(const Variant &p_meta, MetaUnderline p_underline_mode = META_UNDERLINE_ALWAYS); + void push_meta(const Variant &p_meta, MetaUnderline p_underline_mode = META_UNDERLINE_ALWAYS, const String &p_tooltip = String()); void push_hint(const String &p_string); void push_table(int p_columns, InlineAlignment p_alignment = INLINE_ALIGNMENT_TOP, int p_align_to_row = -1); void push_fade(int p_start_index, int p_length);