Creating Hover-Triggered Images for Buttons in Godot 4.0.3

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

On the game’s start screen, there are four buttons - New Game, Load
Game, Settings, and Exit. These buttons are placed on the left side
of the screen. My aim is to display a unique image on the right side
of the screen when the mouse hovers over each button. The image
should disappear when the mouse is moved away. Also, I want the
image appearance and disappearance to be gradual, not abrupt. How
can I achieve this effect? Is there a demo available for reference?

:bust_in_silhouette: Reply From: Zylann

Button inherits Control: Control — Godot Engine (stable) documentation in English
You can use the mouse_entered and mouse_exited signals on each of the buttons to set a particular image using a script.
You can show each image with a TextureRect and put a script on each of them handling the two signals to trigger the changes.

If you want the image to show gradually, you could perhaps use a Tween ( Tween — Godot Engine (stable) documentation in English) to animate the modulate property of each image from opaque white to transparent white, or an animation with AnimationPlayer. Using a script doing this in _process is also a valid solution:

# menu_image.gd
# Put this script on each TextureRect,
# and connect each button's signals to the corresponding TextureRect

@export var speed = 5.0

var _active = false

func _on_button_mouse_entered():
	_active = true


func _on_button_mouse_exited():
	_active = false


func _process(delta):
	var color = modulate
	if active:
		color.a = maxf(color.a - delta * speed, 0.0)
	else:
		color.a = minf(color.a + delta * speed, 1.0)
	modulate = color

(untested, just to show one example of how I’d do it with a script. There are other ways too)

:bust_in_silhouette: Reply From: zhyrin

Button extends Control, so you have access to the mouse_entered and mouse_exited signals. You can connect to these to detect hover over the buttons.

The two ways to animate the right side would be with an AnimationPlayer or using a tween. I recommend a tween.

You need to connect your mouse enter/exit signals from the buttons to the right side of the screen and fade in with mouse enter, fade out with mouse exit.
You want to fade in different images with different buttons, so you need to pass along some extra data about that as well.

a) You can connect each mouse entered signal to a different callback, that way the right side of the screen knows which button was hovered.
b) When connecting the signal, you can bind data in the connection, that way you can predefine with the connection which button was hovered. This way there is only need for one callback for mouse enter event.
c) You can define your own button type that has a similar mouse entered signal (will need a different name), but it has a parameter that can be used to determine which button was hovered. These buttons are connected internally to the base buttons mouse entered signal, and they emit their custom mouse entered signal. The right side of the screen would be connected to these custom signal and in this case also, you only need one callback for the mouse entered events.

The tween is a better option for this kind of animation, because if you are hovering over different buttons quickly, there might not be enought time between them to finish an animation completely, and tween is better for handling situations when you don’t know exactly what’s your start or end position.

How you want to animate the images is up to you. Is it movement or opacity?
If you just want to fade them in, you can use the modulate and self_modulate properties of CanvasItem (which all ui elements inherit) to change the opacity in the alpha channel.