Rotated Button in Container - possible solution

Godot Version

4.4

Question

I’ve been struggling to rotate a button inside of a container because the containers control position, size and rotation.

I think I have a solution to this issue that’s a bit different to what others have proposed but I am pretty new to Godot so I am not sure what the downsides are to what I’ve done and I would love others opinions.

Problem statement, I want a button that is displayed vertically rather than horizontally. In other words, the Y size is bigger than the X size. I want the text for the button to be rotated 90 degrees, so it is displayed vertically (not horizontally one character at a time, properly vertically).

To do this, I create a new Scene with a button and a child label. I rotated the label 90 degrees.

I then use this code in the button control:

func _ready() -> void:
	match_label_size()
	reset_size()
	
func match_label_size():
	custom_minimum_size.y = $Label.size.x
	custom_minimum_size.x = $Label.size.y
	
func _on_label_resized() -> void:
	match_label_size()

This lets me drop this scene in HBoxContainers and the text appears rotated and the button can be sized correctly in the container.

Is this a reasonable approach or have I done something silly?

Thanks in advance for any advice.

If it works, it works!

Something that could be good to remember if you want to mess around a lot with nodes inside container nodes. Any children of containers will lack transform. If instead of adding the button as a child, you add a suitable non-control node and then the button as a grandchild to the control node, you can more freely edit it.

1 Like

You can actually extend the Container class and code your own container to fine-tune the behavior you want. I personally find this easier than trying to rig the default ones to fit my needs.

Here’s a quick example:

extends Container


func _ready() -> void:
	sort_children.connect(_on_sort_children)


func _on_sort_children() -> void:
	var cumulative_x := 0.0
	for child in get_children():
		# Position child if it is a Control
		var control := child as Control
		if control:
			# Rotate control around its center
			control.pivot_offset = control.size / 2
			control.rotation_degrees = 90
			# Position control
			control.position = Vector2(cumulative_x, 0)
			cumulative_x += control.size.x

Thanks for this. I saw this in other threads but when experimenting I found that the container would clip the control as the size of the dummy control wasn’t the same as the child control. Hope that makes sense. Sorry I’d add a picture but not sure how to do that! :slight_smile:

Am I doing something wrong there or is this a limitation of the approach?

So reading this, it seems all child controls of the container will be rotated 90 degrees? So using this, I’d make button a child of this custom container and put this container in a HBoxContainer or whatever. Is that right?

Yes, except that you would use the custom container instead of the HBoxContainer.
Again, that was just a quick example. You can edit that however you’d like. It’s a bit more work, but I personally prefer it over trying to work around the default containers’ limitations.

1 Like

Wonderful. I think I prefer this approach as well. It saves creating an extra label (the button has a text label anyway) which felt like a bit of a hack.

Thanks for taking the time to help, it’s really appreciated.

1 Like