Is there a way to access a sibling node without knowing it's name?

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

What I want is to be able to get Frame1 by only knowing the name of Frame5.
So far I’ve made this:

for frame in range(1,Global.current_frame):
	var before = subview.find_child(str(Global.current_frame-frame),true,false)
	if before:
		prev = before

The code goes thru every frame before the current one and gives back the frame or child above the current one.
It works but I keep thinking if there’s a better way to do it. I’m trying to get the next frame aswell but using the current system that seems to be a challenge.

Are the Frames the only children of this mystery parent node?

CollCaz | 2023-05-16 17:59

Yeah. Also the node is a Subviewport, named as subview.

Drawsi | 2023-05-16 18:11

And, you just want to find the node before and (potentially) after a specified Frame node?

jgodfrey | 2023-05-16 18:56

well then get_child(0) gets you the first child and get_child(-1) gets you the last child
so for example to get Frame4 you do get_child(3) and the one after it is just get_child(4) and so on.

CollCaz | 2023-05-16 18:59

Yeah, pretty much. Problem is that the frames will most often have a 1,5,9,12,23 type of arrangement rather then 1,2,3,4,5

Drawsi | 2023-05-16 18:59

yeah their names don’t matter because you are accessing their index in the tree with get_child(i)
hope this solves your issue

CollCaz | 2023-05-16 19:01

sorry i meant to say get_child(i) not get_node(i), i’ll fix my comments

CollCaz | 2023-05-16 19:04

using the get_child(i) function will only result in errors whenever It cannot find the said child:

E 0:00:01:0002 @ _onionskin_pp(): Index p_index = 2
is out of bounds (data.children.size() - data.internal_children_front

  • data.internal_children_back = 1). <C++ Source> scene/main/node.cpp:1248 @ get_child() @ _onionskin_pp() @ _input()

Drawsi | 2023-05-18 10:06

:bust_in_silhouette: Reply From: CollCaz

I think i understand your problem and this could be the solution

var frame_number1 = subview.get_child(0)
var frame_number3 = subview.get_child(2)
var frame_after_current_one = subview.get_child(current_frame.get_index() + 1)
var frame_before_current_one = subview.get_child(current_frame.get_index() - 1)
:bust_in_silhouette: Reply From: jgodfrey

Here’s one option, though you may need to season it to taste:

func find_prev_next_sibling_nodes(target_node):
	var prev_node = null
	var next_node = null
	if target_node:
		var parent = target_node.get_parent()
		var target_index = target_node.get_index()
		if target_index > 0:
			prev_node = parent.get_child(target_index - 1)
		if target_index < parent.get_child_count() - 1:
			next_node = parent.get_child(target_index + 1)

	return [prev_node, next_node]

Based on a target node, this will return a 2-element array, consisting of the node immediately before and immediately after the specified target node. If either node doesn’t exist (the target node is first or last), a null will be returned in that array element. So, for example, with this scene tree:


If it’s called like this:


… it’ll return [Child1, Child3]

If it’s called like this:


… it’ll return [null, Child2]

… and if it’s called like this:


… it’ll return [Child3, null]

You might want to add some additional error checking, but this might get you started.

Note, I just made a minor edit to the above code to ensure that target_node isn’t null before using it…

jgodfrey | 2023-05-16 20:41