keyboard-codes 0.3.0

Cross-platform keyboard key code mapping and conversion
Documentation
//! 游戏输入系统示例
//! 运行: cargo run --example game_input_system

// use keyboard_codes::*;
// use std::collections::HashMap;

use keyboard_codes::{
    current_platform, parse_keyboard_input, Key, KeyboardInput, Modifier, Platform,
};
use std::collections::HashMap;

#[derive(Debug, Clone, Copy, PartialEq)]
enum GameAction {
    MoveForward,
    MoveBackward,
    MoveLeft,
    MoveRight,
    Jump,
    Sprint,
    Crouch,
    Interact,
    Attack,
    Reload,
    Weapon1,
    Weapon2,
    Weapon3,
}

struct GameInputMapper {
    key_bindings: HashMap<Key, GameAction>,           // 普通键绑定
    modifier_bindings: HashMap<Modifier, GameAction>, // 修饰键绑定
    platform: Platform,
}

impl GameInputMapper {
    fn new(platform: Platform) -> Self {
        let mut key_bindings = HashMap::new();
        let mut modifier_bindings = HashMap::new();

        // 运动控制 - 普通键
        Self::add_key_binding(&mut key_bindings, "w", GameAction::MoveForward);
        Self::add_key_binding(&mut key_bindings, "s", GameAction::MoveBackward);
        Self::add_key_binding(&mut key_bindings, "a", GameAction::MoveLeft);
        Self::add_key_binding(&mut key_bindings, "d", GameAction::MoveRight);
        Self::add_key_binding(&mut key_bindings, "space", GameAction::Jump);

        // 交互控制
        Self::add_key_binding(&mut key_bindings, "e", GameAction::Interact);
        Self::add_key_binding(&mut key_bindings, "f", GameAction::Attack);
        Self::add_key_binding(&mut key_bindings, "r", GameAction::Reload);

        // 武器切换
        Self::add_key_binding(&mut key_bindings, "1", GameAction::Weapon1);
        Self::add_key_binding(&mut key_bindings, "2", GameAction::Weapon2);
        Self::add_key_binding(&mut key_bindings, "3", GameAction::Weapon3);

        // 修饰键绑定
        Self::add_modifier_binding(&mut modifier_bindings, "shift", GameAction::Sprint);
        Self::add_modifier_binding(&mut modifier_bindings, "ctrl", GameAction::Crouch);

        Self {
            key_bindings,
            modifier_bindings,
            platform,
        }
    }

    // 添加普通键绑定
    fn add_key_binding(bindings: &mut HashMap<Key, GameAction>, input: &str, action: GameAction) {
        match parse_keyboard_input(input) {
            Ok(KeyboardInput::Key(key)) => {
                bindings.insert(key, action);
                println!("  绑定: '{}' -> {:?}", input, action);
            }
            Ok(KeyboardInput::Modifier(_)) => {
                eprintln!("警告: '{}' 是修饰键,请使用 add_modifier_binding", input);
            }
            Err(e) => {
                eprintln!("警告: 无法解析键绑定 '{}': {}", input, e);
            }
        }
    }

    // 添加修饰键绑定
    fn add_modifier_binding(
        bindings: &mut HashMap<Modifier, GameAction>,
        input: &str,
        action: GameAction,
    ) {
        match parse_keyboard_input(input) {
            Ok(KeyboardInput::Modifier(modifier)) => {
                bindings.insert(modifier, action);
                println!("  绑定: '{}' -> {:?}", input, action);
            }
            Ok(KeyboardInput::Key(_)) => {
                eprintln!("警告: '{}' 是普通键,请使用 add_key_binding", input);
            }
            Err(e) => {
                eprintln!("警告: 无法解析修饰键绑定 '{}': {}", input, e);
            }
        }
    }

    fn handle_key_event(&self, vk_code: usize) -> Option<GameAction> {
        if let Some(keyboard_input) = KeyboardInput::from_code(vk_code, self.platform) {
            match keyboard_input {
                KeyboardInput::Key(key) => {
                    // 查找普通键绑定
                    if let Some(action) = self.key_bindings.get(&key) {
                        return Some(*action);
                    }
                }
                KeyboardInput::Modifier(modifier) => {
                    // 查找修饰键绑定
                    if let Some(action) = self.modifier_bindings.get(&modifier) {
                        return Some(*action);
                    }
                }
            }
        }
        None
    }

    fn list_bindings(&self) {
        println!("\n普通键绑定:");
        let mut keys: Vec<_> = self.key_bindings.iter().collect();
        keys.sort_by_key(|(key, _)| key.as_str());
        for (key, action) in keys {
            println!("  {:15} -> {:?}", key, action);
        }

        println!("\n修饰键绑定:");
        let mut modifiers: Vec<_> = self.modifier_bindings.iter().collect();
        modifiers.sort_by_key(|(modifier, _)| modifier.as_str());
        for (modifier, action) in modifiers {
            println!("  {:15} -> {:?}", modifier, action);
        }
    }

    // 处理组合键(例如:Shift + 某个键)
    fn handle_combo_event(
        &self,
        modifier_vks: &[usize],
        key_vk: usize,
    ) -> Option<(Vec<Modifier>, GameAction)> {
        let modifiers: Vec<Modifier> = modifier_vks
            .iter()
            .filter_map(|&code| {
                if let Some(KeyboardInput::Modifier(modifier)) =
                    KeyboardInput::from_code(code, self.platform)
                {
                    Some(modifier)
                } else {
                    None
                }
            })
            .collect();

        if let Some(KeyboardInput::Key(key)) = KeyboardInput::from_code(key_vk, self.platform) {
            if let Some(action) = self.key_bindings.get(&key) {
                return Some((modifiers, *action));
            }
        }

        None
    }
}

fn main() {
    println!("=== 游戏输入系统示例 ===\n");

    let platform = current_platform();
    println!("当前平台: {}", platform);

    let input_mapper = GameInputMapper::new(platform);

    input_mapper.list_bindings();

    println!("\n模拟按键事件 (Windows VK 代码):");
    let test_keys = [
        (0x57, "W"),     // W
        (0x41, "A"),     // A
        (0x20, "Space"), // Space
        (0x31, "1"),     // 1
        (0x10, "Shift"), // Shift
        (0x11, "Ctrl"),  // Ctrl
    ];

    for &(vk_code, desc) in &test_keys {
        if let Some(action) = input_mapper.handle_key_event(vk_code) {
            println!("  VK {:02X} ({:6}) -> {:?}", vk_code, desc, action);
        } else {
            println!("  VK {:02X} ({:6}) -> 无绑定", vk_code, desc);
        }
    }

    // 测试组合键
    println!("\n模拟组合键事件:");
    let combo_tests = [
        (vec![0x10], 0x57, "Shift + W"), // Shift + W
        (vec![0x11], 0x41, "Ctrl + A"),  // Ctrl + A
    ];

    for (modifiers, key, desc) in combo_tests {
        if let Some((active_modifiers, action)) = input_mapper.handle_combo_event(&modifiers, key) {
            let mod_names: Vec<String> = active_modifiers.iter().map(|m| m.to_string()).collect();
            println!("  {} -> {:?} (修饰键: {:?})", desc, action, mod_names);
        } else {
            println!("  {} -> 无绑定", desc);
        }
    }

    println!("\n示例完成!");
}