1use super::device::{InputDevice, KeyboardScheme};
2use bevy::prelude::*;
3use std::collections::HashMap;
4
5#[derive(Component, Reflect, Clone)]
7#[reflect(Component)]
8pub struct InputController {
9 pub player_id: u32,
10 pub movement: Vec2,
11 pub primary_action: bool, pub secondary_action: bool, pub input_source: InputSource,
14 pub enabled: bool,
15}
16
17impl Default for InputController {
18 fn default() -> Self {
19 Self {
20 player_id: 0,
21 movement: Vec2::ZERO,
22 primary_action: false,
23 secondary_action: false,
24 input_source: InputSource::Keyboard(KeyboardScheme::WASD),
25 enabled: true,
26 }
27 }
28}
29
30impl InputController {
31 pub fn new(player_id: u32) -> Self {
32 Self {
33 player_id,
34 ..Default::default()
35 }
36 }
37
38 pub fn with_input_source(mut self, source: InputSource) -> Self {
39 self.input_source = source;
40 self
41 }
42
43 pub fn enabled(mut self, enabled: bool) -> Self {
44 self.enabled = enabled;
45 self
46 }
47
48 pub fn clear(&mut self) {
50 self.movement = Vec2::ZERO;
51 self.primary_action = false;
52 self.secondary_action = false;
53 }
54
55 pub fn has_input(&self) -> bool {
57 self.movement != Vec2::ZERO || self.primary_action || self.secondary_action
58 }
59}
60
61#[derive(Reflect, Clone, Debug, PartialEq)]
63pub enum InputSource {
64 Keyboard(KeyboardScheme),
65 Gamepad(Entity),
66 Mouse,
67 Touch,
68}
69
70impl InputSource {
71 pub fn name(&self) -> String {
72 match self {
73 InputSource::Keyboard(scheme) => format!("Keyboard ({})", scheme.name()),
74 InputSource::Gamepad(_) => "Gamepad".to_string(),
75 InputSource::Mouse => "Mouse".to_string(),
76 InputSource::Touch => "Touch".to_string(),
77 }
78 }
79}
80
81#[derive(Component, Reflect, Clone)]
83#[reflect(Component)]
84pub struct PlayerInputMapping {
85 pub player_id: u32,
86 pub primary_device: Option<InputDevice>,
87 pub secondary_device: Option<InputDevice>, pub enabled: bool,
89}
90
91impl Default for PlayerInputMapping {
92 fn default() -> Self {
93 Self {
94 player_id: 0,
95 primary_device: Some(InputDevice::Keyboard(KeyboardScheme::WASD)),
96 secondary_device: None,
97 enabled: true,
98 }
99 }
100}
101
102impl PlayerInputMapping {
103 pub fn new(player_id: u32) -> Self {
104 Self {
105 player_id,
106 ..Default::default()
107 }
108 }
109
110 pub fn with_primary_device(mut self, device: InputDevice) -> Self {
111 self.primary_device = Some(device);
112 self
113 }
114
115 pub fn with_secondary_device(mut self, device: Option<InputDevice>) -> Self {
116 self.secondary_device = device;
117 self
118 }
119
120 pub fn enabled(mut self, enabled: bool) -> Self {
121 self.enabled = enabled;
122 self
123 }
124
125 pub fn get_active_device(&self) -> Option<&InputDevice> {
127 self.primary_device
128 .as_ref()
129 .or(self.secondary_device.as_ref())
130 }
131}
132
133#[derive(Resource, Reflect, Default)]
135#[reflect(Resource)]
136pub struct InputDeviceAssignment {
137 pub assignments: HashMap<u32, InputDevice>, pub max_players: u32,
139}
140
141impl InputDeviceAssignment {
142 pub fn new(max_players: u32) -> Self {
143 Self {
144 assignments: HashMap::new(),
145 max_players,
146 }
147 }
148
149 pub fn assign_device(&mut self, player_id: u32, device: InputDevice) {
151 self.assignments
153 .retain(|_, assigned_device| assigned_device != &device);
154
155 self.assignments.insert(player_id, device);
157
158 info!(
159 "Assigned device to player {}: {:?}",
160 player_id,
161 self.assignments.get(&player_id)
162 );
163 }
164
165 pub fn get_device_for_player(&self, player_id: u32) -> Option<&InputDevice> {
167 self.assignments.get(&player_id)
168 }
169
170 pub fn is_device_assigned(&self, device: &InputDevice) -> bool {
172 self.assignments
173 .values()
174 .any(|assigned_device| assigned_device == device)
175 }
176
177 pub fn get_player_for_device(&self, device: &InputDevice) -> Option<u32> {
179 self.assignments
180 .iter()
181 .find(|(_, assigned_device)| *assigned_device == device)
182 .map(|(player_id, _)| *player_id)
183 }
184
185 pub fn unassign_player(&mut self, player_id: u32) {
187 self.assignments.remove(&player_id);
188 }
189
190 pub fn clear(&mut self) {
192 self.assignments.clear();
193 }
194
195 pub fn get_assigned_players(&self) -> Vec<u32> {
197 self.assignments.keys().copied().collect()
198 }
199}
200
201#[derive(Resource, Reflect, Clone)]
203#[reflect(Resource)]
204pub struct InputSettings {
205 pub gamepad_deadzone: f32,
206 pub movement_threshold: f32,
207 pub auto_assign_devices: bool,
208 pub allow_keyboard_sharing: bool, }
210
211impl Default for InputSettings {
212 fn default() -> Self {
213 Self {
214 gamepad_deadzone: 0.2,
215 movement_threshold: 0.1,
216 auto_assign_devices: true,
217 allow_keyboard_sharing: true,
218 }
219 }
220}
221
222#[derive(Event, Debug, Clone)]
224pub enum InputEvent {
225 DeviceAssigned { player_id: u32, device: InputDevice },
227 DeviceUnassigned { player_id: u32 },
229 PrimaryAction { player_id: u32, source: InputSource },
231 SecondaryAction { player_id: u32, source: InputSource },
233 Movement {
235 player_id: u32,
236 direction: Vec2,
237 source: InputSource,
238 },
239}
240
241#[derive(Component)]
243pub struct InputConfigurationMarker;