Selaa lähdekoodia

Merge pull request #108466 from bruvzg/rtl_vis_rect

[RTL] Add method to get visible content bounding box.
Thaddeus Crews 3 kuukautta sitten
vanhempi
commit
c2ddb04713
3 muutettua tiedostoa jossa 58 lisäystä ja 0 poistoa
  1. 37 0
      doc/classes/RichTextLabel.xml
  2. 18 0
      scene/gui/rich_text_label.cpp
  3. 3 0
      scene/gui/rich_text_label.h

+ 37 - 0
doc/classes/RichTextLabel.xml

@@ -104,6 +104,7 @@
 			<return type="int" />
 			<description>
 				Returns the height of the content.
+				[b]Note:[/b] This method always returns the full content size, and is not affected by [member visible_ratio] and [member visible_characters]. To get the visible content size, use [method get_visible_content_rect].
 				[b]Note:[/b] If [member threaded] is enabled, this method returns a value for the loaded part of the document. Use [method is_finished] or [signal finished] to determine whether document is fully loaded.
 			</description>
 		</method>
@@ -111,6 +112,7 @@
 			<return type="int" />
 			<description>
 				Returns the width of the content.
+				[b]Note:[/b] This method always returns the full content size, and is not affected by [member visible_ratio] and [member visible_characters]. To get the visible content size, use [method get_visible_content_rect].
 				[b]Note:[/b] If [member threaded] is enabled, this method returns a value for the loaded part of the document. Use [method is_finished] or [signal finished] to determine whether document is fully loaded.
 			</description>
 		</method>
@@ -257,10 +259,44 @@
 				[b]Warning:[/b] This is a required internal node, removing and freeing it may cause a crash. If you wish to hide it or any of its children, use their [member CanvasItem.visible] property.
 			</description>
 		</method>
+		<method name="get_visible_content_rect" qualifiers="const">
+			<return type="Rect2i" />
+			<description>
+				Returns the bounding rectangle of the visible content.
+				[b]Note:[/b] This method returns a correct value only after the label has been drawn.
+				[codeblocks]
+				[gdscript]
+				extends RichTextLabel
+
+				@export var background_panel: Panel
+
+				func _ready():
+					await draw
+					background_panel.position = get_visible_content_rect().position
+					background_panel.size = get_visible_content_rect().size
+				[/gdscript]
+				[csharp]
+				public partial class TestLabel : RichTextLabel
+				{
+					[Export]
+					public Panel BackgroundPanel { get; set; }
+
+					public override async void _Ready()
+					{
+						await ToSignal(this, Control.SignalName.Draw);
+						BackgroundGPanel.Position = GetVisibleContentRect().Position;
+						BackgroundPanel.Size = GetVisibleContentRect().Size;
+					}
+				}
+				[/csharp]
+				[/codeblocks]
+			</description>
+		</method>
 		<method name="get_visible_line_count" qualifiers="const">
 			<return type="int" />
 			<description>
 				Returns the number of visible lines.
+				[b]Note:[/b] This method returns a correct value only after the label has been drawn.
 				[b]Note:[/b] If [member threaded] is enabled, this method returns a value for the loaded part of the document. Use [method is_finished] or [signal finished] to determine whether document is fully loaded.
 			</description>
 		</method>
@@ -268,6 +304,7 @@
 			<return type="int" />
 			<description>
 				Returns the number of visible paragraphs. A paragraph is considered visible if at least one of its lines is visible.
+				[b]Note:[/b] This method returns a correct value only after the label has been drawn.
 				[b]Note:[/b] If [member threaded] is enabled, this method returns a value for the loaded part of the document. Use [method is_finished] or [signal finished] to determine whether document is fully loaded.
 			</description>
 		</method>

+ 18 - 0
scene/gui/rich_text_label.cpp

@@ -58,6 +58,14 @@ RichTextLabel::ItemCustomFX::~ItemCustomFX() {
 	custom_effect.unref();
 }
 
+Rect2i _merge_or_copy_rect(const Rect2i &p_a, const Rect2i &p_b) {
+	if (!p_a.has_area()) {
+		return p_b;
+	} else {
+		return p_a.merge(p_b);
+	}
+}
+
 RichTextLabel::Item *RichTextLabel::_get_next_item(Item *p_item, bool p_free) const {
 	if (!p_item) {
 		return nullptr;
@@ -986,8 +994,10 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
 									Size2 pad_size = rect.size.min(img->image->get_size());
 									Vector2 pad_off = (rect.size - pad_size) / 2;
 									img->image->draw_rect(ci, Rect2(p_ofs + rect.position + off + pad_off, pad_size), false, img->color);
+									visible_rect = _merge_or_copy_rect(visible_rect, Rect2(p_ofs + rect.position + off + pad_off, pad_size));
 								} else {
 									img->image->draw_rect(ci, Rect2(p_ofs + rect.position + off, rect.size), false, img->color);
+									visible_rect = _merge_or_copy_rect(visible_rect, Rect2(p_ofs + rect.position + off, rect.size));
 								}
 							} break;
 							case ITEM_TABLE: {
@@ -1358,6 +1368,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
 						if (!skip) {
 							if (txt_visible) {
 								has_visible_chars = true;
+								visible_rect = _merge_or_copy_rect(visible_rect, Rect2i(fx_offset + char_off - Vector2i(0, l_ascent), Point2i(glyphs[i].advance, l_size.y)));
 								if (step == DRAW_STEP_TEXT) {
 									if (frid != RID()) {
 										TS->font_draw_glyph(frid, ci, glyphs[i].font_size, fx_offset + char_off, gl, font_color);
@@ -2501,6 +2512,7 @@ void RichTextLabel::_notification(int p_what) {
 
 			visible_paragraph_count = 0;
 			visible_line_count = 0;
+			visible_rect = Rect2i();
 
 			// New cache draw.
 			Point2 ofs = text_rect.get_position() + Vector2(0, vbegin + main->lines[from_line].offset.y - vofs);
@@ -7258,6 +7270,10 @@ int RichTextLabel::get_content_height() const {
 	return total_height;
 }
 
+Rect2i RichTextLabel::get_visible_content_rect() const {
+	return visible_rect;
+}
+
 int RichTextLabel::get_content_width() const {
 	const_cast<RichTextLabel *>(this)->_validate_line_caches();
 
@@ -7480,6 +7496,8 @@ void RichTextLabel::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_line_height", "line"), &RichTextLabel::get_line_height);
 	ClassDB::bind_method(D_METHOD("get_line_width", "line"), &RichTextLabel::get_line_width);
 
+	ClassDB::bind_method(D_METHOD("get_visible_content_rect"), &RichTextLabel::get_visible_content_rect);
+
 	ClassDB::bind_method(D_METHOD("get_line_offset", "line"), &RichTextLabel::get_line_offset);
 	ClassDB::bind_method(D_METHOD("get_paragraph_offset", "paragraph"), &RichTextLabel::get_paragraph_offset);
 

+ 3 - 0
scene/gui/rich_text_label.h

@@ -536,6 +536,7 @@ private:
 	int current_char_ofs = 0;
 	int visible_paragraph_count = 0;
 	int visible_line_count = 0;
+	Rect2i visible_rect;
 
 	int tab_size = 4;
 	bool underline_meta = true;
@@ -871,6 +872,8 @@ public:
 	int get_line_height(int p_line) const;
 	int get_line_width(int p_line) const;
 
+	Rect2i get_visible_content_rect() const;
+
 	void scroll_to_selection();
 
 	VScrollBar *get_v_scroll_bar() { return vscroll; }