In my game, written in godot 3.5, I use 2 routines to get the (first) node, in a hierarchy, having a given type or type name, and they work fine even with custom classes (i.e. defined with class_name).
They are:

static func find_node_by_type_name(type_name:String, root_node:Node):
	# get the first node instance with the given type name: by using tree's
	# iterative breadth search, the first ones found are returned
	var instance = null
	var stack = []
	stack.append_array(root_node.get_children())
	while not stack.is_empty():
		var child = stack.pop_front()
		if child.get_class() == type_name:
			instance = child
			break
		stack.append_array(child.get_children())
	return instance


static func find_node_by_type(type, root_node:Node):
	# get the first node instance with the given type: by using tree's
	# iterative breadth search, the first ones found are returned
	var instance = null
	var stack = []
	stack.append_array(root_node.get_children())
	while not stack.is_empty():
		var child = stack.pop_front()
		if child is type:
			instance = child
			break
		stack.append_array(child.get_children())
	return instance

Note that the first one,find_node_by_type_name, works with custom types since I've overridden the two methods get_class and is_class for all of my custom types.

Now in godot 4.1 these functions don't work anymore, since:

  • get_class and is_class methods can no longer be overridden

  • a type can no longer be passed as function parameter.

So, does anyone have an idea how to fix this or know of an alternative way to achieve the same results?
Thanks

  • xyz replied to this.

    xyz thanks.
    This is the new version of find_node_by_type

    static func find_node_by_type(type:Variant, root_node:Node):
    	# get the first node instance with the given type: by using tree's
    	# iterative breadth search, the first ones found are returned
    	var instance = null
    	var stack = []
    	stack.append_array(root_node.get_children())
    	while not stack.is_empty():
    		var child = stack.pop_front()
    		if is_instance_of(child, type):
    			instance = child
    			break
    		stack.append_array(child.get_children())
    	return instance

    Unfortunately I didn't find an elegant way to find node by type name that works with custom types.

    • xyz replied to this.

      beopenbefree Override get_class() in all your custom classes so it returns your class name, and use that method to identify types by name strings. When not overridden it will return the name of the native base type.

        xyz , as said, if i try to override get_class() (or is_class()) i get this error/warning:

        The method "get_class()" overrides a method from native class "Object". This won't be called by the engine and may not work as expected. (Warning treated as error.)

        • xyz replied to this.

          beopenbefree You can implement something like get_custom_class() and when testing for type call it if it exists, otherwise call the built in get_class():

          func get_class_name(obj):
          	if obj.has_method("get_custom_class"):
          		return obj.get_custom_class()
          	return obj.get_class()