Is There an Inverse of InputEvent.as_text? I.e., InputEvent.from_text?

Godot Version

4.5

Question

I see that I can convert an InputEvent to a text string via as_text. Is there a way to do the reverse, converting the text back to an InputEvent?

I see solutions where you write your own function that does this. Why isn’t it supported by default?

The reason it matters is that, after the user updates the input mapping, I need some way to save it to/from a string?

InputEvent.as_text() is just a way to humanize the input event as a string. You shouldn’t be using this when saving/loading input events.

You can check how to do it in the following demo:

1 Like

This is how I do it: dragonforge-controller/addons/dragonforge_controller/controller.gd at main · dragonforge-dev/dragonforge-controller · GitHub

Here’s the relevant code. The file linked above is the full file, which is part of an addon I created to handle a bunch of input things.

## For saving and loading the input map.
var _action_list: ActionList


## Loads any custom keybindings from disk and applies them to the InputMap.
func _ready() -> void:
	_action_list = ActionList.load_or_create()
	for action_name in _action_list.action_events:
		for event_name in _action_list.action_events[action_name]:
			_set_binding(action_name, _action_list.action_events[action_name][event_name])
	restore_default_keybindings.connect(_on_restore_default_keybindings)


## Sets the passed event for the given action in the InputMap and saves it to
## disk for loading the next time the game is loaded.
func rebind_action(action: String, event: InputEvent) -> void:
	_set_binding(action, event)
	_save_binding(action, event)


## Sets the passed event for the given action in the InputMap for the game.
## This can result in either an additional option or overriding of an existing 
## option.
##
## (E.G. if the action "move_up" was only mapped to the `W` key, passing in an
## InputEventKey event which presses the Up Arrow would overwrite the entry.
## However passing an InputEventJoypadMovementEvent of the left stick being
## moved up would add a new event.)
func _set_binding(action_to_remap: String, event: InputEvent) -> void:
	var events = InputMap.action_get_events(action_to_remap)
	for existing_event in events:
		if existing_event.get_class() == event.get_class():
			InputMap.action_erase_event(action_to_remap, existing_event)
			break
	InputMap.action_add_event(action_to_remap, event)


## Saves on disk the passed event for the passed action.
func _save_binding(action_name: String, event: InputEvent) -> void:
	var action: Dictionary
	if _action_list.action_events.has(action_name):
		action = _action_list.action_events[action_name]
	action[event_to_string(event)] = event
	_action_list.action_events[action_name] = action
	_action_list.save()


## Deletes the keybindings.tres file, resets the action_list variable
## to a default of empty, and then reloads all the settings the developer
## set in the inital game.
func _on_restore_default_keybindings() -> void:
	_action_list.delete()
	_action_list = ActionList.load_or_create()
	InputMap.load_from_project_settings()
1 Like