Open main menu

Keymapping Improvements

Revision as of 21:10, 30 March 2008 by Sev (talk | contribs) (Rant on mapper)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

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.

Eugene's comment on keymapper task

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:

  1. Backend registers with keymapper and provides it list of hardware keys, and their preferred class of action (such as directions, functional keys)
  2. 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
  3. 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.
  4. 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.