sevenx_engine 0.2.11

Engine de jogos 2D/3D completa com suporte Android, física, áudio, partículas, tilemap, UI, eventos e sistema 3D avançado com PBR.
Documentation
use std::collections::HashSet;
use winit::event::{ElementState, KeyEvent, WindowEvent, MouseButton, MouseScrollDelta};
use winit::keyboard::{KeyCode, PhysicalKey};

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum MouseBtn {
    Left,
    Right,
    Middle,
    Other(u16),
}

impl From<MouseButton> for MouseBtn {
    fn from(button: MouseButton) -> Self {
        match button {
            MouseButton::Left => MouseBtn::Left,
            MouseButton::Right => MouseBtn::Right,
            MouseButton::Middle => MouseBtn::Middle,
            MouseButton::Back => MouseBtn::Other(3),
            MouseButton::Forward => MouseBtn::Other(4),
            MouseButton::Other(id) => MouseBtn::Other(id),
        }
    }
}

pub struct InputHandler {
    // Teclado
    keys_pressed: HashSet<KeyCode>,
    keys_just_pressed: HashSet<KeyCode>,
    keys_just_released: HashSet<KeyCode>,
    
    // Mouse
    pub mouse_delta: (f64, f64),
    pub mouse_position: (f64, f64),
    last_mouse_position: Option<(f64, f64)>,
    mouse_buttons: HashSet<MouseBtn>,
    mouse_buttons_just_pressed: HashSet<MouseBtn>,
    mouse_buttons_just_released: HashSet<MouseBtn>,
    pub mouse_wheel_delta: f32,
    
    // Estado
    pub mouse_locked: bool,
    pub mouse_visible: bool,
}

impl InputHandler {
    pub fn new() -> Self {
        Self {
            keys_pressed: HashSet::new(),
            keys_just_pressed: HashSet::new(),
            keys_just_released: HashSet::new(),
            mouse_delta: (0.0, 0.0),
            mouse_position: (0.0, 0.0),
            last_mouse_position: None,
            mouse_buttons: HashSet::new(),
            mouse_buttons_just_pressed: HashSet::new(),
            mouse_buttons_just_released: HashSet::new(),
            mouse_wheel_delta: 0.0,
            mouse_locked: false,
            mouse_visible: true,
        }
    }
    
    pub fn begin_frame(&mut self) {
        self.keys_just_pressed.clear();
        self.keys_just_released.clear();
        self.mouse_buttons_just_pressed.clear();
        self.mouse_buttons_just_released.clear();
        self.mouse_wheel_delta = 0.0;
        self.mouse_delta = (0.0, 0.0);
    }

    pub fn update(&mut self, event: &WindowEvent) {
        match event {
            WindowEvent::KeyboardInput {
                event:
                    KeyEvent {
                        physical_key: PhysicalKey::Code(keycode),
                        state,
                        ..
                    },
                ..
            } => {
                match state {
                    ElementState::Pressed => {
                        if self.keys_pressed.insert(*keycode) {
                            self.keys_just_pressed.insert(*keycode);
                        }
                    }
                    ElementState::Released => {
                        self.keys_pressed.remove(keycode);
                        self.keys_just_released.insert(*keycode);
                    }
                }
            }
            WindowEvent::CursorMoved { position, .. } => {
                self.mouse_position = (position.x, position.y);
                
                if let Some(last_pos) = self.last_mouse_position {
                    self.mouse_delta = (
                        position.x - last_pos.0,
                        position.y - last_pos.1,
                    );
                } else {
                    self.mouse_delta = (0.0, 0.0);
                }
                
                self.last_mouse_position = Some((position.x, position.y));
            }
            WindowEvent::MouseInput { state, button, .. } => {
                let btn = MouseBtn::from(*button);
                match state {
                    ElementState::Pressed => {
                        if self.mouse_buttons.insert(btn) {
                            self.mouse_buttons_just_pressed.insert(btn);
                        }
                    }
                    ElementState::Released => {
                        self.mouse_buttons.remove(&btn);
                        self.mouse_buttons_just_released.insert(btn);
                    }
                }
            }
            WindowEvent::MouseWheel { delta, .. } => {
                match delta {
                    MouseScrollDelta::LineDelta(_x, y) => {
                        self.mouse_wheel_delta = *y;
                    }
                    MouseScrollDelta::PixelDelta(pos) => {
                        self.mouse_wheel_delta = pos.y as f32 / 100.0;
                    }
                }
            }
            _ => {}
        }
    }

    // Teclado
    pub fn is_key_pressed(&self, keycode: KeyCode) -> bool {
        self.keys_pressed.contains(&keycode)
    }
    
    pub fn is_key_just_pressed(&self, keycode: KeyCode) -> bool {
        self.keys_just_pressed.contains(&keycode)
    }
    
    pub fn is_key_just_released(&self, keycode: KeyCode) -> bool {
        self.keys_just_released.contains(&keycode)
    }
    
    pub fn any_key_pressed(&self) -> bool {
        !self.keys_pressed.is_empty()
    }
    
    pub fn get_pressed_keys(&self) -> Vec<KeyCode> {
        self.keys_pressed.iter().copied().collect()
    }

    // Mouse - Posição e Delta
    pub fn reset_mouse_delta(&mut self) {
        self.mouse_delta = (0.0, 0.0);
    }

    pub fn get_mouse_delta(&self) -> (f64, f64) {
        self.mouse_delta
    }

    pub fn get_mouse_position(&self) -> (f64, f64) {
        self.mouse_position
    }
    
    pub fn get_mouse_x(&self) -> f64 {
        self.mouse_position.0
    }
    
    pub fn get_mouse_y(&self) -> f64 {
        self.mouse_position.1
    }
    
    // Mouse - Botões
    pub fn is_mouse_button_pressed(&self, button: MouseBtn) -> bool {
        self.mouse_buttons.contains(&button)
    }
    
    pub fn is_mouse_button_just_pressed(&self, button: MouseBtn) -> bool {
        self.mouse_buttons_just_pressed.contains(&button)
    }
    
    pub fn is_mouse_button_just_released(&self, button: MouseBtn) -> bool {
        self.mouse_buttons_just_released.contains(&button)
    }
    
    pub fn is_left_mouse_just_released(&self) -> bool {
        self.is_mouse_button_just_released(MouseBtn::Left)
    }
    
    pub fn is_right_mouse_just_released(&self) -> bool {
        self.is_mouse_button_just_released(MouseBtn::Right)
    }
    
    pub fn is_left_mouse_pressed(&self) -> bool {
        self.is_mouse_button_pressed(MouseBtn::Left)
    }
    
    pub fn is_right_mouse_pressed(&self) -> bool {
        self.is_mouse_button_pressed(MouseBtn::Right)
    }
    
    pub fn is_middle_mouse_pressed(&self) -> bool {
        self.is_mouse_button_pressed(MouseBtn::Middle)
    }
    
    pub fn is_left_mouse_just_pressed(&self) -> bool {
        self.is_mouse_button_just_pressed(MouseBtn::Left)
    }
    
    pub fn is_right_mouse_just_pressed(&self) -> bool {
        self.is_mouse_button_just_pressed(MouseBtn::Right)
    }
    
    // Mouse - Scroll
    pub fn get_mouse_wheel_delta(&self) -> f32 {
        self.mouse_wheel_delta
    }
    
    pub fn is_scrolling_up(&self) -> bool {
        self.mouse_wheel_delta > 0.0
    }
    
    pub fn is_scrolling_down(&self) -> bool {
        self.mouse_wheel_delta < 0.0
    }
    
    // Atalhos úteis
    pub fn is_ctrl_pressed(&self) -> bool {
        self.is_key_pressed(KeyCode::ControlLeft) || self.is_key_pressed(KeyCode::ControlRight)
    }
    
    pub fn is_shift_pressed(&self) -> bool {
        self.is_key_pressed(KeyCode::ShiftLeft) || self.is_key_pressed(KeyCode::ShiftRight)
    }
    
    pub fn is_alt_pressed(&self) -> bool {
        self.is_key_pressed(KeyCode::AltLeft) || self.is_key_pressed(KeyCode::AltRight)
    }
    
    // Direções (WASD e Setas)
    pub fn get_axis_horizontal(&self) -> f32 {
        let mut axis = 0.0;
        if self.is_key_pressed(KeyCode::KeyA) || self.is_key_pressed(KeyCode::ArrowLeft) {
            axis -= 1.0;
        }
        if self.is_key_pressed(KeyCode::KeyD) || self.is_key_pressed(KeyCode::ArrowRight) {
            axis += 1.0;
        }
        axis
    }
    
    pub fn get_axis_vertical(&self) -> f32 {
        let mut axis = 0.0;
        if self.is_key_pressed(KeyCode::KeyW) || self.is_key_pressed(KeyCode::ArrowUp) {
            axis -= 1.0;
        }
        if self.is_key_pressed(KeyCode::KeyS) || self.is_key_pressed(KeyCode::ArrowDown) {
            axis += 1.0;
        }
        axis
    }
    
    pub fn get_movement_vector(&self) -> (f32, f32) {
        (self.get_axis_horizontal(), self.get_axis_vertical())
    }
    
    // 🆕 v0.2.9 - Android Touch Support
    #[cfg(target_os = "android")]
    pub fn process_touch(&mut self, event: &WindowEvent) {
        use winit::event::Touch;
        
        match event {
            WindowEvent::Touch(Touch { phase, location, id, .. }) => {
                use winit::event::TouchPhase;
                
                let touch_point = crate::android::TouchPoint {
                    id: *id,
                    x: location.x as f32,
                    y: location.y as f32,
                    pressure: 1.0,
                };
                
                let touch_phase = match phase {
                    TouchPhase::Started => crate::android::TouchPhase::Started,
                    TouchPhase::Moved => crate::android::TouchPhase::Moved,
                    TouchPhase::Ended => crate::android::TouchPhase::Ended,
                    TouchPhase::Cancelled => crate::android::TouchPhase::Cancelled,
                };
                
                let touch_event = crate::android::TouchEvent {
                    point: touch_point,
                    phase: touch_phase,
                };
                
                // Aqui você pode processar o evento de touch
                // Por exemplo, armazenar em um buffer para processar depois
            }
            _ => {}
        }
    }
}