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);