127 lines
4.1 KiB
Rust
127 lines
4.1 KiB
Rust
use prometeu_drivers::hardware::Hardware;
|
|
use prometeu_hal::InputSignals;
|
|
use winit::event::{ElementState, MouseButton, WindowEvent};
|
|
use winit::keyboard::{KeyCode, PhysicalKey};
|
|
use winit::window::Window;
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
struct FbViewport {
|
|
pub x: f32,
|
|
pub y: f32,
|
|
pub w: f32,
|
|
pub h: f32,
|
|
pub scale: f32,
|
|
}
|
|
|
|
impl FbViewport {
|
|
fn framebuffer_viewport(window: &Window) -> Option<FbViewport> {
|
|
let size = window.inner_size();
|
|
|
|
let win_w = size.width as f32;
|
|
let win_h = size.height as f32;
|
|
|
|
if win_w <= 0.0 || win_h <= 0.0 {
|
|
return None;
|
|
}
|
|
|
|
let fb_w = Hardware::W as f32;
|
|
let fb_h = Hardware::H as f32;
|
|
|
|
let scale_x = (win_w / fb_w).floor();
|
|
let scale_y = (win_h / fb_h).floor();
|
|
|
|
let scale = scale_x.min(scale_y).max(1.0);
|
|
|
|
let viewport_w = fb_w * scale;
|
|
let viewport_h = fb_h * scale;
|
|
|
|
let viewport_x = ((win_w - viewport_w) * 0.5).floor();
|
|
let viewport_y = ((win_h - viewport_h) * 0.5).floor();
|
|
|
|
Some(FbViewport { x: viewport_x, y: viewport_y, w: viewport_w, h: viewport_h, scale })
|
|
}
|
|
}
|
|
|
|
pub struct HostInputHandler {
|
|
pub signals: InputSignals,
|
|
}
|
|
|
|
impl Default for HostInputHandler {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
impl HostInputHandler {
|
|
pub fn new() -> Self {
|
|
Self { signals: InputSignals::default() }
|
|
}
|
|
|
|
pub fn handle_event(&mut self, event: &WindowEvent, window: &Window) {
|
|
match event {
|
|
WindowEvent::KeyboardInput { event, .. } => {
|
|
if let PhysicalKey::Code(code) = event.physical_key {
|
|
let is_down = event.state == ElementState::Pressed;
|
|
|
|
match code {
|
|
KeyCode::ArrowUp => self.signals.up_signal = is_down,
|
|
KeyCode::ArrowDown => self.signals.down_signal = is_down,
|
|
KeyCode::ArrowLeft => self.signals.left_signal = is_down,
|
|
KeyCode::ArrowRight => self.signals.right_signal = is_down,
|
|
|
|
KeyCode::KeyA => self.signals.a_signal = is_down,
|
|
KeyCode::KeyD => self.signals.b_signal = is_down,
|
|
KeyCode::KeyW => self.signals.x_signal = is_down,
|
|
KeyCode::KeyS => self.signals.y_signal = is_down,
|
|
KeyCode::KeyQ => self.signals.l_signal = is_down,
|
|
KeyCode::KeyE => self.signals.r_signal = is_down,
|
|
|
|
KeyCode::KeyZ => self.signals.start_signal = is_down,
|
|
KeyCode::ShiftLeft | KeyCode::ShiftRight => {
|
|
self.signals.select_signal = is_down
|
|
}
|
|
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
|
|
WindowEvent::CursorMoved { position, .. } => {
|
|
if let Some((x, y)) = window_to_fb(position.x as f32, position.y as f32, window) {
|
|
self.signals.x_pos = x;
|
|
self.signals.y_pos = y;
|
|
}
|
|
}
|
|
|
|
WindowEvent::MouseInput { state, button, .. } if *button == MouseButton::Left => {
|
|
match state {
|
|
ElementState::Pressed => {
|
|
self.signals.f_signal = true;
|
|
}
|
|
ElementState::Released => {
|
|
self.signals.f_signal = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
_ => {}
|
|
}
|
|
|
|
fn window_to_fb(wx: f32, wy: f32, window: &Window) -> Option<(i32, i32)> {
|
|
let viewport = FbViewport::framebuffer_viewport(window)?;
|
|
|
|
let local_x = wx - viewport.x;
|
|
let local_y = wy - viewport.y;
|
|
|
|
if local_x < 0.0 || local_y < 0.0 || local_x >= viewport.w || local_y >= viewport.h {
|
|
return None;
|
|
}
|
|
|
|
let fb_x = (local_x / viewport.scale).floor() as i32;
|
|
let fb_y = (local_y / viewport.scale).floor() as i32;
|
|
|
|
Some((fb_x.clamp(0, Hardware::W as i32 - 1), fb_y.clamp(0, Hardware::H as i32 - 1)))
|
|
}
|
|
}
|
|
}
|