Key input array selection getting double incremented on loop

Godot Version

4.3

Question

I’m trying to allow the user to cycle through buttons I have in a menu using the up and down keys. I have a print statement to output the index of the button for debugging purposes.

What is currently happening is it will cycle through the buttons and giving them each focus but it will not print until I have looped through the entire array of buttons.

Its suppose to then loop back around and start back at index 0 but instead it begins at index 1 and it will continue to increment the starting index every time it loops through the array of buttons.

I’m not sure if this is an issue with my logic or with a property of the buttons in Godot.

optionsbox

extends Control
class_name Battle 

@onready var _options : Array = $BattleUIContainer/BattleUIBox/OptionsRoot/OptionsBorder/OptionsContainer/OptionsBox.get_children()
var current_index : int = 0

func _ready() -> void:
	_options[current_index].grab_focus()

func _unhandled_key_input(event: InputEvent) -> void:
	if event.is_pressed() and event is InputEventKey:
		print(current_index)
		match event.keycode:
			KEY_DOWN:
				current_index = (current_index + 1) % _options.size()
				_options[current_index].grab_focus()
				
			KEY_UP:
				current_index = (current_index - 1 + _options.size()) % _options.size()
				_options[current_index].grab_focus()

Realized is_pressed is without brackets. Still a weird issue of looping though.

func _unhandled_key_input(event: InputEvent) -> void:
	if event.is_pressed and event is InputEventKey:
		match event.keycode:
			KEY_DOWN:
				if current_index == _options.size() -1:
					current_index = -1
				else:
					current_index += 1
					
				print("Current Index:", current_index)
				_options[current_index].grab_focus()
				
			KEY_UP:
				current_index = (current_index - 1 + _options.size()) % _options.size()
				_options[current_index].grab_focus()

Right now I have it set so the index is set to -1 when it reads a key down and is at the end of the array and it works but I don’t know why. It increments it twice before grabbing focus but only when I loop back around from the end of the array using ‘KEY DOWN’.

If I loop around with the ‘KEY UP’ it works as expected and it brings me to the end of the array.

I’ve simplified it more to get a sense of what is happening.

extends Button

func _ready():
	grab_focus()

I have the code above attached to the first button and then I can select the buttons using up and down keys. It will allow me to select nothing if I KEY UP past the first button in the list but I don’t know what it is selecting.

I don’t understand why you’re trying to change focus in code. Woudn’t it be easier to just set the button’s focus neighbors in the inspector?

1 Like

That’s just because I’m new with Godot and this way made sense to me.

Could you expand on your method?

Select a button and look for properties focus_neighbor_top and focus_neighbor_bottom in the inspector. Click the assign button and choose the buttons you should move to, when pressing up or down. You can also set focus_next and focus_previous to choose the next (TAB) and previous (SHIFT+TAB) buttons.

1 Like

Ah, that worked great.
There is still a small issue that I’m a little confused about that I solved by setting neighbour top to itself on the first button.

If I keep selecting up it will deselect the list entirely and if I try to print what the focus is on it won’t print anything.

Would you know why its able to deselect the list entirely but only if I’m iterating to the top of the VBox but it will stop when I get to the bottom?

If the focus neighbor hasn’t been assigned, the engine will try to find the next node automatically based on position. There’s probably a control node above the fight button with focus mode set to all. I don’t know, why it would lose focus entirely, though.

Anyway, if you set the fight button’s focus_neighbor_top to the run button, it should loop back down without any issues.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.