How to make the button stay (visually) pressed?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By godot.ma.desive.logo

How to make the button stay pressed (visually it is enough), even if the mouse is no longer pressing and touching it?

$Button.set__keep__pressed__outside(true)

is working only while mouse is still pressed.

:bust_in_silhouette: Reply From: jgodfrey

You don’t say what you’re doing here, but maybe a CheckButton or CheckBox control would be more appropriate? Both will give you a specific, binary (on/off) state with expected visuals…

I try to make pause/play button. If the button is pressed, it has got another icon than if it is unpressed.

godot.ma.desive.logo | 2020-08-31 17:17

I still might recommend a CheckButton. In the inspector, you can supply custom icons for Off, On, and On Disabled states of the button. So, you can make it look like you want and it’ll give you explicit on/off state info…

jgodfrey | 2020-08-31 17:28

Likewise, you can assign custom icons to the various states of a CheckBox also.

jgodfrey | 2020-08-31 17:47

I solved it so:

$Pause.DRAW_HOVER_PRESSED

but the thing with the CheckBoxes is good idea.
One more thing, I didn’t figure out how to remove the black square on the CheckBox. So it overlaps the icon I’m trying to place there.

godot.ma.desive.logo | 2020-09-01 08:59

In case other folks find this thread in the future, another solution I found (using Godot 4.6) is turning on Toggle Mode on the button. Clicking on the button will then toggle it between pressed and unpressed.

For my use case, I also had a group of buttons where toggling one on would toggle the rest off, and you weren’t allowed to toggle off a button on its own. For that, I had to do a couple extra things:

  1. Have a script on the button group that accepts a signal when one button is toggled on, then toggle the rest off without emitting the pressed signal (child_button.set_pressed_no_signal(false))
  2. Have a script on each button that takes in the toggle signal, doing nothing if toggling off, and emitting a signal if toggled on

signal button_selected(opponent_id: int)

@export var button_id: int

func _toggled(toggled_on: bool) -> void:
	"""
	Handle when the button is toggled.
	Disallow toggling off by clicking. Group above this handles deselection when
	another button is toggled on. Does not emit when trying to toggle off.
	If toggled to on, emit the signal that the new button is selected.
	"""
	if not toggled_on:
		set_pressed_no_signal(true)
	else:
		button_selected.emit(button_id)