use bevy_app::{App, First, Last, Plugin};
use bevy_ecs::{
entity::Entity,
message::{MessageReader, MessageWriter},
system::ResMut,
};
use bevy_input::{
ButtonInput, ButtonState, InputPlugin,
gestures::PanGesture as BevyPanGesture,
keyboard::KeyCode,
mouse::{
MouseButton as BevyMouseButton, MouseButtonInput as BevyMouseButtonInput,
MouseMotion as BevyMouseMotion, MouseScrollUnit, MouseWheel as BevyMouseWheel,
},
};
use crate::plugins::input::events::{
KeyboardInput as GodotKeyboardInput, MouseButton as GodotMouseButton,
MouseButtonInput as GodotMouseButtonInput, MouseMotion as GodotMouseMotion,
PanGestureInput as GodotPanGestureInput,
};
#[derive(Default)]
pub struct BevyInputBridgePlugin;
impl Plugin for BevyInputBridgePlugin {
fn build(&self, app: &mut App) {
app.add_plugins(super::events::GodotInputEventPlugin)
.add_plugins(InputPlugin)
.add_systems(
First,
(
bridge_keyboard_input,
bridge_mouse_button_input,
bridge_mouse_motion,
bridge_mouse_scroll,
bridge_pan_gesture,
),
)
.add_systems(Last, clear_keyboard_input);
}
}
fn bridge_keyboard_input(
mut keyboard_messages: MessageReader<GodotKeyboardInput>,
mut key_code_input: ResMut<ButtonInput<KeyCode>>,
) {
for message in keyboard_messages.read() {
if let Some(bevy_key_code) = godot_key_to_bevy_keycode(message.keycode) {
if message.pressed {
key_code_input.press(bevy_key_code);
} else {
key_code_input.release(bevy_key_code);
}
}
}
}
fn bridge_mouse_button_input(
mut mouse_messages: MessageReader<GodotMouseButtonInput>,
mut bevy_mouse_button_messages: MessageWriter<BevyMouseButtonInput>,
) {
for message in mouse_messages.read() {
if matches!(
message.button,
GodotMouseButton::WheelUp
| GodotMouseButton::WheelDown
| GodotMouseButton::WheelLeft
| GodotMouseButton::WheelRight
) {
continue;
}
let bevy_button = godot_mouse_to_bevy_mouse(message.button);
let state = if message.pressed {
ButtonState::Pressed
} else {
ButtonState::Released
};
bevy_mouse_button_messages.write(BevyMouseButtonInput {
button: bevy_button,
state,
window: Entity::PLACEHOLDER,
});
}
}
fn bridge_mouse_motion(
mut mouse_motion_messages: MessageReader<GodotMouseMotion>,
mut bevy_mouse_motion_messages: MessageWriter<BevyMouseMotion>,
) {
for event in mouse_motion_messages.read() {
bevy_mouse_motion_messages.write(BevyMouseMotion { delta: event.delta });
}
}
fn bridge_mouse_scroll(
mut mouse_button_messages: MessageReader<GodotMouseButtonInput>,
mut bevy_mouse_scroll_messages: MessageWriter<BevyMouseWheel>,
) {
for message in mouse_button_messages.read() {
match message.button {
GodotMouseButton::WheelUp => {
bevy_mouse_scroll_messages.write(BevyMouseWheel {
x: 0.0,
y: message.factor,
unit: MouseScrollUnit::Line,
window: Entity::PLACEHOLDER,
});
}
GodotMouseButton::WheelDown => {
bevy_mouse_scroll_messages.write(BevyMouseWheel {
x: 0.0,
y: -message.factor,
unit: MouseScrollUnit::Line,
window: Entity::PLACEHOLDER,
});
}
GodotMouseButton::WheelLeft => {
bevy_mouse_scroll_messages.write(BevyMouseWheel {
x: -message.factor,
y: 0.0,
unit: MouseScrollUnit::Line,
window: Entity::PLACEHOLDER,
});
}
GodotMouseButton::WheelRight => {
bevy_mouse_scroll_messages.write(BevyMouseWheel {
x: message.factor,
y: 0.0,
unit: MouseScrollUnit::Line,
window: Entity::PLACEHOLDER,
});
}
_ => {} }
}
}
fn bridge_pan_gesture(
mut pan_messages: MessageReader<GodotPanGestureInput>,
mut bevy_pan_messages: MessageWriter<BevyPanGesture>,
) {
for event in pan_messages.read() {
bevy_pan_messages.write(BevyPanGesture(event.delta));
}
}
fn clear_keyboard_input(mut keyboard_input: ResMut<ButtonInput<KeyCode>>) {
keyboard_input.clear();
}
fn godot_key_to_bevy_keycode(godot_key: godot::global::Key) -> Option<KeyCode> {
use KeyCode as BK;
use godot::global::Key as GK;
match godot_key {
GK::A => Some(BK::KeyA),
GK::B => Some(BK::KeyB),
GK::C => Some(BK::KeyC),
GK::D => Some(BK::KeyD),
GK::E => Some(BK::KeyE),
GK::F => Some(BK::KeyF),
GK::G => Some(BK::KeyG),
GK::H => Some(BK::KeyH),
GK::I => Some(BK::KeyI),
GK::J => Some(BK::KeyJ),
GK::K => Some(BK::KeyK),
GK::L => Some(BK::KeyL),
GK::M => Some(BK::KeyM),
GK::N => Some(BK::KeyN),
GK::O => Some(BK::KeyO),
GK::P => Some(BK::KeyP),
GK::Q => Some(BK::KeyQ),
GK::R => Some(BK::KeyR),
GK::S => Some(BK::KeyS),
GK::T => Some(BK::KeyT),
GK::U => Some(BK::KeyU),
GK::V => Some(BK::KeyV),
GK::W => Some(BK::KeyW),
GK::X => Some(BK::KeyX),
GK::Y => Some(BK::KeyY),
GK::Z => Some(BK::KeyZ),
GK::KEY_0 => Some(BK::Digit0),
GK::KEY_1 => Some(BK::Digit1),
GK::KEY_2 => Some(BK::Digit2),
GK::KEY_3 => Some(BK::Digit3),
GK::KEY_4 => Some(BK::Digit4),
GK::KEY_5 => Some(BK::Digit5),
GK::KEY_6 => Some(BK::Digit6),
GK::KEY_7 => Some(BK::Digit7),
GK::KEY_8 => Some(BK::Digit8),
GK::KEY_9 => Some(BK::Digit9),
GK::SPACE => Some(BK::Space),
GK::ENTER => Some(BK::Enter),
GK::ESCAPE => Some(BK::Escape),
GK::BACKSPACE => Some(BK::Backspace),
GK::TAB => Some(BK::Tab),
GK::SHIFT => Some(BK::ShiftLeft),
GK::CTRL => Some(BK::ControlLeft),
GK::ALT => Some(BK::AltLeft),
GK::LEFT => Some(BK::ArrowLeft),
GK::RIGHT => Some(BK::ArrowRight),
GK::UP => Some(BK::ArrowUp),
GK::DOWN => Some(BK::ArrowDown),
GK::F1 => Some(BK::F1),
GK::F2 => Some(BK::F2),
GK::F3 => Some(BK::F3),
GK::F4 => Some(BK::F4),
GK::F5 => Some(BK::F5),
GK::F6 => Some(BK::F6),
GK::F7 => Some(BK::F7),
GK::F8 => Some(BK::F8),
GK::F9 => Some(BK::F9),
GK::F10 => Some(BK::F10),
GK::F11 => Some(BK::F11),
GK::F12 => Some(BK::F12),
GK::KP_0 => Some(BK::Numpad0),
GK::KP_1 => Some(BK::Numpad1),
GK::KP_2 => Some(BK::Numpad2),
GK::KP_3 => Some(BK::Numpad3),
GK::KP_4 => Some(BK::Numpad4),
GK::KP_5 => Some(BK::Numpad5),
GK::KP_6 => Some(BK::Numpad6),
GK::KP_7 => Some(BK::Numpad7),
GK::KP_8 => Some(BK::Numpad8),
GK::KP_9 => Some(BK::Numpad9),
GK::KP_ADD => Some(BK::NumpadAdd),
GK::KP_SUBTRACT => Some(BK::NumpadSubtract),
GK::KP_MULTIPLY => Some(BK::NumpadMultiply),
GK::KP_DIVIDE => Some(BK::NumpadDivide),
GK::KP_PERIOD => Some(BK::NumpadDecimal),
GK::KP_ENTER => Some(BK::NumpadEnter),
GK::DELETE => Some(BK::Delete),
GK::INSERT => Some(BK::Insert),
GK::HOME => Some(BK::Home),
GK::END => Some(BK::End),
GK::PAGEUP => Some(BK::PageUp),
GK::PAGEDOWN => Some(BK::PageDown),
GK::CAPSLOCK => Some(BK::CapsLock),
GK::NUMLOCK => Some(BK::NumLock),
GK::SCROLLLOCK => Some(BK::ScrollLock),
GK::PAUSE => Some(BK::Pause),
GK::PRINT => Some(BK::PrintScreen),
GK::COMMA => Some(BK::Comma),
GK::PERIOD => Some(BK::Period),
GK::SLASH => Some(BK::Slash),
GK::SEMICOLON => Some(BK::Semicolon),
GK::APOSTROPHE => Some(BK::Quote),
GK::BRACKETLEFT => Some(BK::BracketLeft),
GK::BRACKETRIGHT => Some(BK::BracketRight),
GK::BACKSLASH => Some(BK::Backslash),
GK::QUOTELEFT => Some(BK::Backquote),
GK::MINUS => Some(BK::Minus),
GK::EQUAL => Some(BK::Equal),
_ => None, }
}
fn godot_mouse_to_bevy_mouse(godot_button: GodotMouseButton) -> BevyMouseButton {
match godot_button {
GodotMouseButton::Left => BevyMouseButton::Left,
GodotMouseButton::Right => BevyMouseButton::Right,
GodotMouseButton::Middle => BevyMouseButton::Middle,
GodotMouseButton::Extra1 => BevyMouseButton::Back,
GodotMouseButton::Extra2 => BevyMouseButton::Forward,
_ => BevyMouseButton::Other(255),
}
}