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
            keyboard::Plugin::<MyActions, MyValues, MyKeyboardBinding>::new(),
        ))
        // Add observers to print the inputs. It will catch events for the `MyActions` actions,
        // find the `ControllerInterface` that sent it, and print the event data.
        // The first observer use the entities stored in the action event to find the players.
        .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!("[OBS1] Player {}: {:?}", player_name.as_str(), action.key());
            }
        })
        // The second observer use the `ControlledBy` component of player and compare it to the
        // controller id stored in the action event.
        .add_observer(
            |action: On<ActionEvent<MyActions>>,
             players: Query<(&Name, &ControlledBy), With<Player>>| {
                for (name, controlled_by) in players {
                    // Act only on the controlled players
                    if controlled_by.controller() != action.controller() {
                        continue;
                    }
                    // Print data about this action
                    println!("[OBS2] Player {}: {:?}", name.as_str(), action.key(),);
                }
            },
        )
        // Add a startup system to initiate the entities
        .add_systems(Startup, |mut commands: Commands| {
            commands.spawn(Camera3d::default());
            // Instantiate the controller and keep the id
            let controller_id = commands.spawn(MyKeyboardBinding::new()).id();
            // Instantiate the player with a `ControlledBy` component to link it to the controller.
            // This will also add a `Controlling` component to the controller, just like any Bevy
            // relationships.
            commands.spawn((Player, Name::new("Player1"), ControlledBy(controller_id)));
            // Instantiate another player controlled
            commands.spawn((Player, Name::new("Player2"), ControlledBy(controller_id)));
            // Instantiate another player not controlled
            commands.spawn((Player, Name::new("Player3")));
        })
        // Log the values by using the `Controlling` component of controller to know to with player
        // applying the
        .add_systems(
            Update,
            |controllers: Query<(&ControllerValues<MyValues>, &Controlling)>,
             players: Query<&Name, With<Player>>| {
                for (value, controlling) in controllers {
                    // Only log the 2 axis values
                    let Some(bool_value) = value.get_as_bool(&MyValues::Jumping) else {
                        continue;
                    };
                    // Log only if true
                    if !bool_value {
                        continue;
                    }
                    // Iterate over the controlled players
                    for player_id in controlling.controlling() {
                        let Ok(player_name) = players.get(*player_id) else {
                            continue;
                        };
                        println!("{} jumping", player_name);
                    }
                }
            },
        )
        .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)]
enum MyValues {
    Jumping,
}

/// Custom binder for this example
#[derive(Component, Reflect)]
struct MyKeyboardBinding {
    jump: keyboard::triggers::ButtonPressed,
    jumping: keyboard::values::ButtonPressed,
}

impl MyKeyboardBinding {
    /// Create a keyboard binder
    fn new() -> Self {
        Self {
            jump: keyboard::triggers::ButtonPressed::new(KeyCode::KeyQ),
            jumping: keyboard::values::ButtonPressed::new(KeyCode::KeyW),
        }
    }
}

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

    fn get_value_bindings<'a>(
        &'a mut self,
    ) -> Vec<(&'a mut dyn keyboard::FunctionTrait, MyValues)> {
        return vec![(&mut self.jumping, MyValues::Jumping)];
    }
}