diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml
index d75d3043e02..b982808ff0e 100644
--- a/doc/classes/RichTextLabel.xml
+++ b/doc/classes/RichTextLabel.xml
@@ -190,6 +190,12 @@
Returns the current selection first character index if a selection is active, [code]-1[/code] otherwise. Does not include BBCodes.
+
+
+
+ Returns the current selection vertical line offset if a selection is active, [code]-1.0[/code] otherwise.
+
+
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index be54ef7c94e..99a95910475 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -5449,25 +5449,8 @@ void RichTextLabel::append_text(const String &p_bbcode) {
}
void RichTextLabel::scroll_to_selection() {
- if (selection.active && selection.from_frame && selection.from_line >= 0 && selection.from_line < (int)selection.from_frame->lines.size()) {
- // Selected frame paragraph offset.
- float line_offset = selection.from_frame->lines[selection.from_line].offset.y;
-
- // Add wrapped line offset.
- for (int i = 0; i < selection.from_frame->lines[selection.from_line].text_buf->get_line_count(); i++) {
- Vector2i range = selection.from_frame->lines[selection.from_line].text_buf->get_line_range(i);
- if (range.x <= selection.from_char && range.y >= selection.from_char) {
- break;
- }
- line_offset += selection.from_frame->lines[selection.from_line].text_buf->get_line_ascent(i) + selection.from_frame->lines[selection.from_line].text_buf->get_line_descent(i) + theme_cache.line_separation;
- }
-
- // Add nested frame (e.g. table cell) offset.
- ItemFrame *it = selection.from_frame;
- while (it->parent_frame != nullptr) {
- line_offset += it->parent_frame->lines[it->line].offset.y;
- it = it->parent_frame;
- }
+ float line_offset = get_selection_line_offset();
+ if (line_offset != -1.0) {
vscroll->set_value(line_offset);
}
}
@@ -5978,6 +5961,32 @@ int RichTextLabel::get_selection_to() const {
return selection.to_frame->lines[selection.to_line].char_offset + selection.to_char - 1;
}
+float RichTextLabel::get_selection_line_offset() const {
+ if (selection.active && selection.from_frame && selection.from_line >= 0 && selection.from_line < (int)selection.from_frame->lines.size()) {
+ // Selected frame paragraph offset.
+ float line_offset = selection.from_frame->lines[selection.from_line].offset.y;
+
+ // Add wrapped line offset.
+ for (int i = 0; i < selection.from_frame->lines[selection.from_line].text_buf->get_line_count(); i++) {
+ Vector2i range = selection.from_frame->lines[selection.from_line].text_buf->get_line_range(i);
+ if (range.x <= selection.from_char && range.y >= selection.from_char) {
+ break;
+ }
+ line_offset += selection.from_frame->lines[selection.from_line].text_buf->get_line_ascent(i) + selection.from_frame->lines[selection.from_line].text_buf->get_line_descent(i) + theme_cache.line_separation;
+ }
+
+ // Add nested frame (e.g. table cell) offset.
+ ItemFrame *it = selection.from_frame;
+ while (it->parent_frame != nullptr) {
+ line_offset += it->parent_frame->lines[it->line].offset.y;
+ it = it->parent_frame;
+ }
+ return line_offset;
+ }
+
+ return -1.0;
+}
+
void RichTextLabel::set_text(const String &p_bbcode) {
// Allow clearing the tag stack.
if (!p_bbcode.is_empty() && text == p_bbcode) {
@@ -6412,6 +6421,7 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_selection_from"), &RichTextLabel::get_selection_from);
ClassDB::bind_method(D_METHOD("get_selection_to"), &RichTextLabel::get_selection_to);
+ ClassDB::bind_method(D_METHOD("get_selection_line_offset"), &RichTextLabel::get_selection_line_offset);
ClassDB::bind_method(D_METHOD("select_all"), &RichTextLabel::select_all);
ClassDB::bind_method(D_METHOD("get_selected_text"), &RichTextLabel::get_selected_text);
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index d9aac546ca0..12ae17ad4ad 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -787,6 +787,7 @@ public:
bool is_selection_enabled() const;
int get_selection_from() const;
int get_selection_to() const;
+ float get_selection_line_offset() const;
String get_selected_text() const;
void select_all();
void selection_copy();