How to draw text into a texture or image, entirely from code?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By davthedev

Hi,

My current goal is to generate a simple image with background texture and text. The image can then be used in an ItemList as an icon for items.

I would like to find out how to:

  • draw something using primitives such as draw_rect or draw_string off-screen
  • get the resulting image or texture

Drawing primitives are not available on Image nor TextureImage.
I’ve read the viewport-on-a-texture tutorial; it seems to be a bit of overkill to perform such a simple task.
In addition, it requires preparing a scene tree from the GUI for the rendering part. As my work is a utility function that can be called anywhere, I would like to avoid instanciating any nodes for it using the GUI.

All I want is:
Arguments (text, bg color) in ===> Image or ImageTexture out.

So far, I have tried tinkering with viewports and getting the resulting texture; nothing is visible.

Here is an excerpt of my code:

var vport = Viewport.new()
#this is the desired output image size
vport.set_size_override(true, Vector2(64, 32)) 

var cvitem = Control.new()
vport.add_child(cvitem)

var font = load("res://fonts/res/narrative_text.tres")
cvitem.draw_string(font, Vector2(20, 20), "XXX", Color(0.0, 0.0, 1.0))
cvitem.draw_rect(Rect2(0, 0, 100, 100), Color(1.0, 0.0, 0.0), true)

var vport_img = vport.get_texture().get_data()
vport_img.flip_y()

When displaying the vport_img, all I can see is transparent pixels.

Can I achieve that in Godot 3.1?
Thanks!

Do you reached any solution?

siamak-s | 2019-07-28 13:30

:bust_in_silhouette: Reply From: Gary_CHAN

I don’t know if you still need it. Here is what I got. But I am not sure if it is right and what you want cuz I am still new to Godot. It saves an png with XXX on it.

extends Node2D

var vport = Viewport.new()
var vport_img

func _ready():
	vport.size = Vector2(64, 64)
    # or Viewport.UPDATE_ONCE
	vport.render_target_update_mode = Viewport.UPDATE_ALWAYS 
	self.add_child(vport)
	var cvitem = Control.new()
	vport.add_child(cvitem)
	cvitem.rect_min_size =  Vector2(64, 64)
	cvitem.set_script(load("res://draw.gd"))


func _on_Button_pressed():
    vport_img = vport.get_texture().get_data()
	vport_img.flip_y()
	vport_img.save_png("res://test.png")

draw.gd
the font is a DynamicFont

extends Control

var font = load("res://font.tres")

func _draw():
	draw_string(font, Vector2(20, 20), "XXX", Color(0.0, 0.0, 1.0, 1.0))