Input
Application Loop#
All input data is accessed via an ApplicationLoop (built via the factory's ApplicationLoopBuilder).
Every time the application loop is successfully iterated, the state of every input device (keyboard, mouse, gamepads) is updated.
Multiple loops and IterationShouldRefreshGlobalInputStates
When creating an ApplicationLoop with the builder you can pass a config object and set IterationShouldRefreshGlobalInputStates to false.
By default this property is true, but if set to false iterating the application loop will not update input states.
The purpose of this is to allow using multiple loops for setting different 'tick rates' for different parts/functions in your application whilst having only one loop globally update the input state of the system.
Because input state is system/environment-wide, whenever any one loop iterates and updates the global input state that state will be updated/changed for every loop's Input view.
The Input property on the loop returns an ILatestInputRetriever. As its name implies, this object provides an API for accessing the latest user input events & state since the last application loop iteration:
-
UserQuitRequested -
Will be
trueif the user has requested the application exits in this iteration.Typically users will request a quit via the window's close button or key combination (e.g. Alt+F4 on Windows).
-
KeyboardAndMouse -
Returns an
ILatestKeyboardAndMouseInputRetrieverthat is used to access keyboard & mouse input updates.See below for usage guide.
-
GameControllers -
Returns a TypedReferentIterator of
ILatestGameControllerInputStateRetrievers. EachILatestGameControllerInputStateRetrievercan be used to access input updates for one connected game controller.See below for usage guide.
-
GameControllersCombined -
Returns an
ILatestGameControllerInputStateRetrieverthat represents an amalgam of all updates from every connected game controller this iteration.The main purpose of
GameControllersCombinedis to allow you to simply support anyone using your application to connect any controller and begin using it, without having to worry about configuring the "correct" controller.If no controllers are currently connected to the system, this property is still valid and the returned state retriever will simply have no state updates set. When the user connects a new controller, this property automatically incorporates its updates seamlessly.
See below for usage guide.
The instance returned by loop.Input is the same one every time, which means you can hold on to the same ILatestInputRetriever reference indefinitely and as long as the ApplicationLoop it came from is not disposed, the instance will remain valid and can be used to always access input data for the current frame.
The same lifetime and usage pattern applies to all members of the ILatestInputRetriever, including the ILatestKeyboardAndMouseInputRetriever returned via the KeyboardAndMouse property and the ILatestGameControllerInputStateRetriever returned by the GameControllers/GameControllersCombined properties.
The reason these interfaces are named as input retrievers should hopefully now be apparent: They help you retrieve the latest input from the application loop. They do not "contain" or "snapshot" input state.
Keyboard & Mouse#
KeyboardOrMouseKey Enum#
This enum contains every keyboard key and mouse button supported by TinyFFR.
Why combined on one enum?
Where possible, the ILatestKeyboardAndMouseInputRetriever interface does not separate its API between keyboard keys and mouse buttons; opting instead to attempt to unify the way you consume events for both.
This choice was made in order to make it easier to swap/interoperate between bindings for both device types. For example, if you wish to let your users configure their control bindings, a user can now rebind a keyboard key to a mouse click and there's no difference for you in how that's handled in this API.
If you wish to differentiate between keyboard and mouse events you can use the GetCategory() extension method described below.
Extension Methods#
There are some extension methods defined on KeyboardOrMouseKey as follows:
-
GetNumericValue() -
Returns an
int?indicating the numeric value of the key (e.g.3for the NumberRow3 or Numpad3 keys).If the given key has no numeric representation, this method returns
nullinstead.You can also reverse this method (i.e. convert an
intto aKeyboardOrMouseKey) using the static methodInputUtils.KeyFromNumericValue(). -
GetCharacterValue() -
Returns a
char?indicating the character value of the key (e.g.'A'for the A key,' 'for Space, etc).If the given key has no character representation, this method returns
nullinstead.You can also reverse this method (i.e. convert a
charto aKeyboardOrMouseKey) using the static methodInputUtils.KeyFromCharacterValue(). -
GetCategory() -
Returns a
KeyboardOrMouseKeyCategoryindicating the 'category' of the key (see below for more information on the available categories).
KeyboardOrMouseKeyCategory Enum#
- Alphabetic Represents keyboard keys A through Z.
- NumberRow Represents keyboard keys on the top number row (1, 2, 3, 4, 5, 6, 7, 8, 9, 0).
- Numpad Represents all keyboard keys on the number pad (also known as the keypad), usually to the right of the main keyboard layout.
- PunctuationAndSymbols Represents all keyboard keys that are symbols or punctuation (including space).
- Modifier Represents control, alt, and shift (left and right) keyboard keys.
- Function Represents the F-row keys, typically located at the top of the keyboard.
- Arrow Represents the four arrow keyboard keys (left, right, up, down).
- EditingAndNavigation Represents the six text/page navigation/editing keyboard keys (insert, delete, home, end, page up, page down), usually found above the arrow keys.
- Control Represents the common system/application control keyboard keys (such as escape, return, caps lock, tab, backspace, etc).
- Mouse Represents all mouse buttons.
- Other Represents buttons that are not contained in any other category.
MouseKey Enum#
The MouseKey enum is a subset of the KeyboardOrMouseKey enum that contains only mouse "keys" (i.e. buttons). This enum is only really used for MouseClickEvents; you shouldn't use it anywhere else.
You can convert a MouseKey to a KeyboardOrMouseKey by using the ToKeyboardOrMouseKey() extension method.
ILatestKeyboardAndMouseInputRetriever#
The ILatestKeyboardAndMouseInputRetriever interface (accessed via the KeyboardAndMouse property) is how you can access keyboard and mouse input updates. It provides the following members:
-
NewKeyEvents -
This returns a TypedReferentIterator of
KeyboardOrMouseKeyEvents that enumerates all the new mouse/keyboard events in this loop iteration.Each
KeyboardOrMouseKeyEventcontains two properties:- A
KeyDownbool indicating whether this event is for a key being pressed (true) or released (false); - A
Keywhich is theKeyboardOrMouseKeythat is being pressed or released.
If there are no input updates this loop iteration, this iterator will be empty (0
Count). - A
-
NewKeyDownEvents -
This returns a TypedReferentIterator of
KeyboardOrMouseKeys that enumerates every key that was pressed in this loop iteration.If you only care about keys being pressed, not released, you can use this property to quickly iterate every new key press.
This property returns exactly the same set of keys as you'd get iterating through
NewKeyEventsand filtering for events whereKeyDownistrue.If no keys were pressed this loop iteration, this iterator will be empty (0
Count). -
NewKeyUpEvents -
This returns a TypedReferentIterator of
KeyboardOrMouseKeys that enumerates every key that was released in this loop iteration.If you only care about keys being released, not pressed, you can use this property to quickly iterate every new key release.
This property returns exactly the same set of keys as you'd get iterating through
NewKeyEventsand filtering for events whereKeyDownisfalse.If no keys were released this loop iteration, this iterator will be empty (0
Count). -
CurrentlyPressedKeys -
This returns a TypedReferentIterator of
KeyboardOrMouseKeys that enumerates every key that is currently being pressed/held-down by the user.Note that this is not the same as
NewKeyDownEventsas this iterator enumerates keys that were pressed in previous loop iterations but are still being pressed/held-down in this iteration.If no keys are currently being pressed in this loop iteration, this iterator will be empty (0
Count). -
NewMouseClicks -
This returns a TypedReferentIterator of
MouseClickEvents that enumerates a list of events detailing every mouse 'click' since the last loop iteration.Mouse clicks are "duplicated" in all the other properties (i.e. they count as
CurrentlyPressedKeysand they emit keyup/keydown events). However, this iterator provides additional mouse-specific details for each mouse click.Each
MouseClickEventcontains the following properties:- Location: An
XYPair<int>indicating the pixel position of the cursor relative to the window when the click was made; - MouseKey: Which key was clicked;
- ConsecutiveClickCount: The number of consecutive clicks made with this button. For example, if this value is '2', this click can be considered a "double-click" operation. The timing of what makes a click "consecutive" is defined by the operating system.
If no mouse buttons have been clicked in this loop iteration, this iterator will be empty (0
Count). - Location: An
-
MouseCursorPosition -
This returns an
XYPair<int>indicating which pixel the cursor is currently in relative to the window bounds.(0, 0)is the top-left corner of the window. -
MouseCursorDelta -
This returns an
XYPair<int>indicating how many pixels the cursor moved this loop iteration.This value will be set even if the cursor is locked to the window, meaning you can use it to determine the user's mouse movements even though the cursor itself does not move.
-
MouseScrollWheelDelta -
This returns an
intindicating how many 'stops' the scroll wheel has moved this loop iteration.Positive values indicate scrolling down, negative for up.
-
KeyIsCurrentlyDown(KeyboardOrMouseKey key) -
This convenience method lets you quickly know whether a specific key is currently being pressed/held-down.
-
KeyWasPressedThisIteration(KeyboardOrMouseKey key) -
This convenience method lets you quickly know whether a specific key was pressed this loop iteration.
-
KeyWasReleasedThisIteration(KeyboardOrMouseKey key) -
This convenience method lets you quickly know whether a specific key was released this loop iteration.
Game Controller#
GameControllerButton Enum#
This enum contains every supported game controller button. It also includes LeftTrigger and RightTrigger; although these are not technically buttons the API will emit events for them when they're pressed past a certain threshold.
ILatestGameControllerInputStateRetriever#
The ILatestGameControllerInputStateRetriever interface (accessed via the GameControllers or GameControllersCombined properties) is how you can access gamepad updates. It provides the following members:
-
LeftStickPosition -
This returns a
GameControllerStickPositionindicating the current position of the left analog stick.See below for more information about using this value.
-
RightStickPosition -
This returns a
GameControllerStickPositionindicating the current position of the right analog stick.See below for more information about using this value.
-
RightTriggerPosition -
This returns a
GameControllerTriggerPositionindicating the current position of the right trigger.See below for more information about using this value.
-
LeftTriggerPosition -
This returns a
GameControllerTriggerPositionindicating the current position of the left trigger.See below for more information about using this value.
-
RightTriggerPosition -
This returns a
GameControllerTriggerPositionindicating the current position of the right trigger.See below for more information about using this value.
-
NewButtonEvents -
This returns a TypedReferentIterator of
GameControllerButtonEvents that enumerates all the new button events in this loop iteration.Each
GameControllerButtonEventcontains two properties:- A
ButtonDownbool indicating whether this event is for a button being pressed (true) or released (false); - A
Buttonwhich is theGameControllerButtonthat is being pressed or released.
If there are no input updates this loop iteration, this iterator will be empty (0
Count). - A
-
NewButtonDownEvents -
This returns a TypedReferentIterator of
GameControllerButtons that enumerates every button that was pressed in this loop iteration.(1)- Unfortunately this property does not inform you about new formal-dress parties in your area.
If you only care about buttons being pressed, not released, you can use this property to quickly iterate every new button press.
This property returns exactly the same set of button as you'd get iterating through
NewButtonEventsand filtering for events whereButtonDownistrue.If no buttons were pressed this loop iteration, this iterator will be empty (0
Count). -
NewButtonUpEvents -
This returns a TypedReferentIterator of
GameControllerButtons that enumerates every button that was released in this loop iteration.If you only care about buttons being released, not pressed, you can use this property to quickly iterate every new button release.
This property returns exactly the same set of buttons as you'd get iterating through
NewButtonEventsand filtering for events whereButtonDownisfalse.If no buttons were released this loop iteration, this iterator will be empty (0
Count). -
CurrentlyPressedButtons -
This returns a TypedReferentIterator of
GameControllerButtons that enumerates every button that is currently being pressed/held-down by the user.Note that this is not the same as
NewButtonDownEventsas this iterator enumerates buttons that were pressed in previous loop iterations but are still being pressed/held-down in this iteration.If no buttons are currently being pressed in this loop iteration, this iterator will be empty (0
Count). -
ButtonIsCurrentlyDown(GameControllerButton button) -
This convenience method lets you quickly know whether a specific button is currently being pressed/held-down.
-
ButtonWasPressedThisIteration(GameControllerButton button) -
This convenience method lets you quickly know whether a specific button was pressed this loop iteration.
-
ButtonWasReleasedThisIteration(GameControllerButton button) -
This convenience method lets you quickly know whether a specific button was released this loop iteration.
GameControllerStickPosition Struct#
When using the LeftStickPosition or RightStickPosition property on an ILatestGameControllerInputStateRetriever you will be returned a GameControllerStickPosition with the following members:
-
Displacement -
This returns a
floatin the range0fto1f, indicating how far the stick is currently moved away from its centre position in any direction.A value of
1findicates fully moved away from the centre; a value of0findicates the stick is centered (both vertically and horizontally). -
DisplacementHorizontal -
This returns a
floatin the range1fto-1f, indicating how far the stick is currently moved horizontally.A value of
1findicates fully moved to the right; a value of-1findicates fully moved to the left; a value of0findicates the stick is centered horizontally.You will only see a value of
1f/-1fwhen the stick is pushed hard to the left/right, not in a diagonal position.A value of
0findicates that there is no horizontal displacement, but not necessarily that the stick is in its centre position- it may be pushed up or down. -
DisplacementVertical -
This returns a
floatin the range1fto-1f, indicating how far the stick is currently moved vertically.A value of
1findicates fully moved to the top; a value of-1findicates fully moved to the bottom; a value of0findicates the stick is centered vertically.You will only see a value of
1f/-1fwhen the stick is pushed hard to the top/bottom, not in a diagonal position.A value of
0findicates that there is no vertical displacement, but not necessarily that the stick is in its centre position- it may be pushed left or right. -
DisplacementLevel -
This returns an
AnalogDisplacementLevelenum value that can be used to quickly determine the rough level of displacement. See below for the possible values. -
DisplacementLevelHorizontal -
This returns an
AnalogDisplacementLevelenum value that can be used to quickly determine the rough level of horizontal displacement. See below for the possible values. -
DisplacementLevelVertical -
This returns an
AnalogDisplacementLevelenum value that can be used to quickly determine the rough level of vertical displacement. See below for the possible values. -
IsOutsideDeadzone() -
Returns
trueorfalsedepending on whether theDisplacementis outside a deadzone.This method takes an optional parameter allowing you to set the size of the deadzone from
0fto1f. If not specified, the default recommended size will be used. -
IsOutsideDeadzoneVertical() -
Returns
trueorfalsedepending on whether theDisplacementVerticalis outside a deadzone.This method takes an optional parameter allowing you to set the size of the deadzone from
0fto1f. If not specified, the default recommended size will be used. -
IsOutsideDeadzoneHorizontal() -
Returns
trueorfalsedepending on whether theDisplacementHorizontalis outside a deadzone.This method takes an optional parameter allowing you to set the size of the deadzone from
0fto1f. If not specified, the default recommended size will be used. -
GetDisplacementWithDeadzone() -
Returns
Displacementadjusted according to a deadzone.If
Displacementis below the deadzone value this method returns0f. Otherwise, it returns a value from0fto1fwhich isDisplacementrescaled to the remaining non-deadzone area (e.g. if the deadzone is0.2fandDisplacementis0.6f, this method will return0.5f, indicating the displacement is half way between the deadzone and the max value.)This method takes an optional parameter allowing you to set the size of the deadzone from
0fto1f. If not specified, the default recommended size will be used. -
GetDisplacementVerticalWithDeadzone() -
Returns
DisplacementVerticaladjusted according to a deadzone.If
DisplacementVerticalis below the deadzone value this method returns0f. Otherwise, it returns a value from0fto1fwhich isDisplacementVerticalrescaled to the remaining non-deadzone area (e.g. if the deadzone is0.2fandDisplacementVerticalis0.6f, this method will return0.5f, indicating the displacement is half way between the deadzone and the max value.)This method takes an optional parameter allowing you to set the size of the deadzone from
0fto1f. If not specified, the default recommended size will be used. -
GetDisplacementHorizontalWithDeadzone() -
Returns
DisplacementHorizontaladjusted according to a deadzone.If
DisplacementHorizontalis below the deadzone value this method returns0f. Otherwise, it returns a value from0fto1fwhich isDisplacementHorizontalrescaled to the remaining non-deadzone area (e.g. if the deadzone is0.2fandDisplacementHorizontalis0.6f, this method will return0.5f, indicating the displacement is half way between the deadzone and the max value.)This method takes an optional parameter allowing you to set the size of the deadzone from
0fto1f. If not specified, the default recommended size will be used. -
AsXYPair() -
Returns an
XYPair<float>containingGetDisplacementHorizontalWithDeadzone()asXandGetDisplacementVerticalWithDeadzone()asY.This method takes an optional parameter allowing you to set the size of the deadzone from
0fto1f. If not specified, the default recommended size will be used. -
GetPolarAngle() -
Returns an
Angle?indicating which direction the stick is being pushed towards, ornullif the stick is within the deadzone.A value of
0°indicates the stick is being pushed exactly to the right;90°to the top;180°to the left;270°to the bottom. This follows the polar co-ordinate / unit circle convention.This method takes an optional parameter allowing you to set the size of the deadzone from
0fto1f. If not specified, the default recommended size will be used. -
GetOrientation() -
Returns an
Orientation2Denum value indicating which way the stick is being pushed.If
Displacementis within the deadzone, returnsOrientation2D.None.This method takes an optional parameter allowing you to set the size of the deadzone from
0fto1f. If not specified, the default recommended size will be used. -
GetVerticalOrientation() -
Returns a
VerticalOrientation2Denum value indicating which way the stick is being pushed along the up/down axis.If
DisplacementVerticalis within the deadzone, returnsVerticalOrientation2D.None.This method takes an optional parameter allowing you to set the size of the deadzone from
0fto1f. If not specified, the default recommended size will be used. -
GetHorizontalOrientation() -
Returns a
HorizontalOrientation2Denum value indicating which way the stick is being pushed along the left/right axis.If
DisplacementHorizontalis within the deadzone, returnsHorizontalOrientation2D.None.This method takes an optional parameter allowing you to set the size of the deadzone from
0fto1f. If not specified, the default recommended size will be used. -
GetRawDisplacementValues(out short horizontal, out short vertical) -
The raw input API used by TinyFFR emits controller data as two signed 16-bit values, one each for the horizontal and vertical axes.
If you wish to bypass TinyFFR's abstractions and use these values directly, this method allows you to do that.
These are the values reported by SDL, specifically SDL_ControllerAxisEvent.
GameControllerTriggerPosition Struct#
-
Displacement -
This returns a
floatin the range0fto1f, indicating how far the trigger has been pulled.A value of
1findicates fully squeezed down; a value of0findicates the trigger is in its default un-pulled state. -
DisplacementLevel -
This returns an
AnalogDisplacementLevelenum value that can be used to quickly determine the rough level of displacement. See below for the possible values. -
GetDisplacementWithDeadzone() -
Returns
Displacementadjusted according to a deadzone.If
Displacementis below the deadzone value this method returns0f. Otherwise, it returns a value from0fto1fwhich isDisplacementrescaled to the remaining non-deadzone area (e.g. if the deadzone is0.2fandDisplacementis0.6f, this method will return0.5f, indicating the displacement is half way between the deadzone and the max value.)This method takes an optional parameter allowing you to set the size of the deadzone from
0fto1f. If not specified, the default recommended size will be used. -
GetRawDisplacementValue() -
The raw input API used by TinyFFR emits the trigger displacement value as a signed 16-bit integer.
If you wish to bypass TinyFFR's abstractions and use this value directly, this method allows you to do that.
This is the value reported by SDL, specifically SDL_ControllerAxisEvent.
AnalogDisplacementLevel Enum#
Some gamepad events will let you quantize the level a trigger is squeezed to an AnalogDisplacementLevel. This can be useful if you want to quickly differentiate logic depending how far a user has squeezed the trigger to a few different levels:
-
Full Indicates a trigger has been squeezed more than 75% of its max travel distance.
-
Moderate Indicates a trigger has been squeezed between 40% and 75% of its max travel distance.
-
Slight Indicates a trigger has been squeezed between 15% and 40% of its max travel distance.
-
None Indicates a trigger has been squeezed less than 15% of is max travel distance.(1)
- The reason this is 15% and below (rather than 0%) is to incorporate a small natural deadzone.