moltrun 1.7.2

High-performance game engine library with AI capabilities, built on wgpu for modern 3D graphics and physics simulation
Documentation
````markdown
# Input - 입력 관리 서브시스템

**"윈도우 이벤트에서 게임 입력으로"**를 담당하는 입력 처리 계층입니다.

## 📦 모듈 구성

### `manager.rs`
- **`InputManager`**: 입력의 최상위 관리자
- winit 이벤트를 InputState로 변환
- 프레임 단위 입력 상태 관리
- Engine이 직접 소유하는 유일 인스턴스

```rust
let mut input_manager = InputManager::new();

// 이벤트 처리
input_manager.process_window_event(&event);

// 상태 조회
if input_manager.state().is_key_down(KeyCode::KeyW) {
    // 앞으로 이동
}
```

## 🎯 설계 철학

### 유일 인스턴스 (Singleton-like)
`InputManager`는 Engine이 단 하나만 소유하며, 모든 입력 처리를 중앙화합니다.

```
Engine
└── InputManager (1개)
    └── state: InputState
        ├── keys_down: HashSet<KeyCode>
        ├── keys_pressed_this_frame: HashSet<KeyCode>
        ├── mouse_position: Vec2
        └── mouse_buttons_down: HashSet<MouseButton>
```

### Polling 방식
매 프레임마다 현재 입력 상태를 조회하는 방식으로 게임 로직에 적합합니다.

```rust
// 연속 입력 (이동, 조작)
if input.is_key_down(KeyCode::KeyW) {
    position.y -= speed * delta_time;  // 매 프레임 실행
}

// 단일 입력 (점프, 공격)
if input.is_key_just_pressed(KeyCode::Space) {
    jump();  // 1프레임만 실행
}
```

### 계층 구조
```
core/input.rs          (추상 - 입력 상태 정의)
runtime/input/         (구현 - 입력 이벤트 관리)
    └── manager.rs
```

## 📊 입력 처리 흐름

### 전체 파이프라인
```
1. OS 키보드 이벤트
   2. winit::WindowEvent::KeyboardInput
   3. preview_runner (이벤트 루프)
   └─ 이벤트 필터링
   4. Engine::handle_window_event(&event)
   5. InputManager::process_window_event(event)
   ├─ process_keyboard()
   ├─ process_mouse_move()
   ├─ process_mouse_button()
   └─ process_mouse_wheel()
   6. InputState 업데이트
   ├─ keys_down.insert()
   ├─ keys_pressed_this_frame.insert()
   └─ mouse_position = new_pos
   7. Engine::update(delta_time)
   ├─ input_manager.begin_frame()
   ├─ world.update(dt, &input_state)
   │   └─ System들이 input 참조
   │       └─ context.input.is_key_down()
   └─ input_manager.end_frame()
```

### 프레임 관리
```rust
// 프레임 시작
input_manager.begin_frame();
// → keys_pressed_this_frame.clear()
// → mouse_buttons_pressed_this_frame.clear()

// 게임 로직 실행
world.update(dt, input_manager.state());

// 프레임 종료
input_manager.end_frame();
// → mouse_delta = Vec2::zero()
// → mouse_wheel_delta = 0.0
```

## 🔗 관련 계층

- **`core/input.rs`**: `InputState` 정의 (추상 계층)
- **`core/system.rs`**: `SystemContext``InputState` 참조 포함
- **`runtime/input/manager.rs`**: `InputManager` 구현 (이 파일)
- **`runtime/engine.rs`**: `InputManager` 소유 및 관리
- **`systems/`**: 모든 System이 `context.input` 사용 가능

## 🚀 사용 예시

### InputManager 생성 (Engine 내부)
```rust
let input_manager = InputManager::new();
```

### 이벤트 처리 (Engine)
```rust
impl Engine {
    pub fn handle_window_event(&mut self, event: &WindowEvent) {
        self.input_manager.process_window_event(event);
    }
}
```

### 게임 루프 (Engine::update)
```rust
pub fn update(&mut self, delta_time: f32) -> Result<(), SystemError> {
    self.input_manager.begin_frame();
    
    // World에 InputState 참조 전달
    self.world.update(delta_time, self.input_manager.state())?;
    
    self.input_manager.end_frame();
    Ok(())
}
```

### System에서 입력 사용
```rust
use moltrun_core::core::{System, SystemContext, SystemError};
use winit::keyboard::KeyCode;

pub struct PlayerMovementSystem {
    pub speed: f32,
}

impl System for PlayerMovementSystem {
    fn update(&mut self, context: &mut SystemContext) -> Result<(), SystemError> {
        let input = context.input;
        let dt = context.delta_time;
        
        for entity in context.entities.iter_mut() {
            if let Some(transform) = entity.get_component_mut::<Transform>() {
                // 연속 입력 (WASD)
                if input.is_key_down(KeyCode::KeyW) {
                    transform.position.y -= self.speed * dt;
                }
                if input.is_key_down(KeyCode::KeyS) {
                    transform.position.y += self.speed * dt;
                }
                if input.is_key_down(KeyCode::KeyA) {
                    transform.position.x -= self.speed * dt;
                }
                if input.is_key_down(KeyCode::KeyD) {
                    transform.position.x += self.speed * dt;
                }
                
                // 단일 입력 (Space)
                if input.is_key_just_pressed(KeyCode::Space) {
                    println!("Jump!");
                }
            }
        }
        Ok(())
    }
    
    fn as_any(&self) -> &dyn std::any::Any { self }
    fn as_any_mut(&mut self) -> &mut dyn std::any::Any { self }
}
```

### 마우스 입력 사용
```rust
impl System for CameraSystem {
    fn update(&mut self, context: &mut SystemContext) -> Result<(), SystemError> {
        let input = context.input;
        
        // 마우스 위치
        let mouse_pos = input.mouse_position();
        
        // 마우스 이동량 (드래그)
        if input.is_mouse_button_down(MouseButton::Left) {
            let delta = input.mouse_delta();
            camera.position += delta;
        }
        
        // 마우스 휠 (줌)
        let wheel = input.mouse_wheel_delta();
        if wheel != 0.0 {
            camera.zoom += wheel * 0.1;
        }
        
        Ok(())
    }
}
```

## 💡 Polling API 정리

### 키보드
```rust
// 연속 입력 (누르고 있는 동안 매 프레임 true)
input.is_key_down(KeyCode::KeyW) -> bool

// 단일 입력 (눌린 첫 프레임만 true)
input.is_key_just_pressed(KeyCode::Space) -> bool

// 떼는 순간 (떼진 프레임만 true)
input.is_key_just_released(KeyCode::Escape) -> bool
```

### 마우스
```rust
// 현재 위치 (픽셀 좌표)
input.mouse_position() -> Vec2

// 이번 프레임 이동량
input.mouse_delta() -> Vec2

// 마우스 버튼
input.is_mouse_button_down(MouseButton::Left) -> bool
input.is_mouse_button_just_pressed(MouseButton::Right) -> bool
input.is_mouse_button_just_released(MouseButton::Middle) -> bool

// 휠 스크롤 (양수: 위, 음수: 아래)
input.mouse_wheel_delta() -> f32
```

## ⚡ 성능 최적화

### HashSet 사용
키 상태를 HashSet으로 관리하여 O(1) 조회 성능 보장

```rust
// O(1) 시간복잡도
if input.is_key_down(KeyCode::KeyW) { ... }
```

### 프레임별 초기화
불필요한 메모리 유지를 방지

```rust
// begin_frame(): just_pressed 플래그만 clear (작은 HashSet)
// end_frame(): delta 값만 0으로 초기화 (Vec2, f32)
```

### 참조 전달
InputState를 복사하지 않고 불변 참조로 공유

```rust
// ✅ 복사 없음
world.update(dt, &input_state);

// ❌ 불필요한 복사
world.update(dt, input_state.clone());
```

## ⚠️ 주의사항

### just_pressed vs down
```rust
// ✅ 올바름: 이동은 is_key_down (연속)
if input.is_key_down(KeyCode::KeyW) {
    position.y -= speed * dt;  // 매 프레임 이동
}

// ❌ 잘못됨: 이동에 just_pressed 사용
if input.is_key_just_pressed(KeyCode::KeyW) {
    position.y -= speed * dt;  // 1프레임만 이동 (버그!)
}
```

```rust
// ✅ 올바름: 점프는 is_key_just_pressed (단일)
if input.is_key_just_pressed(KeyCode::Space) {
    apply_jump_force();  // 1번만 실행
}

// ❌ 잘못됨: 점프에 is_key_down 사용
if input.is_key_down(KeyCode::Space) {
    apply_jump_force();  // 매 프레임 실행 (버그!)
}
```

### begin_frame / end_frame 호출
```rust
// ✅ 올바름: Engine::update()에서 호출
pub fn update(&mut self, dt: f32) {
    self.input_manager.begin_frame();  // 필수!
    self.world.update(dt, self.input_manager.state())?;
    self.input_manager.end_frame();    // 필수!
}

// ❌ 잘못됨: 호출하지 않으면 just_pressed가 계속 true
pub fn update(&mut self, dt: f32) {
    self.world.update(dt, self.input_manager.state())?;
    // → 버그: just_pressed가 clear되지 않음
}
```

## 🔮 향후 확장 가능성

### 입력 매핑 시스템
```rust
// 키를 액션에 매핑
input_manager.map_key(KeyCode::KeyW, "Move Forward");
if input.is_action_pressed("Move Forward") { ... }
```

### Event 방식 추가 (UI용)
```rust
// Polling과 병행하여 Event 큐 추가
for event in input.poll_events() {
    match event {
        InputEvent::KeyPressed(KeyCode::Enter) => submit_form(),
        InputEvent::TextInput(ch) => text_field.insert(ch),
    }
}
```