So this is probably more of a pygame question, but I guess it belongs here because the keymap in Ren'Py is borrowed from it.
I am working on a way to let the user change some shortcuts dynamically, in the spirit of this question.
I am this close to making it work, but I am missing one final piece of the puzzle: How to turn the user input into a proper key code (the ones that start with 'K_').
Basically I'm using pygame to detect an event key which returns a number, and I can then turn it into a string using pygame.key.name.
However, this key is not a usable key code by itself, I can make it work for simple cases using a bit of string manipulation, but for complex cases such as keypad keys or symbols like * or ?, it breaks down.
Is there a way to detect the actual key_code so that I can hand it to Ren'Py?
Here is a complete example. You can try it for yourself and see which keys are failing:
Code: Select all
init python:
import pygame
def bind_key(target, old_key="", key=""):
# Currently keys like +, ?, * fail
if not getattr(pygame.locals, key, False):
renpy.notify(key + " is not valid")
return False
for event, binding in config.keymap.items():
remove_list = []
for k in binding:
if event == target:
if old_key and k.endswith(old_key):
remove_list.append(k)
else:
if k.endswith(key):
remove_list.append(k)
renpy.notify(k + " no longer used for " + event)
for k in remove_list:
binding.remove(k)
config.keymap[target].append(key)
renpy.clear_keymap_cache()
return True
def catch_key():
while True:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
key = pygame.key.name(event.key).decode("utf-8")
# The following is an attempt to manually set up the pygame key code: Not ideal!
if len(key) == 1:
return key.lower()
return key.upper()
# The game starts here.
label start:
"'H' hides the UI."
$ bind_key("hide_windows", "K_h", "K_f")
"Now 'F' hides the UI!"
$ bind_key("hide_windows", "K_f", "K_h")
$ bind_key("toggle_fullscreen", key="K_f")
"Back to normal."
label key_loop:
"Now enter any key.{nw}"
$ next = catch_key()
# This lets you test the keys and see which ones fail
if bind_key("hide_windows", "K_h", "K_" + next):
"[next] now hides the window."
else:
"[next] doesn't work as a shortcut. This may be a problem."
jump key_loop