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!