Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InputMap changes are not refreshed automatically #8

Closed
SpyrexDE opened this issue Mar 27, 2024 · 2 comments · Fixed by #9
Closed

InputMap changes are not refreshed automatically #8

SpyrexDE opened this issue Mar 27, 2024 · 2 comments · Fixed by #9
Assignees
Labels
enhancement New feature or request

Comments

@SpyrexDE
Copy link

When adding (InputMap.action_add_event) or removing (InputMap.action_erase_event) events from an input action, those changes are not reflected by the action prompt node. This is unfortunate for games that offer the user to remap actions to different buttons.

@Pennycook
Copy link
Owner

Thanks for reporting this. Would you mind providing a small reproducer project? I haven't ever implemented remapping (or any sort of updates to the InputMap via code).

From a quick look through the documentation, it doesn't seem as though InputMap has any sort of signal to let us detect when this sort of remapping happens. If we can't find a way to refresh things automatically, would calling something like an InputPrompts.refresh() function manually as part of your remapping code be an acceptable solution?

@Pennycook Pennycook added the enhancement New feature or request label Mar 28, 2024
@Pennycook Pennycook self-assigned this Mar 28, 2024
@SpyrexDE
Copy link
Author

Yes, I think in this case a globally accessible refresh function to refresh all action prompts would be the best solution.

It's just a quick sketch of how I figured out to make a remapping popup window but it works quite well for remapping actions separate for controller and keyboard/mouse as long it's just one event per device:

var awaiting_input_action: String = ""
var new_event: InputEvent = null


func remap_action(action: String):
	awaiting_input_action = action
	set_process_input(true) # Start processing inputs
	print("Press a new key or button for action: ", action)

func _input(event: InputEvent):
	if not awaiting_input_action:
		return

	if event.is_action("ui_cancel"):
		queue_free()
		return

	if event is InputEventKey or event is InputEventJoypadButton or event is InputEventMouseButton:
		new_event = event
		_apply_remap(awaiting_input_action, event)
		awaiting_input_action = ""
		set_process_input(false) # Stop processing inputs

func _apply_remap(action: String, event: InputEvent):
	var action_events = InputMap.action_get_events(action)
	var device_type = _get_device_type(event)

	for action_event in action_events:
		if _get_device_type(action_event) == device_type:
			InputMap.action_erase_event(action, action_event)
			print("Erased: " + action_event.as_text())
	
	InputMap.action_add_event(action, event)
	print("Action ", action, " remapped to ", event.as_text())
	
	# Here is where I would call InputPrompts.refresh()
	
	queue_free()

func _get_device_type(event: InputEvent) -> String:
	if event is InputEventKey or event is InputEventMouseButton:
		return "keyboard/mouse"
	elif event is InputEventJoypadButton or event is InputEventJoypadMotion:
		return "controller"
	return "unknown"

Pennycook added a commit that referenced this issue Mar 30, 2024
Calling the refresh() function of a specific prompt node forces it to
update its events and icons. Calling the refresh() function of the
PromptManager singleton refreshes all input prompts.

refresh() must be called whenever the events associated with an action
in the InputMap changes, because Godot does not provide an ability to
detect changes in the InputMap.

Closes #8.
Pennycook added a commit that referenced this issue Mar 31, 2024
Calling the refresh() function of a specific prompt node forces it to
update its events and icons. Calling the refresh() function of the
PromptManager singleton refreshes all input prompts.

refresh() must be called whenever there is a change in the event(s) associated
with an action in the InputMap, because Godot does not provide an ability to
detect changes in the InputMap.

Closes #8.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants