Newer
Older
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
use bevy::ecs::system::SystemParam;
use crate::prelude::*;
use std::{fmt::Debug, time::Duration};
pub(crate) fn plugin(app: &mut App) {
app.init_resource::<ClickStateRes>()
.register_type::<ClickStateRes>()
.add_systems(Update, tick);
}
#[derive(SystemParam)]
pub struct ClickState<'w> {
res: ResMut<'w, ClickStateRes>,
}
/// Actual state struct
#[derive(Resource, Reflect)]
#[reflect(Resource)]
struct ClickStateRes {
timer_since_last_click: Timer,
click_state: Option<ClickCount>,
}
impl Default for ClickStateRes {
fn default() -> Self {
Self {
timer_since_last_click: Timer::from_seconds(0.5, TimerMode::Once),
click_state: None,
}
}
}
#[derive(Reflect, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum ClickCount {
Single,
Double,
Triple,
MoreThanTriple,
}
impl ClickCount {
fn advance(self) -> Self {
match self {
Self::Single => Self::Double,
Self::Double => Self::Triple,
Self::Triple => Self::MoreThanTriple,
Self::MoreThanTriple => Self::MoreThanTriple,
}
}
}
impl ClickState<'_> {
/// Makes [ClickState] aware of a click event.
pub fn feed_click(&mut self) -> ClickCount {
self.res.timer_since_last_click.reset();
match self.res.click_state {
None => {
self.res.click_state = Some(ClickCount::Single);
ClickCount::Single
}
Some(click_count) => {
let new_click_count = click_count.advance();
self.res.click_state = Some(new_click_count);
new_click_count
}
}
}
/// Get the current click state.
///
/// `None` means no clicks have been registered recently
#[allow(dead_code)]
pub fn get(&self) -> Option<ClickCount> {
self.res.click_state
}
/// You must call this every frame
pub(crate) fn tick(&mut self, delta: Duration) {
self.res.timer_since_last_click.tick(delta);
if self.res.timer_since_last_click.just_finished() {
self.res.click_state = None;
// debug!("Resetting click timer");
}
}
}
fn tick(mut state: ClickState, time: Res<Time>) {
state.tick(time.delta());
}