Carbonite Input Plugin#
Overview#
Carbonite input plugin acts like an input hub, the goal is to make it easy for the input providers to register input devices and events in the input plugin and input users to consume input events or states, abstracting away the underlying mechanisms.
Input users#
Any plugin or client that only cares about consuming the inputs are called input users. Input could be consumed either
by registering event listeners or directly polling the input state. Input users should use the
carb::input::IInput interface.
The main idea behind the user interface design is to unify discrete and analog controls, and assign any type of controls to the user-specified action mapping. More information about the specifics of such unification is presented in the [Values] and [Button flags] sections, and how to set up a user-specified action mapping is described in the [Action mapping] section.
Input states#
Alternatively, it is possible to poll the input device state using functions like
carb::input::IInput::getKeyboardValue and carb::input::IInput::getKeyboardButtonFlags.
Similar functions are present for mouse and gamepad input devices. The difference between get*Value and
get*ButtonFlags functions is in how the device button states are treated, and the reasoning behind having two types
of interpretations of the same underlying input states is allowing the user to assign any kind of input state, whether
it is discrete or analog, to the specific actions. For example, this approach allows to interpret gamepad analog stick
as D-pad, assigning discrete actions to analog controls–e.g. analog stick driven up or trigger pressed above specified
threshold, can trigger a certain menu to pop up. This works as well if a user wants to move a slider for a determined
amount when a discrete keyboard key is pressed.
It is important to note, that there are two input states mapped to any single axis–negative and positive, e.g.
carb::input::MouseInput::eMoveLeft / carb::input::MouseInput::eMoveRight corresponding to mouse
move on the X axis, or GamepadInput::eLeftStickLeft / GamepadInput::eLeftStickRight
corresponding to the same axis of a left gamepad stick–this is done for consistency and finer action mapping control;
user can set up one actions on the negative stick/mouse axis move and a different one for the positive stick/mouse axis
move, thus effectively turning them into d-pads. Or allow to rebind camera pitch and yaw control to the keyboard keys.
Values#
The get*Value functions return floating point numbers representing the current button state–for discrete device inputs
(like keyboard keys, mouse or gamepad buttons) it is either 0.0 or 1.0, and for analog inputs (e.g. mouse axes or
gamepad sticks) the returned number can take values between 0.0 and 1.0.
Frames#
carb.input transfers the current state to a previous state in the update*() functions: carb::input::InputProvider::updateKeyboard,
carb::input::InputProvider::updateMouse and carb::input::InputProvider::updateGamepad. When these
functions are called it is considered the beginning of the next frame of the device.
Input events#
carb::input::IInput interface provides ways to subscribe and unsubscribe to the input event streams with
functions like carb::input::IInput::subscribeToKeyboardEvents /
carb::input::IInput::unsubscribeToKeyboardEvents (similar events present for mouse and gamepads).
Action mapping#
User interface for the input plugin allows to assign any kind of device input to a named action. Each named action can
have several device inputs assigned to it. Actions support both state polling and event subscription, similar to the
regular device inputs: carb::input::IInput::getActionValue returns floating point value for the named
action, carb::input::IInput::getActionButtonFlags returns discrete button flag, and
carb::input::IInput::subscribeToActionEvents /
carb::input::IInput::unsubscribeToActionEvents allow to manage named action event stream subscriptions.
In case when several inputs are assigned, a prioritizing logic determines the exact action value or flag. Typically, when queried for the continuous action value, maximum absolute value of the assigned inputs is determined–i.e. if two axes of different sticks are assigned to the same action, the stick with maximum deviation from the initial state is prioritized. Alternatively, when queried for the discrete action flag, the following logic determines the prioritized button flag (in the order of decreasing priority):
The device input is “held” for some time.
The device input was just “pressed”.
The device input was just “released”.
The device input is in idle state.
This list of priorities for the button flag was designed to make sure that different device inputs assigned to the same action do not conflict with each other–for example if two inputs assigned to the same action were “held”, and then one of the inputs gets released, the action is not interrupted.
NOTE: the prioritization logic described is only a recommendation for the input plugin implementation, and is true for the default Carbonite input plugin (carb.input.plugin). Other input plugin implementations may implement different logic to determine action flags or values.
Input providers#
Plugins that aim to feed the input events and states use carb::input::InputProvider interface.