How to make folding menu ?

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

How to make a folding menu like this:
(they looks like a drawer, usually its closes.
When one is opened, expand the window it contains and squeeze down the other drawers)

:bust_in_silhouette: Reply From: flurick

Here is an example of a custom node that works like an accordion.

enter image description here

enter image description here

The Control moves each child to the end of the previous one (only in the y direction)
enter image description here

extends Control

export var spacing = 10

func _draw():
	
	var last_end_achor = Vector2.ZERO
	for child in get_children():
		child.rect_position = last_end_achor
		last_end_achor.y = child.rect_position.y + child.rect_size.y 
		last_end_achor.y += spacing
	
	rect_min_size.y = last_end_achor.y #to work with ScrollContainer

And clicking on the button “show” toggles the parent “Panel” size to the open or the closed value.
enter image description here

extends Panel

var is_expanded = false


func _ready():
	$VBoxContainer/show.connect("pressed",self,"expand")


func expand():
	is_expanded = !is_expanded


var last_rect_size = Vector2.ZERO
func _process(delta):
	
	#snap to end
	if abs(rect_size.y-rect_min_size.y) < 1:
		rect_size.y = rect_min_size.y
	
	#resize to target size
	if is_expanded:
		rect_size.y = lerp(rect_size.y, 70, 0.1)
	else:
		rect_size.y = lerp(rect_size.y, rect_min_size.y, 0.1)
	
	#update layout
	if last_rect_size != rect_size:
		get_parent().update()
		last_rect_size = rect_size

Wow!!!Thanks!!

fish2091852127 | 2019-03-18 08:05

I followed your instruction to make this menu. But the items in panel didn’t close. Can you help?

hoody monkey | 2019-12-06 02:29

What I have done to make this work is to make the show button a child of the root and then set “Clip Content” in the panel rect properties to true.

Now the content of the panel will shrink with the panel.

If I find the time I will post an github project with an working reusable example.

R. K. | 2020-02-11 10:22

For me that solution doesn’t work well with spinbox. It makes an overflow due to callback update. I have done a simpler script on a VBoxContainer and a button “show” as his child and it seems to work.

extends VBoxContainer

export var is_expanded = true

func _ready():
	$show.connect("pressed",self,"expand")
	get_parent().connect("expand",self,"resized")


func expand():
	is_expanded = !is_expanded
	for child in get_children():
		child.visible = true if is_expanded else child == $show

m21-cerutti | 2022-02-21 20:18