Forráskód Böngészése

Merge pull request #98036 from bruvzg/para_btn_spacing

[TextParagraph/Button] Add support for line spacing.
Thaddeus Crews 8 hónapja
szülő
commit
6bbc1cb6a9

+ 3 - 0
doc/classes/Button.xml

@@ -127,6 +127,9 @@
 		<theme_item name="icon_max_width" data_type="constant" type="int" default="0">
 			The maximum allowed width of the [Button]'s icon. This limit is applied on top of the default size of the icon, or its expanded size if [member expand_icon] is [code]true[/code]. The height is adjusted according to the icon's ratio. If the button has additional icons (e.g. [CheckBox]), they will also be limited.
 		</theme_item>
+		<theme_item name="line_spacing" data_type="constant" type="int" default="0">
+			Additional vertical spacing between lines (in pixels), spacing is added to line descent. This value can be negative.
+		</theme_item>
 		<theme_item name="outline_size" data_type="constant" type="int" default="0">
 			The size of the text outline.
 			[b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended.

+ 1 - 1
doc/classes/Label.xml

@@ -122,7 +122,7 @@
 			[Color] of the text's shadow effect.
 		</theme_item>
 		<theme_item name="line_spacing" data_type="constant" type="int" default="3">
-			Vertical space between lines in multiline [Label].
+			Additional vertical spacing between lines (in pixels), spacing is added to line descent. This value can be negative.
 		</theme_item>
 		<theme_item name="outline_size" data_type="constant" type="int" default="0">
 			Text outline size.

+ 1 - 1
doc/classes/Label3D.xml

@@ -79,7 +79,7 @@
 			Language code used for line-breaking and text shaping algorithms, if left empty current locale is used instead.
 		</member>
 		<member name="line_spacing" type="float" setter="set_line_spacing" getter="get_line_spacing" default="0.0">
-			Vertical space between lines in multiline [Label3D].
+			Additional vertical spacing between lines (in pixels), spacing is added to line descent. This value can be negative.
 		</member>
 		<member name="modulate" type="Color" setter="set_modulate" getter="get_modulate" default="Color(1, 1, 1, 1)" keywords="color, colour">
 			Text [Color] of the [Label3D].

+ 1 - 1
doc/classes/LabelSettings.xml

@@ -19,7 +19,7 @@
 			Size of the text.
 		</member>
 		<member name="line_spacing" type="float" setter="set_line_spacing" getter="get_line_spacing" default="3.0">
-			Vertical space between lines when the text is multiline.
+			Additional vertical spacing between lines (in pixels), spacing is added to line descent. This value can be negative.
 		</member>
 		<member name="outline_color" type="Color" setter="set_outline_color" getter="get_outline_color" default="Color(1, 1, 1, 1)">
 			The color of the outline.

+ 1 - 1
doc/classes/RichTextLabel.xml

@@ -810,7 +810,7 @@
 			The default background color for odd rows.
 		</theme_item>
 		<theme_item name="line_separation" data_type="constant" type="int" default="0">
-			The vertical space between lines.
+			Additional vertical spacing between lines (in pixels), spacing is added to line descent. This value can be negative.
 		</theme_item>
 		<theme_item name="outline_size" data_type="constant" type="int" default="0">
 			The size of the text outline.

+ 1 - 1
doc/classes/TextEdit.xml

@@ -1624,7 +1624,7 @@
 			The caret's width in pixels. Greater values can be used to improve accessibility by ensuring the caret is easily visible, or to ensure consistency with a large font size. If set to [code]0[/code] or lower, the caret width is automatically set to 1 pixel and multiplied by the display scaling factor.
 		</theme_item>
 		<theme_item name="line_spacing" data_type="constant" type="int" default="4">
-			Sets the spacing between the lines.
+			Additional vertical spacing between lines (in pixels), spacing is added to line descent. This value can be negative.
 		</theme_item>
 		<theme_item name="outline_size" data_type="constant" type="int" default="0">
 			The size of the text outline.

+ 1 - 1
doc/classes/TextMesh.xml

@@ -37,7 +37,7 @@
 			Language code used for text shaping algorithms, if left empty current locale is used instead.
 		</member>
 		<member name="line_spacing" type="float" setter="set_line_spacing" getter="get_line_spacing" default="0.0">
-			Vertical space between lines in multiline [TextMesh].
+			Additional vertical spacing between lines (in pixels), spacing is added to line descent. This value can be negative.
 		</member>
 		<member name="offset" type="Vector2" setter="set_offset" getter="get_offset" default="Vector2(0, 0)">
 			The text drawing offset (in pixels).

+ 3 - 0
doc/classes/TextParagraph.xml

@@ -280,6 +280,9 @@
 		<member name="justification_flags" type="int" setter="set_justification_flags" getter="get_justification_flags" enum="TextServer.JustificationFlag" is_bitfield="true" default="163">
 			Line fill alignment rules. See [enum TextServer.JustificationFlag] for more information.
 		</member>
+		<member name="line_spacing" type="float" setter="set_line_spacing" getter="get_line_spacing" default="0.0">
+			Additional vertical spacing between lines (in pixels), spacing is added to line descent. This value can be negative.
+		</member>
 		<member name="max_lines_visible" type="int" setter="set_max_lines_visible" getter="get_max_lines_visible" default="-1">
 			Limits the lines of text shown.
 		</member>

+ 2 - 0
scene/gui/button.cpp

@@ -561,6 +561,7 @@ void Button::_shape(Ref<TextParagraph> p_paragraph, String p_text) {
 	}
 	autowrap_flags = autowrap_flags | TextServer::BREAK_TRIM_EDGE_SPACES;
 	p_paragraph->set_break_flags(autowrap_flags);
+	p_paragraph->set_line_spacing(theme_cache.line_spacing);
 
 	if (text_direction == Control::TEXT_DIRECTION_INHERITED) {
 		p_paragraph->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
@@ -833,6 +834,7 @@ void Button::_bind_methods() {
 	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Button, icon_max_width);
 
 	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Button, align_to_largest_stylebox);
+	BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Button, line_spacing);
 }
 
 Button::Button(const String &p_text) {

+ 1 - 0
scene/gui/button.h

@@ -100,6 +100,7 @@ private:
 
 		int h_separation = 0;
 		int icon_max_width = 0;
+		int line_spacing = 0;
 	} theme_cache;
 
 	void _shape(Ref<TextParagraph> p_paragraph = Ref<TextParagraph>(), String p_text = "");

+ 33 - 8
scene/resources/text_paragraph.cpp

@@ -112,6 +112,11 @@ void TextParagraph::_bind_methods() {
 
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "max_lines_visible"), "set_max_lines_visible", "get_max_lines_visible");
 
+	ClassDB::bind_method(D_METHOD("set_line_spacing", "line_spacing"), &TextParagraph::set_line_spacing);
+	ClassDB::bind_method(D_METHOD("get_line_spacing"), &TextParagraph::get_line_spacing);
+
+	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "line_spacing"), "set_line_spacing", "get_line_spacing");
+
 	ClassDB::bind_method(D_METHOD("get_line_objects", "line"), &TextParagraph::get_line_objects);
 	ClassDB::bind_method(D_METHOD("get_line_object_rect", "line", "key"), &TextParagraph::get_line_object_rect);
 	ClassDB::bind_method(D_METHOD("get_line_size", "line"), &TextParagraph::get_line_size);
@@ -180,6 +185,7 @@ void TextParagraph::_shape_lines() {
 			for (int i = 0; i < line_breaks.size(); i = i + 2) {
 				RID line = TS->shaped_text_substr(rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]);
 				float h = (TS->shaped_text_get_orientation(line) == TextServer::ORIENTATION_HORIZONTAL) ? TS->shaped_text_get_size(line).y : TS->shaped_text_get_size(line).x;
+				h += line_spacing;
 				if (!tab_stops.is_empty()) {
 					TS->shaped_text_tab_align(line, tab_stops);
 				}
@@ -574,12 +580,18 @@ Size2 TextParagraph::get_size() const {
 			}
 			size.x = MAX(size.x, lsize.x);
 			size.y += lsize.y;
+			if (i != visible_lines - 1) {
+				size.y += line_spacing;
+			}
 		} else {
 			if (h_offset > 0 && i <= dropcap_lines) {
 				lsize.y += h_offset;
 			}
 			size.x += lsize.x;
 			size.y = MAX(size.y, lsize.y);
+			if (i != visible_lines - 1) {
+				size.x += line_spacing;
+			}
 		}
 	}
 	if (h_offset > 0) {
@@ -612,6 +624,19 @@ int TextParagraph::get_max_lines_visible() const {
 	return max_lines_visible;
 }
 
+void TextParagraph::set_line_spacing(float p_spacing) {
+	_THREAD_SAFE_METHOD_
+
+	if (line_spacing != p_spacing) {
+		line_spacing = p_spacing;
+		lines_dirty = true;
+	}
+}
+
+float TextParagraph::get_line_spacing() const {
+	return line_spacing;
+}
+
 Array TextParagraph::get_line_objects(int p_line) const {
 	_THREAD_SAFE_METHOD_
 
@@ -697,10 +722,10 @@ Rect2 TextParagraph::get_line_object_rect(int p_line, Variant p_key) const {
 		if (i != p_line) {
 			if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) {
 				ofs.x = 0.f;
-				ofs.y += TS->shaped_text_get_descent(lines_rid[i]);
+				ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing;
 			} else {
 				ofs.y = 0.f;
-				ofs.x += TS->shaped_text_get_descent(lines_rid[i]);
+				ofs.x += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing;
 			}
 		}
 	}
@@ -872,10 +897,10 @@ void TextParagraph::draw(RID p_canvas, const Vector2 &p_pos, const Color &p_colo
 		TS->shaped_text_draw(lines_rid[i], p_canvas, ofs, clip_l, clip_l + l_width, p_color);
 		if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) {
 			ofs.x = p_pos.x;
-			ofs.y += TS->shaped_text_get_descent(lines_rid[i]);
+			ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing;
 		} else {
 			ofs.y = p_pos.y;
-			ofs.x += TS->shaped_text_get_descent(lines_rid[i]);
+			ofs.x += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing;
 		}
 	}
 }
@@ -974,10 +999,10 @@ void TextParagraph::draw_outline(RID p_canvas, const Vector2 &p_pos, int p_outli
 		TS->shaped_text_draw_outline(lines_rid[i], p_canvas, ofs, clip_l, clip_l + l_width, p_outline_size, p_color);
 		if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) {
 			ofs.x = p_pos.x;
-			ofs.y += TS->shaped_text_get_descent(lines_rid[i]);
+			ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing;
 		} else {
 			ofs.y = p_pos.y;
-			ofs.x += TS->shaped_text_get_descent(lines_rid[i]);
+			ofs.x += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing;
 		}
 	}
 }
@@ -1001,12 +1026,12 @@ int TextParagraph::hit_test(const Point2 &p_coords) const {
 			if ((p_coords.y >= ofs.y) && (p_coords.y <= ofs.y + TS->shaped_text_get_size(line_rid).y)) {
 				return TS->shaped_text_hit_test_position(line_rid, p_coords.x);
 			}
-			ofs.y += TS->shaped_text_get_size(line_rid).y;
+			ofs.y += TS->shaped_text_get_size(line_rid).y + line_spacing;
 		} else {
 			if ((p_coords.x >= ofs.x) && (p_coords.x <= ofs.x + TS->shaped_text_get_size(line_rid).x)) {
 				return TS->shaped_text_hit_test_position(line_rid, p_coords.y);
 			}
-			ofs.y += TS->shaped_text_get_size(line_rid).x;
+			ofs.y += TS->shaped_text_get_size(line_rid).x + line_spacing;
 		}
 	}
 	return TS->shaped_text_get_range(rid).y;

+ 4 - 0
scene/resources/text_paragraph.h

@@ -51,6 +51,7 @@ private:
 
 	bool lines_dirty = true;
 
+	float line_spacing = 0.0;
 	float width = -1.0;
 	int max_lines_visible = -1;
 
@@ -122,6 +123,9 @@ public:
 	void set_max_lines_visible(int p_lines);
 	int get_max_lines_visible() const;
 
+	void set_line_spacing(float p_spacing);
+	float get_line_spacing() const;
+
 	Size2 get_non_wrapped_size() const;
 
 	Size2 get_size() const;