1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
use bevy::{
    input::{keyboard::KeyboardInput, ButtonState},
    prelude::*,
};

/// Builder of keyboard events & state based system execution condition.
#[derive(Copy, Clone)]
pub(super) struct KeyCondition {
    control: bool,
    shift: bool,
    key: KeyCode,
}

impl KeyCondition {
    /// Run if a key is pressed and control is not.
    pub(super) fn single(key: KeyCode) -> Self {
        Self {
            control: false,
            shift: false,
            key,
        }
    }

    /// Run if a key is pressed together with control.
    pub(super) fn with_ctrl(mut self) -> Self {
        self.control = true;
        self
    }

    /// Run if a key is pressed together with shift.
    pub(super) fn with_shift(mut self) -> Self {
        self.shift = true;
        self
    }

    pub(super) fn build(
        self,
    ) -> impl Fn(Res<ButtonInput<KeyCode>>, EventReader<KeyboardInput>) -> bool {
        move |keys: Res<ButtonInput<KeyCode>>, mut events: EventReader<KeyboardInput>| {
            let proper_key = events
                .read()
                .filter(|k| k.state == ButtonState::Pressed && k.key_code == self.key)
                .count()
                > 0;

            let control = keys.pressed(KeyCode::ControlLeft) || keys.pressed(KeyCode::ControlRight);
            let shift = keys.pressed(KeyCode::ShiftLeft) || keys.pressed(KeyCode::ShiftRight);
            self.control == control && shift == self.shift && proper_key
        }
    }
}