shadowengine2d 2.0.0

A comprehensive 2D game engine built in Rust with ECS, rendering, audio, assets, animations, and scene management
Documentation
/*
 * MIT License
 * 
 * Copyright (c) 2025 ShadowEngine2D
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

use crate::math::Position;
use std::collections::HashSet;
use winit::event::{ElementState, MouseButton, WindowEvent};
use winit::keyboard::{KeyCode, PhysicalKey};

#[derive(Debug, Default)]
pub struct Input {

    keys_pressed: HashSet<KeyCode>,
    keys_just_pressed: HashSet<KeyCode>,
    keys_just_released: HashSet<KeyCode>,

    mouse_position: Position,
    mouse_buttons_pressed: HashSet<MouseButton>,
    mouse_buttons_just_pressed: HashSet<MouseButton>,
    mouse_buttons_just_released: HashSet<MouseButton>,
}

impl Input {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn new_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();
    }

    pub fn handle_event(&mut self, event: &WindowEvent) {
        match event {
            WindowEvent::KeyboardInput { event, .. } => {
                if let PhysicalKey::Code(keycode) = event.physical_key {
                    match event.state {
                        ElementState::Pressed => {
                            if !self.keys_pressed.contains(&keycode) {
                                self.keys_just_pressed.insert(keycode);
                            }
                            self.keys_pressed.insert(keycode);
                        }
                        ElementState::Released => {
                            self.keys_pressed.remove(&keycode);
                            self.keys_just_released.insert(keycode);
                        }
                    }
                }
            }
            WindowEvent::MouseInput { state, button, .. } => {
                match state {
                    ElementState::Pressed => {
                        if !self.mouse_buttons_pressed.contains(button) {
                            self.mouse_buttons_just_pressed.insert(*button);
                        }
                        self.mouse_buttons_pressed.insert(*button);
                    }
                    ElementState::Released => {
                        self.mouse_buttons_pressed.remove(button);
                        self.mouse_buttons_just_released.insert(*button);
                    }
                }
            }
            WindowEvent::CursorMoved { position, .. } => {
                self.mouse_position = Position::new(position.x as f32, position.y as f32);
            }
            _ => {}
        }
    }

    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 mouse_position(&self) -> Position {
        self.mouse_position
    }

    pub fn is_mouse_button_pressed(&self, button: MouseButton) -> bool {
        self.mouse_buttons_pressed.contains(&button)
    }

    pub fn is_mouse_button_just_pressed(&self, button: MouseButton) -> bool {
        self.mouse_buttons_just_pressed.contains(&button)
    }

    pub fn is_mouse_button_just_released(&self, button: MouseButton) -> bool {
        self.mouse_buttons_just_released.contains(&button)
    }

    pub fn is_arrow_key_pressed(&self, direction: ArrowKey) -> bool {
        let keycode = match direction {
            ArrowKey::Up => KeyCode::ArrowUp,
            ArrowKey::Down => KeyCode::ArrowDown,
            ArrowKey::Left => KeyCode::ArrowLeft,
            ArrowKey::Right => KeyCode::ArrowRight,
        };
        self.is_key_pressed(keycode)
    }

    pub fn is_wasd_pressed(&self, direction: ArrowKey) -> bool {
        let keycode = match direction {
            ArrowKey::Up => KeyCode::KeyW,
            ArrowKey::Down => KeyCode::KeyS,
            ArrowKey::Left => KeyCode::KeyA,
            ArrowKey::Right => KeyCode::KeyD,
        };
        self.is_key_pressed(keycode)
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ArrowKey {
    Up,
    Down,
    Left,
    Right,
}