Bevy Version:0.9(outdated!)

Mouse

Relevant official examples: mouse_input, mouse_input_events.


Mouse Buttons

Similar to keyboard input, mouse buttons are available as an Input state resource, as well as events.

You can check the state of specific mouse buttons using Input<MouseButton>:

fn mouse_button_input(
    buttons: Res<Input<MouseButton>>,
) {
    if buttons.just_pressed(MouseButton::Left) {
        // Left button was pressed
    }
    if buttons.just_released(MouseButton::Left) {
        // Left Button was released
    }
    if buttons.pressed(MouseButton::Right) {
        // Right Button is being held down
    }
    // we can check multiple at once with `.any_*`
    if buttons.any_just_pressed([MouseButton::Left, MouseButton::Right]) {
        // Either the left or the right button was just pressed
    }
}

To get all press/release activity, use MouseButtonInput events:

fn mouse_button_events(
    mut mousebtn_evr: EventReader<MouseButtonInput>,
) {
    use bevy::input::ButtonState;

    for ev in mousebtn_evr.iter() {
        match ev.state {
            ButtonState::Pressed => {
                println!("Mouse button press: {:?}", ev.button);
            }
            ButtonState::Released => {
                println!("Mouse button release: {:?}", ev.button);
            }
        }
    }
}

Mouse Scrolling / Wheel

To detect scrolling input, use MouseWheel events:

fn scroll_events(
    mut scroll_evr: EventReader<MouseWheel>,
) {
    use bevy::input::mouse::MouseScrollUnit;
    for ev in scroll_evr.iter() {
        match ev.unit {
            MouseScrollUnit::Line => {
                println!("Scroll (line units): vertical: {}, horizontal: {}", ev.y, ev.x);
            }
            MouseScrollUnit::Pixel => {
                println!("Scroll (pixel units): vertical: {}, horizontal: {}", ev.y, ev.x);
            }
        }
    }
}

The MouseScrollUnit enum is important: it tells you the type of scroll input. Line is for hardware with fixed steps, like the wheel on desktop mice. Pixel is for hardware with smooth (fine-grained) scrolling, like laptop touchpads.

You should probably handle each of these differently (with different sensitivity settings), to provide a good experience on both types of hardware.

Note: the Line unit is not guaranteed to have whole number values/steps! At least macOS does non-linear scaling / acceleration of scrolling at the OS level, meaning your app will get a fractional number of lines even when using a regular PC mouse with a scroll wheel.

Mouse Motion

Use this if you don't care about the exact position of the mouse cursor, but rather you just want to see how much it moved from frame to frame. This is useful for things like controlling a 3D camera.

Use MouseMotion events. Whenever the mouse is moved, you will get an event with the delta.

fn mouse_motion(
    mut motion_evr: EventReader<MouseMotion>,
) {
    for ev in motion_evr.iter() {
        println!("Mouse moved: X: {} px, Y: {} px", ev.delta.x, ev.delta.y);
    }
}

You might want to grab/lock the mouse inside the game window.

Mouse Cursor Position

Use this if you want to accurately track the position pointer / cursor. This is useful for things like clicking and hovering over objects in your game or UI.

You can get the current coordinates of the mouse pointer, from the respective Window (if the mouse is currently inside that window):

fn cursor_position(
    windows: Res<Windows>,
) {
    // Games typically only have one window (the primary window).
    // For multi-window applications, you need to use a specific window ID here.
    let window = windows.get_primary().unwrap();

    if let Some(_position) = window.cursor_position() {
        // cursor is inside the window, position given
    } else {
        // cursor is not inside the window
    }
}

To detect when the pointer is moved, use CursorMoved events to get the updated coordinates:

fn cursor_events(
    mut cursor_evr: EventReader<CursorMoved>,
) {
    for ev in cursor_evr.iter() {
        println!(
            "New cursor position: X: {}, Y: {}, in Window ID: {:?}",
            ev.position.x, ev.position.y, ev.id
        );
    }
}

Note that you can only get the position of the mouse inside a window; you cannot get the global position of the mouse in the whole OS Desktop / on the screen as a whole.

The coordinates you get are in "window space". They represent window pixels, and the origin is the bottom left corner of the window. They do not relate to your camera or in-game coordinates in any way. See this cookbook example for converting these window cursor coordinates into world-space coordinates.

To track when the mouse cursor enters and leaves your window(s), use CursorEntered and CursorLeft events.