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

OS.get_keycode_string() returns empty string #84731

Open
warxander opened this issue Nov 10, 2023 · 5 comments · May be fixed by #84836
Open

OS.get_keycode_string() returns empty string #84731

warxander opened this issue Nov 10, 2023 · 5 comments · May be fixed by #84836

Comments

@warxander
Copy link

Godot version

v4.1.3.stable.official [f06b6836a]

System information

Godot v4.1.3.stable - Windows 10.0.22621 - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 4070 (NVIDIA; 31.0.15.4601) - AMD Ryzen 5 5600X 6-Core Processor (12 Threads)

Issue description

I'm trying to show an interaction hint in UI by getting InputEventKey from InputMap.

Code:

# var interact_event_key: := ...
print(interact_event_key)
print(OS.get_keycode_string(interact_event_key.keycode))

Output:

InputEventKey: keycode=69 (E), mods=none, physical=true, pressed=false, echo=false
<empty-string>

I expect OS.get_keycode_string() returns E in this particular example.

Steps to reproduce

Download reproduction project, run it, look at the Output.

Minimal reproduction project

os_get_keycode_string_bug.zip

@ananas030
Copy link

Try using event.physical_keycode instead of event.keycode. For me it works fine this way.

@jsjtxietian
Copy link
Contributor

It's because you set it as physical keycode in Input map, so the engine just store a None in keycode field ,and so it will print physical=true instead of false.

image

@akien-mga
Copy link
Member

Seems worth clarifying in the docs.

@BertrandBordage
Copy link

I also made the same assumption that InputEventKey would be giving equivalents between keycode and physical_keycode.

The solution is not to switch to non-physical keys (in most cases, you want the same physical layout regardless of the configured/printed keyboard layout).

The solution was actually written in the docs.

To get it from an action name (what most people want I guess), I use the following:

func get_key_name(action_name: String, event_index_in_action: int = 0) -> String:
    var event: InputEvent = InputMap.action_get_events(action_name)[event_index_in_action]
    if not (event is InputEventKey):
        return ""
    return OS.get_keycode_string(
        DisplayServer.keyboard_get_label_from_physical(
            event.physical_keycode
        )
    )

@hsandt
Copy link
Contributor

hsandt commented Jul 1, 2024

Thanks, it helped us head toward the right direction. On the issue you see just above, I found limitations when using this for:

  • default mappings defined e.g. in the Project Settings Input Map, where we can assign non-physical keycodes (as opposed to listening to input)
  • input with modifiers

Maaack found a solution for this in this PR:
https://github.com/Maaack/Godot-Game-Template/pull/105/files (check InputHelper.gd)

The full get_text method handles various cases including joystick, but since we're focused on key input I'll just copy the InputEventKey case below:

static func get_text(event : InputEvent) -> String:
	# ...
	elif event is InputEventKey:
		var keycode : Key = event.get_physical_keycode()
		if keycode:
			keycode = event.get_physical_keycode_with_modifiers()
		else:
			keycode = event.get_keycode_with_modifiers()
		keycode = DisplayServer.keyboard_get_keycode_from_physical(keycode)
		return OS.get_keycode_string(keycode)

(excerpt should be short enough to be used as a mere code sample, but if you need to copy more and worry about license, know that it's under MIT)

EDIT: Label keys are displayed properly, but Unicode keys are still invisible...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants