Newer
Older
use bevy::{
input::{
keyboard::KeyboardInput,
mouse::{MouseButtonInput, MouseScrollUnit, MouseWheel},
ButtonState,
},
prelude::*,
};
use crate::{
context::{CustomEventReader, KayakRootContext},
event_dispatcher::EventDispatcher,
input_event::InputEvent,
};
pub(crate) fn process_events(world: &mut World) {
let window_size = if let Some(windows) = world.get_resource::<Windows>() {
if let Some(window) = windows.get_primary() {
Vec2::new(window.width(), window.height())
} else {
log::warn!("Couldn't find primiary window!");
return;
}
} else {
log::warn!("Couldn't find primiary window!");
return;
};
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
let mut input_events = Vec::new();
query_world::<
(
Res<Events<CursorMoved>>,
Res<Events<MouseButtonInput>>,
Res<Events<MouseWheel>>,
Res<Events<ReceivedCharacter>>,
Res<Events<KeyboardInput>>,
ResMut<CustomEventReader<CursorMoved>>,
ResMut<CustomEventReader<MouseButtonInput>>,
ResMut<CustomEventReader<MouseWheel>>,
ResMut<CustomEventReader<ReceivedCharacter>>,
ResMut<CustomEventReader<KeyboardInput>>,
),
_,
_,
>(
|(
cursor_moved_events,
mouse_button_input_events,
mouse_wheel_events,
char_input_events,
keyboard_input_events,
mut custom_event_reader_cursor,
mut custom_event_mouse_button,
mut custom_event_mouse_wheel,
mut custom_event_char_input,
mut custom_event_keyboard,
)| {
if let Some(event) = custom_event_reader_cursor
.0
.iter(&cursor_moved_events)
.last()
{
// Currently, we can only handle a single MouseMoved event at a time so everything but the last needs to be skipped
input_events.push(InputEvent::MouseMoved((
event.position.x as f32,
window_size.y - event.position.y as f32,
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
)));
}
for event in custom_event_mouse_button.0.iter(&mouse_button_input_events) {
match event.button {
MouseButton::Left => {
if event.state == ButtonState::Pressed {
input_events.push(InputEvent::MouseLeftPress);
} else if event.state == ButtonState::Released {
input_events.push(InputEvent::MouseLeftRelease);
}
}
_ => {}
}
}
for MouseWheel { x, y, unit } in custom_event_mouse_wheel.0.iter(&mouse_wheel_events) {
input_events.push(InputEvent::Scroll {
dx: *x,
dy: *y,
is_line: matches!(unit, MouseScrollUnit::Line),
})
}
for event in custom_event_char_input.0.iter(&char_input_events) {
input_events.push(InputEvent::CharEvent { c: event.char });
}
for event in custom_event_keyboard.0.iter(&keyboard_input_events) {
if let Some(key_code) = event.key_code {
input_events.push(InputEvent::Keyboard {
key: key_code,
is_pressed: matches!(event.state, ButtonState::Pressed),
});
}
}
},
world,
);
// TODO: find a faster way of doing this.
let mut context_data = Vec::new();
query_world::<Query<(Entity, &mut EventDispatcher, &mut KayakRootContext)>, _, _>(
|mut query| {
for (entity, mut event_dispatcher, mut kayak_root_context) in query.iter_mut() {
context_data.push((
entity,
std::mem::take(&mut *event_dispatcher),
std::mem::take(&mut *kayak_root_context),
));
}
},
world,
);
for (entity, mut event_dispatcher, mut context) in context_data.drain(..) {
event_dispatcher.process_events(&input_events, &mut context, world);
world.entity_mut(entity).insert((event_dispatcher, context));
}
pub(crate) fn query_world<T: bevy::ecs::system::SystemParam + 'static, F, R>(
f: F,
world: &mut World,
) -> R
F: FnOnce(<T::Fetch as bevy::ecs::system::SystemParamFetch<'_, '_>>::Item) -> R,