Propagate _make_custom_tooltip() to children?

Godot Version

4.5

Question

Hi,
I try to use _make_custom_tooltip() to create my own tooltips (the same tooltip frame for the whole application), but for the moment it seems that I have to declare this function on every control where I want this custom tooltip, which is tedious because I have a lot of nested controls in my UI (and most of them do not even have an attached script).
I tried to declare it once on the main parent control, but it does not seems to propagate to its children or sub children…
Am I missing something ?
Does someone have a simple solution ?

If you are just changing the background you can override the TooltipPanel StyleBox as explained in the Control.tooltip_text documentation.

There’s no way to propagate _make_custom_tooltip() currently as far as I’m aware.

1 Like

No, not just changing the style : I am redesigning the whole tooltip with icons, colors, etc…

Subsidary question : is there a way to programmaticaly add a method to an object ? (in my case add the _make_custom_tooltip method to every control of my tree ?..)

GDScript does not support mixins/traits yet. There is an open proposal and an open implementation so maybe for 4.6.

In the meantime, it’s kinda possible (with a few drawbacks):

extends Node


const SCRIPT_CONTENT = """
extends {extend_class}

func _make_custom_tooltip(for_text: String) -> Object:
	var lbl = Label.new()
	lbl.text = "Extended: %s" % for_text
	lbl.add_theme_color_override("font_color", Color.RED)
	return lbl
"""


func _enter_tree() -> void:
	get_tree().node_added.connect(func(node:Node):
		# Skip nodes that aren't a control
		if not node is Control:
			return

		node = node as Control

		# Skip node if it does not have a tooltip
		if node.get_tooltip() == "":
			return

		# Get the class of the node
		var extend_class = node.get_class()
		# Also check if the node has a script
		var node_script = node.get_script() as Script
		if node_script:
			# If it does, then change it to extend that script
			extend_class = '"%s"' % node_script.resource_path

		# Format the script content
		var script_content = SCRIPT_CONTENT.format({"extend_class": extend_class})

		# Create a new script, assign the new source code and reload it
		var script = GDScript.new()
		script.source_code = script_content
		script.reload()
		# Set the new script to that node
		node.set_script(script)
	)

Add that script as an autoload and every Control that gets added to the SceneTree and has a tooltip will add or extend its script with that function. If the script is a built-in script or not a GDScript then it will probably fail.

Result:

1 Like

Hi @mrcdk and thanks for your useful answer !
I understand the principle, but I must admit that I’m a bit lost when you add dynamically the make_custom_tooltip script to any Control that is added to the tree.
I do not understand how you are not overwritting any pre-existing script on the node.
I tried it, creating a derivated class from Button, with its own script, and it works, but I cannot figure out why both scripts can run on the same node… I though that one node - one script.
I do not understand either when you say : “If the script is a built-in script or not a GDScript then it will probably fail.”

Edit: BTW, I do not understand how Godot can compile a piece of code that you add dynamically after compilation time…

It just creates a new GDScript script and assigns it to the node. When creating the script it will extend the script the node already has, if any, or extends the class of the node.

You can extend scripts by file path and that’s why if the script is a built-in script will fail because built-in scripts don’t have a file path and I’m not sure if you can extend a C# with GDScript for example.

GDScript is an scripting language and it’s not compiled.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.