konnektoren_bevy/input/
systems.rs1use super::{
2 components::*,
3 device::{AvailableInputDevices, InputDevice},
4};
5use bevy::prelude::*;
6
7pub fn handle_keyboard_input(
9 keyboard: Res<ButtonInput<KeyCode>>,
10 mut controller_query: Query<(&mut InputController, &PlayerInputMapping)>,
11 settings: Res<InputSettings>,
12 mut input_events: EventWriter<InputEvent>,
13) {
14 for (mut controller, mapping) in &mut controller_query {
15 if !controller.enabled || !mapping.enabled {
16 continue;
17 }
18
19 let keyboard_scheme = match &mapping.primary_device {
21 Some(InputDevice::Keyboard(scheme)) => Some(scheme.clone()),
22 _ => match &mapping.secondary_device {
23 Some(InputDevice::Keyboard(scheme)) => Some(scheme.clone()),
24 _ => None,
25 },
26 };
27
28 let Some(scheme) = keyboard_scheme else {
29 continue;
30 };
31
32 let (up, down, left, right) = scheme.get_keys();
33
34 let mut movement = Vec2::ZERO;
36 if keyboard.pressed(up) {
37 movement.y += 1.0;
38 }
39 if keyboard.pressed(down) {
40 movement.y -= 1.0;
41 }
42 if keyboard.pressed(left) {
43 movement.x -= 1.0;
44 }
45 if keyboard.pressed(right) {
46 movement.x += 1.0;
47 }
48
49 if movement != Vec2::ZERO {
51 movement = movement.normalize();
52 }
53
54 if movement.length() > settings.movement_threshold {
56 controller.movement = movement;
57 controller.input_source = InputSource::Keyboard(scheme.clone());
58
59 input_events.write(InputEvent::Movement {
60 player_id: controller.player_id,
61 direction: movement,
62 source: controller.input_source.clone(),
63 });
64 } else if matches!(controller.input_source, InputSource::Keyboard(_)) {
65 controller.movement = Vec2::ZERO;
66 }
67
68 let primary_pressed =
70 keyboard.just_pressed(KeyCode::Space) || keyboard.just_pressed(KeyCode::Enter);
71 let secondary_pressed =
72 keyboard.just_pressed(KeyCode::Escape) || keyboard.just_pressed(KeyCode::Backspace);
73
74 if primary_pressed {
75 controller.primary_action = true;
76 controller.input_source = InputSource::Keyboard(scheme.clone());
77
78 input_events.write(InputEvent::PrimaryAction {
79 player_id: controller.player_id,
80 source: controller.input_source.clone(),
81 });
82 }
83
84 if secondary_pressed {
85 controller.secondary_action = true;
86 controller.input_source = InputSource::Keyboard(scheme.clone());
87
88 input_events.write(InputEvent::SecondaryAction {
89 player_id: controller.player_id,
90 source: controller.input_source.clone(),
91 });
92 }
93 }
94}
95
96pub fn handle_gamepad_input(
98 gamepads: Query<(Entity, &Gamepad)>,
99 mut controller_query: Query<(&mut InputController, &PlayerInputMapping)>,
100 settings: Res<InputSettings>,
101 mut input_events: EventWriter<InputEvent>,
102) {
103 for (mut controller, mapping) in &mut controller_query {
104 if !controller.enabled || !mapping.enabled {
105 continue;
106 }
107
108 let gamepad_id = match &mapping.primary_device {
110 Some(InputDevice::Gamepad(id)) => Some(*id),
111 _ => match &mapping.secondary_device {
112 Some(InputDevice::Gamepad(id)) => Some(*id),
113 _ => None,
114 },
115 };
116
117 let Some(target_gamepad_id) = gamepad_id else {
118 continue;
119 };
120
121 let gamepad_entities: Vec<(Entity, &Gamepad)> = gamepads.iter().collect();
123
124 let Some((gamepad_entity, gamepad)) = gamepad_entities.get(target_gamepad_id as usize)
125 else {
126 continue;
127 };
128
129 let mut movement = Vec2::ZERO;
130
131 if gamepad.pressed(GamepadButton::DPadUp) {
133 movement.y += 1.0;
134 }
135 if gamepad.pressed(GamepadButton::DPadDown) {
136 movement.y -= 1.0;
137 }
138 if gamepad.pressed(GamepadButton::DPadLeft) {
139 movement.x -= 1.0;
140 }
141 if gamepad.pressed(GamepadButton::DPadRight) {
142 movement.x += 1.0;
143 }
144
145 let left_stick = gamepad.left_stick();
147 if left_stick.length() > settings.gamepad_deadzone {
148 movement += left_stick;
149 }
150
151 if movement.length() > 1.0 {
153 movement = movement.normalize();
154 }
155
156 if movement.length() > settings.movement_threshold {
157 controller.movement = movement;
158 controller.input_source = InputSource::Gamepad(*gamepad_entity);
159
160 input_events.write(InputEvent::Movement {
161 player_id: controller.player_id,
162 direction: movement,
163 source: controller.input_source.clone(),
164 });
165 } else if matches!(controller.input_source, InputSource::Gamepad(_)) {
166 controller.movement = Vec2::ZERO;
167 }
168
169 if gamepad.just_pressed(GamepadButton::South) || gamepad.just_pressed(GamepadButton::Start)
171 {
172 controller.primary_action = true;
173 controller.input_source = InputSource::Gamepad(*gamepad_entity);
174
175 input_events.write(InputEvent::PrimaryAction {
176 player_id: controller.player_id,
177 source: controller.input_source.clone(),
178 });
179 }
180
181 if gamepad.just_pressed(GamepadButton::East) || gamepad.just_pressed(GamepadButton::Select)
182 {
183 controller.secondary_action = true;
184 controller.input_source = InputSource::Gamepad(*gamepad_entity);
185
186 input_events.write(InputEvent::SecondaryAction {
187 player_id: controller.player_id,
188 source: controller.input_source.clone(),
189 });
190 }
191 }
192}
193
194pub fn detect_gamepads(
196 mut available_devices: ResMut<AvailableInputDevices>,
197 gamepads: Query<Entity, With<Gamepad>>,
198) {
199 let old_count = available_devices.gamepads.len();
200
201 available_devices.gamepads.clear();
203 for gamepad_entity in gamepads.iter() {
204 available_devices.gamepads.push(gamepad_entity);
205 }
206
207 let new_count = available_devices.gamepads.len();
208
209 if old_count != new_count {
210 info!("Gamepad count changed: {} -> {}", old_count, new_count);
211 }
212
213 available_devices.update_availability();
215}
216
217pub fn auto_assign_devices(
219 mut assignment: ResMut<InputDeviceAssignment>,
220 available_devices: Res<AvailableInputDevices>,
221 settings: Res<InputSettings>,
222 controllers: Query<&InputController>,
223) {
224 if !settings.auto_assign_devices || !assignment.assignments.is_empty() {
225 return;
226 }
227
228 let player_count = controllers.iter().map(|c| c.player_id).max().unwrap_or(0) + 1;
229 let available = available_devices.get_available_devices();
230
231 for player_id in 0..player_count.min(assignment.max_players) {
232 if assignment.get_device_for_player(player_id).is_some() {
233 continue; }
235
236 if let Some(device) = available
238 .iter()
239 .find(|device| !assignment.is_device_assigned(device))
240 {
241 assignment.assign_device(player_id, device.clone());
242 }
243 }
244}
245
246pub fn update_player_mappings(
248 assignment: Res<InputDeviceAssignment>,
249 mut mappings: Query<&mut PlayerInputMapping>,
250) {
251 if !assignment.is_changed() {
252 return;
253 }
254
255 for mut mapping in mappings.iter_mut() {
256 if let Some(device) = assignment.get_device_for_player(mapping.player_id) {
257 mapping.primary_device = Some(device.clone());
258 } else {
259 mapping.primary_device = None;
260 }
261 }
262}
263
264pub fn clear_input_states(mut controllers: Query<&mut InputController>) {
266 for mut controller in controllers.iter_mut() {
267 controller.primary_action = false;
268 controller.secondary_action = false;
269 }
270}