When creating the concept for input processing, we were left with two possibilities. The first and simpler one was to have an ID for every possible event. When you press a key, that event is fired and all listeners get informed. But as my colleague pointed out, this doesn't really scale since you have add new events over and over.
Instead he suggested to write a command interpreter that would parse a string and execute a command (CommandExecutor). Consequently this simplifies the KeyBinder by magnitudes: Every key can be assigned a string and whenever you press the key, the string gets executed. The obvious disadvantage is performance, but that has been dealt with preparsing so that the overhead gets minmal.
A quick how to
There is a built in ConsoleCommand named "keybind" which helps you assign the keys. Write 'keybind' followed by an arbitrary ConsoleCommand with arguments, hit enter and press the key you would like to assign it to. This also works for mouse and joystick axes. However you have to do some double work since those axes are split in half ones. For simple left-right movement for instance, this means you have to assign left movement to the left axis and vice versa.
One of the basic ideas was not to separate keys, buttons and axes from each other. Every such input 'trigger' should be able to fulfill the same functions. An axis should for instance be able to act as a simple button and any key or buttons has to have the ability to work like an axis. This essentially means that there have to be translation mechanisms.
Button and HalfAxis?
When looking from input side, every key, button or axis is a 'Button' in class design. An important mentioning is the splitting of an axis into two half axes. To clarify, consider a joy stick and imagine every direction to be binary instead of continuous.
The other end of input processing always ends in the execution of a command. There are two kinds of such commands: Binary or continuous. The latter involves an argument that tells 'how much', the other is simply 'whether or not'.
Obviously a half axis cannot simply act as button like that. The conversion however is rather simple: When the axis is moved more than a certain configurable threshold, it triggers the 'button'.
The other way round, when a buttons acts axis like, we simply interpret a pressed button as 1.0 and 0.0 otherwise.
This file governs the key bindings while playing. There might be more with different names to come, but currently, there is only one. Now every key, button or axis can be assigned an arbitrary number of commands. Usually it is only one, but I you never know…
Command separating is done with a "|"
In order to configure a command it has to be preceded by one of these non case sensitive tokens:
|OnPress?||Event gets fired when button is pressed|
|OnRelease?||Event gets fired when button is released|
|OnHold?||Event gets fired every tick if button is held down|
|ButtonThreshold? [0.0 - 1.0]||How much a half axis has to be moved to trigger a button like event|
|Scale [float]||Scales the output parameter (if any) by [float]. Useful for negative movements|
Some of these tokens might have no effect if used on an physical button/key.
keyA = OnPress Command1 param | OnRelease Command2 param keyB = OnHold Command3