veebee 1.1.1

A Simple Rust Game Engine For 2D
Documentation
use crate::prelude::GameState;
use bevy::{prelude::*, utils::HashSet};

pub use bevy::{
    input::{
        mouse::{MouseButton, MouseButtonInput, MouseMotion, MouseWheel},
        ElementState,
    },
    window::CursorMoved,
};

pub struct MousePlugin;

impl Plugin for MousePlugin {
    fn build(&self, app: &mut bevy::prelude::AppBuilder) {
        app.insert_resource(MouseState::default())
            .add_system(sync_mouse_state.system().before("game_logic_sync"))
            .add_system(sync_mouse_events.system().before("game_logic_sync"));
    }
}
#[derive(Clone, Debug, Default)]
pub struct MouseState {
    location: Option<Vec2>,
    motion: Vec2,
    wheel: MouseWheelState,
    pressed: HashSet<MouseButton>,
    just_pressed: HashSet<MouseButton>,
    just_released: HashSet<MouseButton>,
}


#[derive(Clone, Copy, Debug, Default)]
pub struct MouseWheelState {

    pub y: f32,

    pub x: f32,
}

impl MouseState {

    pub fn location(&self) -> Option<Vec2> {
        self.location
    }

    pub fn motion(&self) -> Vec2 {
        self.motion
    }

    pub fn wheel(&self) -> MouseWheelState {
        self.wheel
    }

    pub fn pressed(&self, mouse_button: MouseButton) -> bool {
        self.pressed.contains(&mouse_button)
    }

    pub fn just_pressed(&self, mouse_button: MouseButton) -> bool {
        self.just_pressed.contains(&mouse_button)
    }

    pub fn just_released(&self, mouse_button: MouseButton) -> bool {
        self.just_released.contains(&mouse_button)
    }

    pub fn get_pressed(&self) -> impl ExactSizeIterator<Item = &MouseButton> {
        self.pressed.iter()
    }

    pub fn get_just_pressed(&self) -> impl ExactSizeIterator<Item = &MouseButton> {
        self.just_pressed.iter()
    }

    pub fn get_just_released(&self) -> impl ExactSizeIterator<Item = &MouseButton> {
        self.just_released.iter()
    }
}

fn sync_mouse_events(
    mut game_state: ResMut<GameState>,
    mut mouse_button_events: EventReader<MouseButtonInput>,
    mut cursor_moved_events: EventReader<CursorMoved>,
    mut mouse_motion_events: EventReader<MouseMotion>,
    mut mouse_wheel_events: EventReader<MouseWheel>,
) {

    game_state.mouse_button_events.clear();
    game_state.mouse_location_events.clear();
    game_state.mouse_motion_events.clear();
    game_state.mouse_wheel_events.clear();

    // Populate this frame's events
    for ev in mouse_button_events.iter() {
        game_state.mouse_button_events.push(ev.clone());
    }
    for ev in cursor_moved_events.iter() {
        let mut new_event = ev.clone();

        new_event.position -= game_state.screen_dimensions * 0.5;
        game_state.mouse_location_events.push(new_event);
    }
    for ev in mouse_motion_events.iter() {
        let mut ev2 = ev.clone();
        ev2.delta.y *= -1.0;
        game_state.mouse_motion_events.push(ev2.clone());
    }
    for ev in mouse_wheel_events.iter() {
        game_state.mouse_wheel_events.push(ev.clone());
    }
}

fn sync_mouse_state(
    mouse_button_input: Res<Input<MouseButton>>,
    mut mouse_state: ResMut<MouseState>,
    mut mouse_motion_events: EventReader<MouseMotion>,
    mut cursor_moved_events: EventReader<CursorMoved>,
    mut mouse_wheel_events: EventReader<MouseWheel>,
    game_state: Res<GameState>,
) {

    if let Some(event) = cursor_moved_events.iter().last() {

        let location = event.position - game_state.screen_dimensions * 0.5;
        mouse_state.location = Some(location);
    }

    mouse_state.motion = Vec2::ZERO;
    for ev in mouse_motion_events.iter() {

        let mut ev2 = ev.clone();
        ev2.delta.y *= -1.0;
        mouse_state.motion += ev2.delta;
    }

    mouse_state.wheel = MouseWheelState::default();
    let mut cumulative_x = 0.0;
    let mut cumulative_y = 0.0;
    for ev in mouse_wheel_events.iter() {
        cumulative_x += ev.x;
        cumulative_y += ev.y;
    }
    mouse_state.wheel.x = match cumulative_x {
        x if x > 0.0 => 1.0,
        x if x < 0.0 => -1.0,
        _ => 0.0,
    };
    mouse_state.wheel.y = match cumulative_y {
        y if y > 0.0 => 1.0,
        y if y < 0.0 => -1.0,
        _ => 0.0,
    };

    mouse_state.pressed.clear();
    for mouse_button in mouse_button_input.get_pressed() {
        mouse_state.pressed.insert(*mouse_button);
    }

    mouse_state.just_pressed.clear();
    for mouse_button in mouse_button_input.get_just_pressed() {
        mouse_state.just_pressed.insert(*mouse_button);
    }

    mouse_state.just_released.clear();
    for mouse_button in mouse_button_input.get_just_released() {
        mouse_state.just_released.insert(*mouse_button);
    }
}