325e278af1
Add plugin skeleton with versioned skill directories, TODO SKILL.md scaffolds with goals for skill-creator, and copy over bevy-skill-research reports from spacecraft into docs/workpad/research/.
100 lines
3.4 KiB
Markdown
100 lines
3.4 KiB
Markdown
# Bevy Skill Research: Input System
|
|
|
|
> **Bevy version**: 0.18, with 0.19 notes
|
|
> **Date**: 2026-07-07
|
|
|
|
## Keyboard Input (`Res<ButtonInput<KeyCode>>`)
|
|
|
|
| Method | Returns | Purpose |
|
|
|--------|---------|---------|
|
|
| `pressed(KeyCode)` | `bool` | Held this frame |
|
|
| `just_pressed(KeyCode)` | `bool` | First frame pressed |
|
|
| `just_released(KeyCode)` | `bool` | First frame released |
|
|
| `any_pressed(impl IntoIterator)` | `bool` | Any of these held |
|
|
| `any_just_pressed(...)` | `bool` | Any of these just pressed |
|
|
| `all_pressed(...)` | `bool` | All of these held |
|
|
| `get_pressed()` | `impl Iterator` | Iterate all held keys |
|
|
| `get_just_pressed()` | `impl Iterator` | Iterate newly pressed |
|
|
| `clear_just_pressed(KeyCode)` | `bool` | Consume the event |
|
|
|
|
Also available: `ButtonInput<Key>` for logical/locale-aware keys.
|
|
|
|
Updated by `keyboard_input_system` from `KeyboardInput` events.
|
|
|
|
## Mouse Input
|
|
|
|
**Buttons**: `Res<ButtonInput<MouseButton>>` — same API as keyboard.
|
|
Variants: `Left`, `Right`, `Middle`, `Back`, `Forward`, `Other(u16)`.
|
|
|
|
**Motion**:
|
|
| Type | Kind | Purpose |
|
|
|------|------|---------|
|
|
| `MouseMotion` | Event | `delta: Vec2` per raw motion event |
|
|
| `AccumulatedMouseMotion` | Resource | Total delta this frame, reset each frame |
|
|
| `MouseWheel` | Event | Scroll with `MouseScrollUnit` (Line/Pixel) |
|
|
| `AccumulatedMouseScroll` | Resource | Total scroll this frame |
|
|
|
|
**Cursor position**: Read from `Window` component:
|
|
```rust
|
|
fn cursor(windows: Query<&Window>) {
|
|
if let Ok(window) = windows.single() {
|
|
if let Some(pos) = window.cursor_position() {
|
|
// pos is Vec2 in logical pixels, origin top-left
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Gamepad Input
|
|
|
|
**Buttons**: `Res<ButtonInput<GamepadButton>>` — same pressed/just_pressed API.
|
|
|
|
**Axes**: `Res<Axis<GamepadAxis>>`:
|
|
- `get(GamepadAxis) -> Option<f32>` — range `[-1.0, 1.0]`
|
|
- `GamepadButton` mapped range `[0.0, 1.0]` (triggers are analog)
|
|
|
|
**Events**: `GamepadButtonStateChangedEvent`, `GamepadButtonChangedEvent`, `GamepadAxisChangedEvent`, `GamepadConnectionEvent`.
|
|
|
|
**Settings**: `GamepadSettings` component for deadzone/threshold configuration.
|
|
|
|
## Touch Input
|
|
|
|
- `TouchInput` (Event) — touch event with `TouchPhase` (Began/Moved/Ended)
|
|
- `Touches` (Resource) — query active touches, analogous to ButtonInput pattern
|
|
- `ForceTouch` — pressure-sensitive data on supported devices
|
|
- Requires `touch` feature flag in 0.18
|
|
|
|
## Action Mapping
|
|
|
|
No built-in action mapping system in Bevy 0.18. Community crate `leafwing-input-manager` fills this role.
|
|
|
|
## 0.18 Change
|
|
|
|
Input sources (`mouse`, `keyboard`, `gamepad`, `touch`, `gestures`) are now **feature-gated**. Enabled by default with `bevy_window`/`bevy_gilrs`, but must be explicit with `default-features = false`.
|
|
|
|
## Common Patterns
|
|
|
|
```rust
|
|
fn movement(
|
|
keys: Res<ButtonInput<KeyCode>>,
|
|
mouse: Res<ButtonInput<MouseButton>>,
|
|
) {
|
|
if keys.just_pressed(KeyCode::Space) { /* fire */ }
|
|
if mouse.pressed(MouseButton::Left) { /* hold fire */ }
|
|
|
|
let mut dir = Vec3::ZERO;
|
|
if keys.pressed(KeyCode::KeyW) { dir.z -= 1.0; }
|
|
if keys.pressed(KeyCode::KeyS) { dir.z += 1.0; }
|
|
if keys.pressed(KeyCode::KeyA) { dir.x -= 1.0; }
|
|
if keys.pressed(KeyCode::KeyD) { dir.x += 1.0; }
|
|
}
|
|
|
|
fn read_motion(mut motion: MessageReader<MouseMotion>) {
|
|
for ev in motion.read() {
|
|
// ev.delta.x, ev.delta.y
|
|
}
|
|
}
|
|
```
|
|
|
|
Note: `MouseMotion` uses `MessageReader` (not `EventReader`) in 0.18+.
|