Binding
Every action can have zero or more bindings per user. If an action has multiple bindings they will be combined according to the action type. If action has zero bindings the action is marked as inactive
letting the application know that it will not be used. The application can use the inactive
value to enable / disable features such as aim assist (if a Delta2D Turn
action is bound) or quick time events (if a quick time event key is unbound).
Input Components are bound to Input Actions using bindings. Bindings can be very simple, such as directly binding a Button component to a Boolean action. But they can also be complex, like binding a Scroll Wheel to that same Boolean action or binding Gyro Motion to Delta2D.
Binding types (WIP)¶
Instead of creating 'one binding abstraction to rule them all' SuInput uses a system that allows multiple 'binding engines' to work together. As the binding system is the most complex part of SuInput it is almost impossible to cover every scenario with one monolithic system. For example it would be challenging to bend the default engine to allow input from MIDI devices.
Default Engine¶
The default engine covers all the conversions listed in Input Component Types and should be enough for most use cases. While I believe it offers a better alternative to many other binding engines, it still has a few major flaws.
Strong Points¶
Provides a Input Component based bindings and a simplistic structure
Supports most use cases through its 6 step system:
1. Input Component Config
2. Chords
3. Input Component Conversion
4. Activators (if applicable)
5. Action Conversion
6. Action Config
Flaws¶
6 step system can be limiting for some conversions
e.g.
Touchpad -> Joystick -> Spin -> Bool (Debounced) -> Value (Static)
is this
ICC (Touchpad -> Joystick -> Spin) -> AC (Bool (Debounced) -> Value (Static))
or
ICC (Touchpad -> Joystick -> Spin -> Bool (Debounced)) -> AC (-> Value (Static))
or
ICC (Touchpad -> Joystick -> Spin) -> ?(Bool (Debounced)) -> AC (-> Value (Static))
Possible Fixes¶
We could ditch the 6 step system for a simpler one:
1. Input Component Config
2. Chords
3. Magic!
6. Action Config
All the binding UI would need to do is find some permutation that can convert from Component to Action. The foreseeable downsides of this are: performance overhead, API complexity and configuration complexity.
- Input Component Config (Sharable)
- Chords <- needs to exist for all bindings for mode shifting
- Magic! <- this is where the binding engine lives
- Action Config
2 passes
1. Priority check pass
2. Actual pass
API¶
OnInteractionProfileConnected(interaction_profile: &InteractionProfile, id: u64)
OnInteractionProfileDisconnected(interaction_profile: &InteractionProfile, id: u64)
OnComponentUpated(interaction_profile_state: &InteractionProfileState, component: (SuPath, SuPath), new_state: ComponentEvent)
Binding to Actions¶
Allow binding to actions for ease of use
e.g.
In Minecraft bind sprint to "move"."forward" with double tap activator
In Generic FPS bind zoom turn to "turn" with 0.x sensitivity
This means that if the user changes the binding to "move.forward"
or the binding / sensitivity of "turn"
they don't need to also change the sprint binding / zoom turn binding / sensitivity
Priority still matters here so if an active action is bound to a lower priority action it blocks it from receiving any input.
TODO Figure out why this is allowed to break the 6/4 step rule