Browse Source

Merge pull request #32864 from nekomatata/rich-text-image-size

Support for resized images in RichTextLabel
Rémi Verschelde 5 years ago
parent
commit
b67537b14b
3 changed files with 66 additions and 9 deletions
  1. 6 1
      doc/classes/RichTextLabel.xml
  2. 58 7
      scene/gui/rich_text_label.cpp
  3. 2 1
      scene/gui/rich_text_label.h

+ 6 - 1
doc/classes/RichTextLabel.xml

@@ -16,8 +16,13 @@
 			</return>
 			<argument index="0" name="image" type="Texture">
 			</argument>
+			<argument index="1" name="width" type="int" default="0">
+			</argument>
+			<argument index="2" name="height" type="int" default="0">
+			</argument>
 			<description>
-				Adds an image's opening and closing tags to the tag stack.
+				Adds an image's opening and closing tags to the tag stack, optionally providing a [code]width[/code] and [code]height[/code] to resize the image.
+				If [code]width[/code] or [code]height[/code] is set to 0, the image size will be adjusted in order to keep the original aspect ratio.
 			</description>
 		</method>
 		<method name="add_text">

+ 58 - 7
scene/gui/rich_text_label.cpp

@@ -624,19 +624,19 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
 				if (p_mode == PROCESS_POINTER && r_click_char)
 					*r_click_char = 0;
 
-				ENSURE_WIDTH(img->image->get_width());
+				ENSURE_WIDTH(img->size.width);
 
-				bool visible = visible_characters < 0 || (p_char_count < visible_characters && YRANGE_VISIBLE(y + lh - font->get_descent() - img->image->get_height(), img->image->get_height()));
+				bool visible = visible_characters < 0 || (p_char_count < visible_characters && YRANGE_VISIBLE(y + lh - font->get_descent() - img->size.height, img->size.height));
 				if (visible)
 					line_is_blank = false;
 
 				if (p_mode == PROCESS_DRAW && visible) {
-					img->image->draw(ci, p_ofs + Point2(align_ofs + wofs, y + lh - font->get_descent() - img->image->get_height()));
+					img->image->draw_rect(ci, Rect2(p_ofs + Point2(align_ofs + wofs, y + lh - font->get_descent() - img->size.height), img->size));
 				}
 				p_char_count++;
 
-				ADVANCE(img->image->get_width());
-				CHECK_HEIGHT((img->image->get_height() + font->get_descent()));
+				ADVANCE(img->size.width);
+				CHECK_HEIGHT((img->size.height + font->get_descent()));
 
 			} break;
 			case ITEM_NEWLINE: {
@@ -1634,7 +1634,7 @@ void RichTextLabel::_remove_item(Item *p_item, const int p_line, const int p_sub
 	}
 }
 
-void RichTextLabel::add_image(const Ref<Texture> &p_image) {
+void RichTextLabel::add_image(const Ref<Texture> &p_image, const int p_width, const int p_height) {
 
 	if (current->type == ITEM_TABLE)
 		return;
@@ -1643,6 +1643,30 @@ void RichTextLabel::add_image(const Ref<Texture> &p_image) {
 	ItemImage *item = memnew(ItemImage);
 
 	item->image = p_image;
+
+	if (p_width > 0) {
+		// custom width
+		item->size.width = p_width;
+		if (p_height > 0) {
+			// custom height
+			item->size.height = p_height;
+		} else {
+			// calculate height to keep aspect ratio
+			item->size.height = p_image->get_height() * p_width / p_image->get_width();
+		}
+	} else {
+		if (p_height > 0) {
+			// custom height
+			item->size.height = p_height;
+			// calculate width to keep aspect ratio
+			item->size.width = p_image->get_width() * p_height / p_image->get_height();
+		} else {
+			// keep original width and height
+			item->size.height = p_image->get_height();
+			item->size.width = p_image->get_width();
+		}
+	}
+
 	_add_item(item, false);
 }
 
@@ -2125,6 +2149,7 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
 			int end = p_bbcode.find("[", brk_end);
 			if (end == -1)
 				end = p_bbcode.length();
+
 			String image = p_bbcode.substr(brk_end + 1, end - brk_end - 1);
 
 			Ref<Texture> texture = ResourceLoader::load(image, "Texture");
@@ -2133,6 +2158,32 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
 
 			pos = end;
 			tag_stack.push_front(tag);
+		} else if (tag.begins_with("img=")) {
+
+			int width = 0;
+			int height = 0;
+
+			String params = tag.substr(4, tag.length());
+			int sep = params.find("x");
+			if (sep == -1) {
+				width = params.to_int();
+			} else {
+				width = params.substr(0, sep).to_int();
+				height = params.substr(sep + 1, params.length()).to_int();
+			}
+
+			int end = p_bbcode.find("[", brk_end);
+			if (end == -1)
+				end = p_bbcode.length();
+
+			String image = p_bbcode.substr(brk_end + 1, end - brk_end - 1);
+
+			Ref<Texture> texture = ResourceLoader::load(image, "Texture");
+			if (texture.is_valid())
+				add_image(texture, width, height);
+
+			pos = end;
+			tag_stack.push_front("img");
 		} else if (tag.begins_with("color=")) {
 
 			String col = tag.substr(6, tag.length());
@@ -2581,7 +2632,7 @@ void RichTextLabel::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_text"), &RichTextLabel::get_text);
 	ClassDB::bind_method(D_METHOD("add_text", "text"), &RichTextLabel::add_text);
 	ClassDB::bind_method(D_METHOD("set_text", "text"), &RichTextLabel::set_text);
-	ClassDB::bind_method(D_METHOD("add_image", "image"), &RichTextLabel::add_image);
+	ClassDB::bind_method(D_METHOD("add_image", "image", "width", "height"), &RichTextLabel::add_image, DEFVAL(0), DEFVAL(0));
 	ClassDB::bind_method(D_METHOD("newline"), &RichTextLabel::add_newline);
 	ClassDB::bind_method(D_METHOD("remove_line", "line"), &RichTextLabel::remove_line);
 	ClassDB::bind_method(D_METHOD("push_font", "font"), &RichTextLabel::push_font);

+ 2 - 1
scene/gui/rich_text_label.h

@@ -148,6 +148,7 @@ private:
 
 	struct ItemImage : public Item {
 		Ref<Texture> image;
+		Size2 size;
 		ItemImage() { type = ITEM_IMAGE; }
 	};
 
@@ -406,7 +407,7 @@ protected:
 public:
 	String get_text();
 	void add_text(const String &p_text);
-	void add_image(const Ref<Texture> &p_image);
+	void add_image(const Ref<Texture> &p_image, const int p_width = 0, const int p_height = 0);
 	void add_newline();
 	bool remove_line(const int p_line);
 	void push_font(const Ref<Font> &p_font);