bevy_input_bindings 0.0.2

High level, flexible and shareable input binding library for the Bevy game engine
Documentation
use bevy::prelude::*;

use bevy_input_bindings::prelude::*;

fn main() {
    App::new()
        .add_plugins((
            DefaultPlugins,
            // Add the keyboard plugin attached to the custom binder
            gamepad::Plugin::<MyActions, MyValues, MyBinding>::new(),
        ))
        // Add observers to print the actions.
        .add_observer(|action: On<ActionEvent<MyActions>>, players: Query<&Name, With<Player>>| {
            // Iterate over the controlled entities
            for controlled_id in action.controlling() {
                // Get the player name from the entity stored
                let Ok(player_name) = players.get(*controlled_id) else {
                    continue;
                };
                // Print data about this action
                println!("{} -> {:?}", player_name.as_str(), action.key());
            }
        })
        // Add a startup system to initiate the entities
        .add_systems(Startup, |mut commands: Commands| {
            commands.spawn(Camera3d::default());
            commands.spawn((Player, Name::new("John Doe")));
            commands.spawn((Player, Name::new("Emily Williams")));
        })
        // Add a system to connect the players to newly added gamepads
        .add_systems(
            Update,
            |mut commands: Commands,
             uncontrolled_players: Query<
                (Entity, &Name),
                (With<Player>, Without<ControlledBy>),
            >,
             added_gamepads: Query<Entity, (Added<MyBinding>, Without<Controlling>)>| {
                // Keep track of the players that have already been processed in this iteration
                let mut newly_controlled_players = vec![];
                // Iterate over added gamepads
                for gamepad_id in added_gamepads {
                    println!("Added gamepad {gamepad_id}");
                    for (player_id, player_name) in uncontrolled_players {
                        // Avoid set up two controllers to the same player
                        if newly_controlled_players.contains(&player_id) {
                            continue;
                        }
                        newly_controlled_players.push(player_id);
                        // Add the `ControlledBy` component
                        commands.entity(player_id).insert(ControlledBy(gamepad_id));
                        // Print the link
                        println!("{player_name} ({player_id}) is now controlled by {gamepad_id}");
                        // Leave the loop to avoid setting two players on the same controller
                        break;
                    }
                }
            },
        )
        .run();
}

#[derive(Component)]
struct Player;

/// Custom actions for this example
#[derive(Debug)]
enum MyActions {
    Jump,
}

/// Custom values for this example
#[derive(Debug, Hash, PartialEq, Eq)]
struct MyValues;

/// Custom binder for this example
#[derive(Component, Reflect)]
struct MyBinding {
    jump: gamepad::triggers::ButtonPressed,
}

impl Default for MyBinding {
    fn default() -> Self {
        Self {
            jump: gamepad::triggers::ButtonPressed::new(GamepadButton::South),
        }
    }
}

impl gamepad::Binding<MyActions, MyValues> for MyBinding {
    fn get_action_bindings<'a>(
        &'a mut self,
    ) -> Vec<(&'a mut dyn gamepad::TriggerTrait, MyActions)> {
        return vec![(&mut self.jump, MyActions::Jump)];
    }
}