Display animated image in RichTextLabel

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

Is it possible to have an animated image (spritesheet or .gif) in RichTextLabel? How to do it?

:bust_in_silhouette: Reply From: njamster

No. You’ll have to use a RichTextLabel for the text and a TextureRect with an AnimatedTexture for the image.

Necroing here, but I just wanted to share that I have been able to make animated images work in RichTextLabels in Godot 4.3 stable. You would use an AnimatedTexture and add this via the add_image method just as you would add any other image texture. You just have to animate manually. Short workflow as follows:

  • Import the AnimatedTexture (yes I know it’s deprecated, but it’s running)
  • Call pause = true on the texture (I don’t know if that is really necessary but it wasn’t animating for me by itself, so just disabling the automatic code here)
  • Get an array of “time indices”, I call it timing array with time thresholds when to jump to the next frame
  • Store a reference to the texture and a manager item for keeping track of frame, current delta and timings
  • In your _process, use the delta to go through the frames as needed

Known Problems:

  • speed_scale is non-trivial to implement without frameskips

Code Snippets:

Preparing an animation

var texture: AnimatedTexture = ImageTransformer.read(body) # or whatever you use to import a GIF or something
texture.pause = true
var timing: PackedFloat32Array = [0.0]
for f in range(texture.frames):
	timing.push_back(timing[f] + texture.get_frame_duration(f))
var entry := { 'frame': 0, 'delta': 0.0, 'timing': timing.slice(1) }
animations[key] = entry
images[key] = texture

Playing the animation

func _process(delta: float) -> void:
	for key in animations:
		var animation: Dictionary = animations[key]
		var image: AnimatedTexture = images[key]
		animation.delta += delta
		var update := false
		while animation.delta > animation.timing[animation.frame]:
			update = true
			animation.frame += 1
			if animation.frame == image.frames:
				animation.frame = 0
				animation.delta -= animation.timing.back()
		if update:
			image.current_frame = animation.frame