How to programatically create word-wrapped text that changes color on focus/mouseover

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

I am programming a CYOA-alike in godot using GDScript. I have created a SQL database using the Godot SQLite plugin that contains one table with paragraph IDs and the associated text, and another table that contains the choices presented to the player.

I have written some code that waits for a new paragraph to be displayed on screen, and then looks up all choices associated with that paragraph and iterates through them using a for loop, generating a button for each choice. When the button is clicked, it emits a signal notifying the main scene to display the next paragraph. (This is probably over-engineered but it is not the focus of this question).

So far so good. However, I would like to have the choices change color when moused-over or focused, so that the player can know which choice they are selecting on clicking.

It is trivial to do this when the choices are buttons. Unfortunately buttons don’t come with word-wrap, so longer choices were continuing off the screen.

I fixed this by adding code to create a child label for each button. This handles word wrapping, but as labels do not come with a built-in ‘on hover’ color change, I have now lost the color-change functionality.

My search of the existing Q&A showed how to implement color change functionality for an existing node, but not for a programatically-created one. At this point I’m not sure how to handle.

:bust_in_silhouette: Reply From: skysphr

Try to call

get_node("YourButton/YourLabel").add_color_override("default_color", some_colour)

on mouse enter and resetting the colour on mouse exit.

Thank you, this is helpful.

I think that I’m still going wrong somewhere in the path. The button and label are intended to be created underneath an HBox (so the path would be something/HBox/[Object x]/[Object y]), where x is the button and y is the label, and x and y are both dynamically generated.

The relevant bit of code inside the for loop reads as follows:

	# Create new button as child of HBox
	add_child(newbutton)
	
	# Create new label as child of button
	newbutton.add_child(newlabel)
	
	# Connect new label to mouseover functionality
	newlabel.connect("mouse_entered", self, "on_mouse_entered")

Later I created a function:

func on_mouse_entered():
	[presumably this is where I would add the code snippet you suggested?]

The newlabel.connect doesn’t seem to do anything. I’m working on the basis that ‘self’ here references the button and not the Hbox, which is the node to which the script is attached. Maybe this is wrong?

Should this work, or am I missing something very obvious (like I’m referencing the wrong object or similar)?

Beefeater1980 | 2022-01-26 13:34

I’m working on the basis that ‘self’ here references the button and
not the Hbox, which is the node to which the script is attached.

If the script is attached to the hbox, self will refer to the hbox. You can run

newlabel.connect("mouse_entered", newbutton, "on_mouse_entered")

to make a connection between the label and the button. Alternatively you can make the button respond to mouse_entered and set the label’s mouse_filter to MOUSE_FILTER_IGNORE if you prefer.

skysphr | 2022-01-26 18:38