How to get all nodes in the tree?

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

The title should be pretty self explanatory, but anyway: I need to check something with every single node in a tree. Is there a method that would return an array of all the nodes in a tree or something like that?

Please notify me if my question isn’t clear enough.

:bust_in_silhouette: Reply From: jgodfrey

Depending on your scene tree, that sounds highly inefficient. Perhaps with some more detail, a more performant solution could be suggested…

Regarding the specific question, I don’t think there’s a built-in way to retrieve all nodes, though you could write code to recursively do so relatively easily.

Potentially helpful, the SceneTree has both node_added and node_removed signals that fire each time a node is added or removed from the scene. You could hook those up and use them to keep a running collection of nodes in the scene.

:bust_in_silhouette: Reply From: GrayDwarf
# Example use-case where I needed to go through the entire
# tree looking for a node that had a min_size set. This is a 
# recursive method that performs the search while traversing
# through all the nodes in the tree.
func SpewTreeInfo(node = get_tree().root):
	if "rect_min_size" in node:
		if node.rect_min_size.x > 0:
			print(node.name + " - " + str(node.rect_min_size.x))
	for childNode in node.get_children():
		SpewTreeInfo(childNode)

func _on_Button_pressed():
	SpewTreeInfo()
    
# This alternative method can be called to get a list of all nodes
func GetAllTreeNodes(var node = get_tree().root, var listOfAllNodesInTree = []):
	listOfAllNodesInTree.append(node)
	for childNode in node.get_children():
		GetAllTreeNodes(childNode, listOfAllNodesInTree)
	return listOfAllNodesInTree

# An example that uses GetAllTreeNodes() and does the same thing as 
# the recursive method above.
func _on_Button_pressed():
    var listOfAllTreeNodes = GetAllTreeNodes()
	print("Total Tree Nodes: " + str(listOfAllTreeNodes.size()))
    for node in listOfAllTreeNodes:
        if "rect_min_size" in node:
	        if node.rect_min_size.x > 0:
                print(node.name + " - " + str(node.rect_min_size.x))

I used your advice and found it very useful… so to get all nodes in scene, for instance if you want to filter specific node types you need a callable with content:

var scene_list=[] #in properties list or use set_meta("scene_list", [])

func node_list(node):
	scene_list.append(node)

then add to script:

func _enter_tree():
	get_tree().node_added.connect(self.node_list)
func _ready():
	get_tree().node_added.disconnect(self.node_list) #should be first string in _ready()
	print(scene_list)

after all checks and lists done in _ready() scripts it is good to set scene_list=null

OR alternatively you can get an array of exact type of nodes:

func node_list(node):
	if node.is_class("Label"):
		labels.append(node)
	elif node.is_class("Button"):
		btns_list.append(node)
	elif node.is_class("LineEdit"):
		lines.append(node)

but better DO NOT use this sorting outside of _ready()