Navigating PopupMenu with keyboard

Godot Version

4.2.1

Question

Hello! Recently, I’ve been working on creating a grid based, turn based strategy game. A key feature is that players can select a unit, move them to a new tile, and select an action to perform. To meet this requirement, I’ve been using a PopupMenu node.
PopupMenu
From a functional standpoint, this has been a good choice. However, in addition to mouse controls (which the PopupMenu handles perfectly by default), I’d also like the game to be playable solely with the keyboard, using the player’s preferred keys bindings.

The menu can by default be navigated with the arrow keys, and the currently highlighted option can be selected with Enter. I’d like to make it so that, at the very least, Enter’s functionality can be mimicked by whatever key the player has bound to their “select/yes” option (“key_a” ) by default. Here, however, I run into trouble. The core of the menu’s script (attached to a control node with the PopupMenu as its child) is as follows:

func show_menu(unit, x, y, screen_position):
	emit_signal("lock_cursor_for_menu")
	print("menu open")
	new_x = x
	new_y = y
	selected_unit = unit
	var action_popup = $ActionPopup #The name of the popupMenu
	action_popup.set_position(Vector2(screen_position[2].x+24, screen_position[2].y))
	action_popup.popup() # Show the popup
	menu_showing = true

func _on_ActionPopup_id_pressed(id):
	menu_showing = false
	emit_signal("lock_cursor_for_menu")
	var playerArmyNode = get_node("../PlayerArmy")
	if id == 0: # Wait
		playerArmyNode.moving_unit = true
		selected_unit.move_unit(new_x, new_y)
	elif id == 1: # Cancel
		selected_unit.hide_move_range()
	selected_unit = null
	playerArmyNode.action_chosen = id
	print(id)
	print("menu closed")

Where show_menu makes the menu appear, and _on_ActionPopup_id_pressed is connected to the id_pressed signal of the popup menu. An intuitive approach was to create an _input function, that when the menu was open, would call _on_ActionPopup_id_pressed with the correct id, like so:

func _input(event):
        print("Input received!")
	if menu_showing:
		if event.is_action_pressed("key_a"): #Choose focused item
			_on_ActionPopup_id_pressed(highlighted_option) #highlighted option is a variable updated when a new id is focused
		elif event.is_action_pressed("key_s"): #cancel
			_on_ActionPopup_id_pressed(1)

However, this does not work, and the print statement’s output (or lack thereof) indicates that _input is simply not being called once the menu is opened. Trying _unhandled_input instead also fails, as for some reason _on_ActionPopup_id_pressed is immediately called with an ID of Null as soon as the menu is opened, instantly closing it. Is there a way to get my desired keyboard functionality with a PopupMenu, or should I pursue an alternative means of implementing a popup menu?
Incidentally, the “allow search” option is turned off for this menu, in order to avoid conflicts from letter keys (such as A) being bound to the “select/yes” command.
Thanks for the help!

As a follow up, I have resolved this issue by replacing the PopupMenu with a Panel and Buttons.

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