1use bevy_app::{App, First, Last, Plugin};
2use bevy_ecs::{
3 entity::Entity,
4 message::{MessageReader, MessageWriter},
5 system::ResMut,
6};
7use bevy_input::{
8 ButtonInput, ButtonState, InputPlugin,
9 gestures::PanGesture as BevyPanGesture,
10 keyboard::KeyCode,
11 mouse::{
12 MouseButton as BevyMouseButton, MouseButtonInput as BevyMouseButtonInput,
13 MouseMotion as BevyMouseMotion, MouseScrollUnit, MouseWheel as BevyMouseWheel,
14 },
15};
16
17use crate::plugins::input::events::{
18 KeyboardInput as GodotKeyboardInput, MouseButton as GodotMouseButton,
19 MouseButtonInput as GodotMouseButtonInput, MouseMotion as GodotMouseMotion,
20 PanGestureInput as GodotPanGestureInput,
21};
22
23#[derive(Default)]
26pub struct BevyInputBridgePlugin;
27
28impl Plugin for BevyInputBridgePlugin {
29 fn build(&self, app: &mut App) {
30 app.add_plugins(super::events::GodotInputEventPlugin)
32 .add_plugins(InputPlugin)
33 .add_systems(
34 First,
35 (
36 bridge_keyboard_input,
37 bridge_mouse_button_input,
38 bridge_mouse_motion,
39 bridge_mouse_scroll,
40 bridge_pan_gesture,
41 ),
42 )
43 .add_systems(Last, clear_keyboard_input);
44 }
45}
46
47fn bridge_keyboard_input(
48 mut keyboard_messages: MessageReader<GodotKeyboardInput>,
49 mut key_code_input: ResMut<ButtonInput<KeyCode>>,
50) {
51 for message in keyboard_messages.read() {
52 if let Some(bevy_key_code) = godot_key_to_bevy_keycode(message.keycode) {
54 if message.pressed {
55 key_code_input.press(bevy_key_code);
56 } else {
57 key_code_input.release(bevy_key_code);
58 }
59 }
60 }
61}
62
63fn bridge_mouse_button_input(
64 mut mouse_messages: MessageReader<GodotMouseButtonInput>,
65 mut bevy_mouse_button_messages: MessageWriter<BevyMouseButtonInput>,
66) {
67 for message in mouse_messages.read() {
68 if matches!(
70 message.button,
71 GodotMouseButton::WheelUp
72 | GodotMouseButton::WheelDown
73 | GodotMouseButton::WheelLeft
74 | GodotMouseButton::WheelRight
75 ) {
76 continue;
77 }
78
79 let bevy_button = godot_mouse_to_bevy_mouse(message.button);
80 let state = if message.pressed {
81 ButtonState::Pressed
82 } else {
83 ButtonState::Released
84 };
85
86 bevy_mouse_button_messages.write(BevyMouseButtonInput {
88 button: bevy_button,
89 state,
90 window: Entity::PLACEHOLDER,
91 });
92 }
93}
94
95fn bridge_mouse_motion(
96 mut mouse_motion_messages: MessageReader<GodotMouseMotion>,
97 mut bevy_mouse_motion_messages: MessageWriter<BevyMouseMotion>,
98) {
99 for event in mouse_motion_messages.read() {
101 bevy_mouse_motion_messages.write(BevyMouseMotion { delta: event.delta });
102 }
103}
104
105fn bridge_mouse_scroll(
106 mut mouse_button_messages: MessageReader<GodotMouseButtonInput>,
107 mut bevy_mouse_scroll_messages: MessageWriter<BevyMouseWheel>,
108) {
109 for message in mouse_button_messages.read() {
111 match message.button {
112 GodotMouseButton::WheelUp => {
113 bevy_mouse_scroll_messages.write(BevyMouseWheel {
114 x: 0.0,
115 y: message.factor,
116 unit: MouseScrollUnit::Line,
117 window: Entity::PLACEHOLDER,
118 });
119 }
120 GodotMouseButton::WheelDown => {
121 bevy_mouse_scroll_messages.write(BevyMouseWheel {
122 x: 0.0,
123 y: -message.factor,
124 unit: MouseScrollUnit::Line,
125 window: Entity::PLACEHOLDER,
126 });
127 }
128 GodotMouseButton::WheelLeft => {
129 bevy_mouse_scroll_messages.write(BevyMouseWheel {
130 x: -message.factor,
131 y: 0.0,
132 unit: MouseScrollUnit::Line,
133 window: Entity::PLACEHOLDER,
134 });
135 }
136 GodotMouseButton::WheelRight => {
137 bevy_mouse_scroll_messages.write(BevyMouseWheel {
138 x: message.factor,
139 y: 0.0,
140 unit: MouseScrollUnit::Line,
141 window: Entity::PLACEHOLDER,
142 });
143 }
144 _ => {} }
146 }
147}
148
149fn bridge_pan_gesture(
150 mut pan_messages: MessageReader<GodotPanGestureInput>,
151 mut bevy_pan_messages: MessageWriter<BevyPanGesture>,
152) {
153 for event in pan_messages.read() {
154 bevy_pan_messages.write(BevyPanGesture(event.delta));
155 }
156}
157
158fn clear_keyboard_input(mut keyboard_input: ResMut<ButtonInput<KeyCode>>) {
159 keyboard_input.clear();
162}
163
164fn godot_key_to_bevy_keycode(godot_key: godot::global::Key) -> Option<KeyCode> {
166 use KeyCode as BK;
167 use godot::global::Key as GK;
168
169 match godot_key {
170 GK::A => Some(BK::KeyA),
171 GK::B => Some(BK::KeyB),
172 GK::C => Some(BK::KeyC),
173 GK::D => Some(BK::KeyD),
174 GK::E => Some(BK::KeyE),
175 GK::F => Some(BK::KeyF),
176 GK::G => Some(BK::KeyG),
177 GK::H => Some(BK::KeyH),
178 GK::I => Some(BK::KeyI),
179 GK::J => Some(BK::KeyJ),
180 GK::K => Some(BK::KeyK),
181 GK::L => Some(BK::KeyL),
182 GK::M => Some(BK::KeyM),
183 GK::N => Some(BK::KeyN),
184 GK::O => Some(BK::KeyO),
185 GK::P => Some(BK::KeyP),
186 GK::Q => Some(BK::KeyQ),
187 GK::R => Some(BK::KeyR),
188 GK::S => Some(BK::KeyS),
189 GK::T => Some(BK::KeyT),
190 GK::U => Some(BK::KeyU),
191 GK::V => Some(BK::KeyV),
192 GK::W => Some(BK::KeyW),
193 GK::X => Some(BK::KeyX),
194 GK::Y => Some(BK::KeyY),
195 GK::Z => Some(BK::KeyZ),
196
197 GK::KEY_0 => Some(BK::Digit0),
198 GK::KEY_1 => Some(BK::Digit1),
199 GK::KEY_2 => Some(BK::Digit2),
200 GK::KEY_3 => Some(BK::Digit3),
201 GK::KEY_4 => Some(BK::Digit4),
202 GK::KEY_5 => Some(BK::Digit5),
203 GK::KEY_6 => Some(BK::Digit6),
204 GK::KEY_7 => Some(BK::Digit7),
205 GK::KEY_8 => Some(BK::Digit8),
206 GK::KEY_9 => Some(BK::Digit9),
207
208 GK::SPACE => Some(BK::Space),
209 GK::ENTER => Some(BK::Enter),
210 GK::ESCAPE => Some(BK::Escape),
211 GK::BACKSPACE => Some(BK::Backspace),
212 GK::TAB => Some(BK::Tab),
213 GK::SHIFT => Some(BK::ShiftLeft),
214 GK::CTRL => Some(BK::ControlLeft),
215 GK::ALT => Some(BK::AltLeft),
216
217 GK::LEFT => Some(BK::ArrowLeft),
218 GK::RIGHT => Some(BK::ArrowRight),
219 GK::UP => Some(BK::ArrowUp),
220 GK::DOWN => Some(BK::ArrowDown),
221
222 GK::F1 => Some(BK::F1),
223 GK::F2 => Some(BK::F2),
224 GK::F3 => Some(BK::F3),
225 GK::F4 => Some(BK::F4),
226 GK::F5 => Some(BK::F5),
227 GK::F6 => Some(BK::F6),
228 GK::F7 => Some(BK::F7),
229 GK::F8 => Some(BK::F8),
230 GK::F9 => Some(BK::F9),
231 GK::F10 => Some(BK::F10),
232 GK::F11 => Some(BK::F11),
233 GK::F12 => Some(BK::F12),
234
235 GK::KP_0 => Some(BK::Numpad0),
237 GK::KP_1 => Some(BK::Numpad1),
238 GK::KP_2 => Some(BK::Numpad2),
239 GK::KP_3 => Some(BK::Numpad3),
240 GK::KP_4 => Some(BK::Numpad4),
241 GK::KP_5 => Some(BK::Numpad5),
242 GK::KP_6 => Some(BK::Numpad6),
243 GK::KP_7 => Some(BK::Numpad7),
244 GK::KP_8 => Some(BK::Numpad8),
245 GK::KP_9 => Some(BK::Numpad9),
246 GK::KP_ADD => Some(BK::NumpadAdd),
247 GK::KP_SUBTRACT => Some(BK::NumpadSubtract),
248 GK::KP_MULTIPLY => Some(BK::NumpadMultiply),
249 GK::KP_DIVIDE => Some(BK::NumpadDivide),
250 GK::KP_PERIOD => Some(BK::NumpadDecimal),
251 GK::KP_ENTER => Some(BK::NumpadEnter),
252
253 GK::DELETE => Some(BK::Delete),
255 GK::INSERT => Some(BK::Insert),
256 GK::HOME => Some(BK::Home),
257 GK::END => Some(BK::End),
258 GK::PAGEUP => Some(BK::PageUp),
259 GK::PAGEDOWN => Some(BK::PageDown),
260 GK::CAPSLOCK => Some(BK::CapsLock),
261 GK::NUMLOCK => Some(BK::NumLock),
262 GK::SCROLLLOCK => Some(BK::ScrollLock),
263 GK::PAUSE => Some(BK::Pause),
264 GK::PRINT => Some(BK::PrintScreen),
265
266 GK::COMMA => Some(BK::Comma),
268 GK::PERIOD => Some(BK::Period),
269 GK::SLASH => Some(BK::Slash),
270 GK::SEMICOLON => Some(BK::Semicolon),
271 GK::APOSTROPHE => Some(BK::Quote),
272 GK::BRACKETLEFT => Some(BK::BracketLeft),
273 GK::BRACKETRIGHT => Some(BK::BracketRight),
274 GK::BACKSLASH => Some(BK::Backslash),
275 GK::QUOTELEFT => Some(BK::Backquote),
276 GK::MINUS => Some(BK::Minus),
277 GK::EQUAL => Some(BK::Equal),
278
279 _ => None, }
281}
282
283fn godot_mouse_to_bevy_mouse(godot_button: GodotMouseButton) -> BevyMouseButton {
284 match godot_button {
285 GodotMouseButton::Left => BevyMouseButton::Left,
286 GodotMouseButton::Right => BevyMouseButton::Right,
287 GodotMouseButton::Middle => BevyMouseButton::Middle,
288 GodotMouseButton::Extra1 => BevyMouseButton::Back,
289 GodotMouseButton::Extra2 => BevyMouseButton::Forward,
290 _ => BevyMouseButton::Other(255),
292 }
293}