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.