Getting multiple InputMap events?

Godot Version

v4.6 Stable

Question

I must be doing something wrong because I’m getting both InputEvents happening.

Here’s my Input Map:

Here’s my func:

var is_in_valid_slot = true
func _input(event: InputEvent) -> void:
	if event.is_action_pressed("drop_stack") and is_in_valid_slot:
		InventoryManager.trash_stack()
		return
	if event.is_action_pressed("drop_item") and is_in_valid_slot:
		InventoryManager.trash_single_item()

Both ‘trash’ functions just do print() statements for now: “trashing item” and “trashing stack”

The problem is that both events process unless I use the “return” statement shown in my code above.

But then, if I do this:

func _input(event: InputEvent) -> void:
	var is_in_valid_slot = true
	if event.is_action_pressed("drop_item") and is_in_valid_slot:
		InventoryManager.trash_single_item()
	elif event.is_action_pressed("drop_stack") and is_in_valid_slot:
		InventoryManager.trash_stack()

I also get both events happening (and both print statements).

It works however, if I reverse the order:

func _input(event: InputEvent) -> void:
	if event.is_action_pressed("drop_stack") and is_in_valid_slot:
		InventoryManager.trash_stack()
	elif event.is_action_pressed("drop_item") and is_in_valid_slot:
		InventoryManager.trash_single_item()

Now, this means that I must always process the input in a specific order for it to work, with modified keys coming first. This seems kinda crazy.

It seems as though with both keys held down (shift+backspace) both events are firing - right? if so, this seems kinda wrong - shouldn’t the modifier key override the single key and act a single event?

So there must be a proper way to handle this kind of input??

If it did, I don’t see how shift to run would work in games unless developers specify all four walk inputs and run inputs with shift held. Pressing shift would nullify any unmapped inputs so similarly I’d have to map actions for E to interact and Shift+E to interact while sprinting in this example.


It is consistent with any other precedence comparison, the input Shift+Backspace does contain Backspace so if you check if backspace first it will always fire, but if shift and backspace should be of higher precedence.

Just consume the event when you process it and it won’t propagate it.

func _input(event: InputEvent) -> void:
	if event.is_action_pressed("drop_stack") and is_in_valid_slot:
		InventoryManager.trash_stack()
		get_tree().set_input_as_handled()
	if event.is_action_pressed("drop_item") and is_in_valid_slot:
		InventoryManager.trash_single_item()
get_tree().set_input_as_handled()

Throws an error.

I might as well use “return” - right?

What error does it throw?

And sure, you can not handle the input, as long as you don’t use anything else with Backspace.

It’s really get_viewport().set_input_as_handled() but that only affects events passed in _unhandled_input, and I don’t believe it’s creating multiple inputs that need to be handled, just one that can be interpreted in multiple ways.

I guess I thought specifying ‘shift+backspace’ in the inputMap would behave differently and allow a certain ‘ignorance’ of the precendence.

If I allow a user to remap the keys, and the use a modifier where I did not, then how would you handle that precedence in code?

e.g. What if they reverse my defaults and ‘remove item’ becomes ‘shift+backspace’
and ‘remove stack’ becomes ‘backspace’ - what happens to my hard-coded precendence?

error:

E 0:00:04:603 ItemSlot._input: Invalid call. Nonexistent function ‘set_input_as_handled’ in base ‘SceneTree’.
item_slot.gd:73 @ ItemSlot._input()
item_slot.gd:73 @ _input()

Turns out my code was wrong, it’s get_tree().get_root().set_input_as_handled(); but I have a better solution for you.

func _input(event: InputEvent) -> void:
	if event.is_action_pressed("drop_stack", false, true) and is_in_valid_slot:
		InventoryManager.trash_stack()
	elif event.is_action_pressed("drop_item", false, true) and is_in_valid_slot:
		InventoryManager.trash_single_item()

The false leaves the echo setting at default, and true is for exact_match. This should solve your problem even if you allow remapping with Shift.

1 Like

Yes!

Adding values for echo and match works perfectly.
And it works if I remap without affecting the code - I don’t have to reorder my statements.

Keep track of mappings hard-coded seemed insane - this solution makes sense.

Thanks!

2 Likes

If that solution worked for you, please mark it as the solution for people coming after you with the same question.