How to create a reusable component?

I’m using Godot 4, and I want a special LineEdit control, which I can instantiate multiple times. Is it right to create a scene for it? I tried this, see here:

https://i.imgur.com/BMibtax.png

So there is a normal LineEdit, and then there is a Button as a child. I attached a script to the button, for implementing dragging on it. This works fine, and I can instantiate it as a node in other scenes.

But I also defined a signal, but I can’t see it in the Node tab to connect it to a script in the parent scene. How would I do this? And is this approach with a scene the right way to implement reusable components?

Yes, this is exactly what scenes are made for. Since the script is on your button, the signal is also on your button. To see the signal in a other scene, you have to either put the script on the LineEdit (this would require to change a lot of code) or you press right-click on the LineEdit in the other scene and activate “Editable Children”. Then you can click on the button and should see your signal

Would it be a lot of code?

Could you just have the button’s signal instead connect to the root node (line edit) of the scene, and have it connect to a function that emits a custom signal of that root node?

So you would just need a script on the line edit that was a few lines long to define a signal and have a function that emits it?

Depends on the code you have right-now.
Have you tried the second option i presented?

I am not OP just interested in learning as well.

Oh sorry :sweat_smile:. Your solution would work, but its unneccessarily complicated

Thanks, moving the script to the LineEdit worked. Wasn’t that much code.

It is a component, where the user can click on the (invisible) button, and then drag it to change the value of the underlying field. This is the current code:

extends LineEdit

signal value_changed(number)

var dragging = false
var ofs = 0

var current_number = 0
var start = 10
var end = 1000

var width = 200

func _ready():
	pass


func _process(delta):
	if dragging:
		var x = get_global_mouse_position().x
		var dx = x - ofs
		ofs = x
		var value_range = end - start
		if value_range == 0:
			dx = 0
		else:
			var pixels_per_value = value_range / width
			dx *= pixels_per_value
		current_number += dx
		current_number = clampf(current_number, start, end)
		_update_number_text()
		emit_signal("value_changed", current_number)


func _update_number_text():
	text = String.num(current_number)


func _on_button_down():
	dragging = true
	mouse_default_cursor_shape = Control.CURSOR_HSIZE
	ofs = get_global_mouse_position().x


func _on_button_up():
	mouse_default_cursor_shape = Control.CURSOR_ARROW
	dragging = false


func init(start, end, number):
	self.start = start
	self.end = end
	self.number = number

Might need some more code to synchronize text edits as well.

1 Like

So are there still problems?

No, everything is fine. I marked the solution.

2 Likes

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