@@ -1223,8 +1223,25 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
12231223 for (int i = 0 ; i < gl_size; i++) {
12241224 bool selected = selection.active && (sel_start != -1 ) && (glyphs[i].start >= sel_start) && (glyphs[i].end <= sel_end);
12251225 Item *it = _get_item_at_pos (it_from, it_to, glyphs[i].start );
1226+ bool has_ul = _find_underline (it);
1227+ if (!has_ul && underline_meta) {
1228+ ItemMeta *meta = nullptr ;
1229+ if (_find_meta (it, nullptr , &meta) && meta) {
1230+ switch (meta->underline ) {
1231+ case META_UNDERLINE_ALWAYS: {
1232+ has_ul = true ;
1233+ } break ;
1234+ case META_UNDERLINE_NEVER: {
1235+ has_ul = false ;
1236+ } break ;
1237+ case META_UNDERLINE_ON_HOVER: {
1238+ has_ul = (meta == meta_hovering);
1239+ } break ;
1240+ }
1241+ }
1242+ }
12261243 Color font_color = _find_color (it, p_base_color);
1227- if (_find_underline (it) || ( _find_meta (it, nullptr ) && underline_meta) ) {
1244+ if (has_ul ) {
12281245 if (ul_started && font_color != ul_color_prev) {
12291246 float y_off = TS->shaped_text_get_underline_position (rid);
12301247 float underline_width = MAX (1.0 , TS->shaped_text_get_underline_thickness (rid) * theme_cache.base_scale );
@@ -2242,6 +2259,7 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) {
22422259
22432260 Variant meta;
22442261 ItemMeta *item_meta;
2262+ ItemMeta *prev_meta = meta_hovering;
22452263 if (c_item && !outside && _find_meta (c_item, &meta, &item_meta)) {
22462264 if (meta_hovering != item_meta) {
22472265 if (meta_hovering) {
@@ -2250,11 +2268,17 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) {
22502268 meta_hovering = item_meta;
22512269 current_meta = meta;
22522270 emit_signal (SNAME (" meta_hover_started" ), meta);
2271+ if ((item_meta && item_meta->underline == META_UNDERLINE_ON_HOVER) || (prev_meta && prev_meta->underline == META_UNDERLINE_ON_HOVER)) {
2272+ queue_redraw ();
2273+ }
22532274 }
22542275 } else if (meta_hovering) {
22552276 meta_hovering = nullptr ;
22562277 emit_signal (SNAME (" meta_hover_ended" ), current_meta);
22572278 current_meta = false ;
2279+ if (prev_meta->underline == META_UNDERLINE_ON_HOVER) {
2280+ queue_redraw ();
2281+ }
22582282 }
22592283 }
22602284}
@@ -3650,7 +3674,7 @@ void RichTextLabel::push_list(int p_level, ListType p_list, bool p_capitalize, c
36503674 _add_item (item, true , true );
36513675}
36523676
3653- void RichTextLabel::push_meta (const Variant &p_meta) {
3677+ void RichTextLabel::push_meta (const Variant &p_meta, MetaUnderline p_underline_mode ) {
36543678 _stop_thread ();
36553679 MutexLock data_lock (data_mutex);
36563680
@@ -3659,6 +3683,7 @@ void RichTextLabel::push_meta(const Variant &p_meta) {
36593683 item->owner = get_instance_id ();
36603684 item->rid = items.make_rid (item);
36613685 item->meta = p_meta;
3686+ item->underline = p_underline_mode;
36623687 _add_item (item, true );
36633688}
36643689
@@ -4573,14 +4598,14 @@ void RichTextLabel::append_text(const String &p_bbcode) {
45734598 end = p_bbcode.length ();
45744599 }
45754600 String url = p_bbcode.substr (brk_end + 1 , end - brk_end - 1 ).unquote ();
4576- push_meta (url);
4601+ push_meta (url, META_UNDERLINE_ALWAYS );
45774602
45784603 pos = brk_end + 1 ;
45794604 tag_stack.push_front (tag);
45804605
45814606 } else if (tag.begins_with (" url=" )) {
45824607 String url = tag.substr (4 , tag.length ()).unquote ();
4583- push_meta (url);
4608+ push_meta (url, META_UNDERLINE_ALWAYS );
45844609 pos = brk_end + 1 ;
45854610 tag_stack.push_front (" url" );
45864611 } else if (tag.begins_with (" hint=" )) {
@@ -5891,7 +5916,7 @@ void RichTextLabel::_bind_methods() {
58915916 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 ()));
58925917 ClassDB::bind_method (D_METHOD (" push_indent" , " level" ), &RichTextLabel::push_indent);
58935918 ClassDB::bind_method (D_METHOD (" push_list" , " level" , " type" , " capitalize" , " bullet" ), &RichTextLabel::push_list, DEFVAL (String::utf8 (" •" )));
5894- ClassDB::bind_method (D_METHOD (" push_meta" , " data" ), &RichTextLabel::push_meta);
5919+ ClassDB::bind_method (D_METHOD (" push_meta" , " data" , " underline_mode " ), &RichTextLabel::push_meta, DEFVAL (META_UNDERLINE_ALWAYS) );
58955920 ClassDB::bind_method (D_METHOD (" push_hint" , " description" ), &RichTextLabel::push_hint);
58965921 ClassDB::bind_method (D_METHOD (" push_language" , " language" ), &RichTextLabel::push_language);
58975922 ClassDB::bind_method (D_METHOD (" push_underline" ), &RichTextLabel::push_underline);
@@ -6081,6 +6106,10 @@ void RichTextLabel::_bind_methods() {
60816106 BIND_ENUM_CONSTANT (MENU_SELECT_ALL);
60826107 BIND_ENUM_CONSTANT (MENU_MAX);
60836108
6109+ BIND_ENUM_CONSTANT (META_UNDERLINE_NEVER);
6110+ BIND_ENUM_CONSTANT (META_UNDERLINE_ALWAYS);
6111+ BIND_ENUM_CONSTANT (META_UNDERLINE_ON_HOVER);
6112+
60846113 BIND_BITFIELD_FLAG (UPDATE_TEXTURE);
60856114 BIND_BITFIELD_FLAG (UPDATE_SIZE);
60866115 BIND_BITFIELD_FLAG (UPDATE_COLOR);
0 commit comments