This page is meant to track the design of the new keymapping (or rather, "input mapping" code). Right now, it only contains a copy of my original mail on the subject. This should be rewritten and updated with input from other people. Also the plan needs to be developed, e.g. a detailed proposal for the new API should be added.
Max' Email "RFC: Flexible keymapping via new EVENT_ (post 0.10)", June 4 2007
Recently a new event was added: EVENT_PREDICTIVE_DIALOG; Kostas
already informed us via an explanatory email about its purpose. Short
version of the story, this event can be used to tell the frontend
(i.e. the game engine) to show a special dialog, if desired/required.
However, I think this event is rather to special and to narrow in
scope. So I was thinking about this, and I came up with the following
idea, and I hope I'll get some helpful comments from you guys.
In short, I'd propose to replace EVENT_PREDICTIVE_DIALOG with a new
more generic event, by letting a frontend specify an arbitrary list
of actions which the backend should map to a button or hotkey. This
list would contain structs similar to this:
struct UserAction {
UserActionType type; // an enum type, see below
String description; // Human readable description, for a GUI keymapping config dialog
KeyDesc defaultKey; // an (optional) default key combo to be assigned to this; includes modifier state
// ... your idea goes here
};
The UserActionType might look like this:
enum UserActionType {
kQuitUserAction, // *maybe* could replace EVENT_QUIT
kPredictiveDialogUserAction,
kOptionsDialogUserAction,
kSaveLoadDialogUserAction,
kPauseUserAction,
...
kGenericUserAction
};
The backend then would use this information to map triggers to
actions; either by using the provided defaultKeys; or by using custom
hard mappings (based on the UserType, or on the currently running
game/engine); or by letting the user configure this via a trigger/
hotkey mapping dialog (that's what the "description" field is for); etc.
Then, whenever such a trigger occurs, instead of sending a regular
keyboard event, the backend generates the appropriate useraction
event (might be named EVENT_USERACTION). The goal here is to replace
EVENT_PREDICTIVE_DIALOG (and maybe EVENT_QUIT) with a more generic
and powerful setup. Oh, also hacks like "KEY_ALL_SKIP" could be
subsumed under this. And hopefully many other similar hacks, which
currently backends with few keys have to use to map their few input
triggers in a sensible way to the various actions our many engines
provide.
How to implement this, w/o too much effort? Well, the mapping code
would go into the EventManager. The default event manager would
simply use the specified defaultKey verbatim. Backend which want
enhanced mapping capabilities (e.g. to map PDA buttons to actions)
would have to use a custom event manager, but that shouldn't be a
major problem.
Over time, we could adapt our engines to register their standard
hotkeys/actions via the new API. E.g. in the SCUMM engine, at least
F5 (save/load) and space (pause) come immediately to mind, but many
more certainly would be desirable.
My hope is that by breaking this down into sensible small pieces, it
should be possible to implement this gradually and w/o too much
effort, w/o requiring backend authors to add extra code, unless they
want to; and finally, with minimal impact on engines (maybe the
handling of EVENT_QUIT has to be changed, but that'd be a no-
brainer). The gain would initial not be too big. Over time we'd
convert more and more engines to use it. My hope is that on the long
run it will allow us to get rid of many engine-specific hacks in
backends, will make user friendly key mapping dialog(s) possible, and
simply make it easier for us to add certain new features.
Current keymapper code could be used as a base, but only in
terms of initial GUI. In other areas it does not suit our needs. What
should be done there is this:
Each engine knows which keys is used by some particular game. I.e. there are
cases when different games supported by same engine require different
set of keys.
Additionally, some games need different keyboard layout at different parts of
the games. Good example is fights in Indy3.
Each backend knows which hardware keys exist on some particular device. And
again, some backends have support devices with different set of keys (WinCE,
Symbian).
Current approach is that in keymapper there are hardcoded gameids and predefined
set of keys. This is really really bad, since no backend code should
know about any
particular game or engine.
Thus, the appoach is this:
- Backend registers with keymapper and provides it list of hardware keys, and their preferred class of action (such as directions, functional keys)
- Game engine registers with keymapper and provides it set of keys which need to be mapped, along with their class, preferred mapping and priority. I.e. some keys are must to be present, and some are completely optional
- Then keymapper aligns these two list in attempt to "autoassign" keys. In most cases it will be based on preferred mapping provided by the engine.
- User can anytime open a dialog and remap any key. This should be stored in our global .ini file on per-game basis
There should be one global mapping, mainly for common keys such as directions,
mouse buttons, exit and save buttons. Again, it has to be editable by the users.
Also as I mentioned, there could be several mappings per game, and engine
provides them all at the game start, so user can alter all of them.
Also engine will notify the keymapper and request some particular map
to be activated. Additionally these keymaps should be possible to switch
both from GUI, or by a special key.