The task of this object is to capture input from the OIS library and then redistribute it to InputStates?.
As describes briefly in Input, the InputManager is the main object. Even though its tasks don't seem to be large, there is a large part of the code dealing with initialisation, destruction and reloading. This graphics is an extract from the one found in Input:
This class represents a container for InputHandlers? that actually do something. There is only one InputState that can be active at the same time for one device except for the master state. See below. The state objects are maintained by the InputManager and can therefore neither be created or destroyed on its own.
Let me explain the flow of input in an example:
When you press a button, OIS gets informed by the operating system and calls our InputManager. That can then, if necessary preprocess the input (e.g. for a joystick calibration) and send it to an InputState (the master input state is not considered in this explanation). If that input state doesn't handle input from keyboard, it gets handed over to another input state. The order is determined by hard coded priorities.
An InputState then redistributes (without modification) the input event to all registered InputHandlers. They finally process it and actually do something. More on that subject in the InputState article.
Why such a fuss?
When writing the InputManager I came across numerous problems when determining where to send the input. Consider a very simple example that involves a main menu with a GUI system, a console and the game level itself. Of course it would be very pleasant to allow the console to have priority whenever it is active. On the other hand, you might like to exit a level from the console and enter the main menu again. This operation should not change the target for keyboard input at all.
Now, why distinguishing between the input devices? Whenever an InputState discards input, it is handed over to the next in line (by priorities), but for each device separately. Consider the example from above: You are playing in a level and call the console. Would there be any reason not to use the mouse to steer the game in that instant? No. So you can. And that requires differentiation between devices when distributing input to the input states.
Tis is the easy part. Once the state is created and therefore registered in the InputManager, you can activate it by calling 'requestEnterState(state as string)' and deactivate it with 'requestLeaveState(state as string)'. Activation doesn't necessarily mean that the input gets sent there. The priority among the active states are still present.
The Master InputState
This state is always active after the InputManager has been created. It can be used to log input for instance if that is desired. The main purpose however is to reserve certain keys that always have a function, like the key to open the console. In order to realise that, a KeyBinder is used.
OIS makes it simple and raises an event for every pressed or released button or key and for every axis that has moved. However, sometimes it would be a lot easier to only handle the active state. For instance simple movements can be achieved by accelerating as long as the user holds a key. To realise that, the InputManager generates an event of its own: keyHeld. It gets raised every tick whenever a button or key is held. Be careful to consider that the tick frequency varies!
Initialisation, Destruction and Reloading
The InputManager initialises the OIS library and sets up some basic input states like a Detector to run-time detect key names in the console, a joystick calibrator, a master state (see above) and an empty state for internal reasons.
This all gets destroyed when destroying the InputManager. However: When destroying the InputStates?, the KeyHandlers? are NOT destroyed. It is the programmers task to do that in advance!
If you would like to connect a joystick during runtime, you need to reload OIS. The InputManager supports that with a call to 'reload()' which is executed as soon as the InputManager is not 'ticking' anymore. This accounts for possible problems when the reloading is caused by user input, which of course requires OIS to run…
This feature is not completed for an arbitrary number of joysticks. However, it works fine if you only have one Just type 'calibrate' in the ingame console and follow the instructions. The calibration is saved in a file to be used next start.