Files
WV-Core/INPUT_API.md

547 lines
13 KiB
Markdown

# WillowVox Input API Documentation
The WillowVox engine provides a Unity-like input system that abstracts platform-specific input into a consistent API. All input is handled through three main classes:
## Core Classes
### 1. **InputManager** - Main Input API
The primary interface for all input queries. Works across all platforms (PC, mobile, consoles).
### 2. **GamepadInput** - Gamepad-Specific Features
Advanced gamepad features like individual stick values, triggers, and vibration.
### 3. **TouchInput** - Touch-Specific Features
Multi-touch support for mobile (Android, iOS) and Wii U GamePad.
---
## InputManager - Core Input API
### Button Input
```cpp
#include <wv/core.h>
using namespace WillowVox;
void Update(const InputState& input)
{
// Check if jump button is held down
if (InputManager::GetButton(InputAction::Jump))
{
player->Jump();
}
// Check if action button was pressed THIS FRAME
if (InputManager::GetButtonDown(InputAction::Action1))
{
player->Attack();
}
// Check if button was released THIS FRAME
if (InputManager::GetButtonUp(InputAction::Action2))
{
player->StopAiming();
}
}
```
### Axis Input (Movement & Look)
```cpp
// Get individual axes by name
float horizontal = InputManager::GetAxis("MoveX"); // -1.0 to 1.0
float vertical = InputManager::GetAxis("MoveY"); // -1.0 to 1.0
float lookX = InputManager::GetAxis("LookX");
float lookY = InputManager::GetAxis("LookY");
// Or get as vectors (recommended)
glm::vec2 movement = InputManager::GetMovementVector(); // (x, y)
glm::vec2 look = InputManager::GetLookVector(); // (x, y)
// Apply to player
player->Move(movement.x, movement.y);
camera->Rotate(look.x, look.y);
```
**Supported Axis Names:**
- `"MoveX"` or `"Horizontal"` - Left/Right movement
- `"MoveY"` or `"Vertical"` - Forward/Backward movement
- `"LookX"` or `"Mouse X"` - Horizontal look/camera
- `"LookY"` or `"Mouse Y"` - Vertical look/camera
### Pointer/Mouse Input
```cpp
// Get pointer position (mouse or touch)
glm::vec2 pointerPos = InputManager::GetPointerPosition();
// Get pointer movement delta (useful for camera)
glm::vec2 pointerDelta = InputManager::GetPointerDelta();
camera->Rotate(pointerDelta.x * sensitivity, pointerDelta.y * sensitivity);
// Check if pointer/mouse button is down
if (InputManager::GetPointerDown())
{
// Click or touch is active
}
// Get scroll wheel delta
float scroll = InputManager::GetScrollDelta();
camera->Zoom(scroll);
```
### Device Detection
```cpp
// Check what device is being used
InputDeviceType device = InputManager::GetDeviceType();
// Check for specific device types
if (InputManager::IsGamepad())
{
// Show gamepad button prompts
UI::ShowPrompt("Press A to continue");
}
else if (InputManager::IsTouchscreen())
{
// Show touch controls
UI::ShowVirtualButtons();
}
// Check if specific device
if (InputManager::IsDeviceType(InputDeviceType::XboxController))
{
// Xbox-specific UI
}
```
### Convenience Methods
```cpp
// Check if player is trying to move
if (InputManager::IsMoving())
{
player->PlayWalkAnimation();
}
// Check if player is looking around
if (InputManager::IsLooking())
{
camera->UpdateRotation();
}
```
---
## GamepadInput - Gamepad Features
For more advanced gamepad control, use the `GamepadInput` class:
### Individual Stick Values
```cpp
#include <wv/input/GamepadInput.h>
// Get left stick (movement)
float leftX = GamepadInput::GetLeftStickX();
float leftY = GamepadInput::GetLeftStickY();
glm::vec2 leftStick = GamepadInput::GetLeftStick();
// Get right stick (camera/look)
float rightX = GamepadInput::GetRightStickX();
float rightY = GamepadInput::GetRightStickY();
glm::vec2 rightStick = GamepadInput::GetRightStick();
```
### Trigger Values
```cpp
// Get analog trigger values (0.0 to 1.0)
float leftTrigger = GamepadInput::GetTriggerLeft();
float rightTrigger = GamepadInput::GetTriggerRight();
// Use for vehicle acceleration
vehicle->Accelerate(rightTrigger);
vehicle->Brake(leftTrigger);
// Check if trigger exceeds threshold
if (GamepadInput::GetTriggerRightDown(0.5f))
{
// Trigger pressed at least 50%
}
```
### D-Pad Input
```cpp
// Get D-Pad as vector
glm::vec2 dpad = GamepadInput::GetDPad();
// Or check individual directions
if (GamepadInput::GetDPadUp()) { menu->MoveUp(); }
if (GamepadInput::GetDPadDown()) { menu->MoveDown(); }
if (GamepadInput::GetDPadLeft()) { menu->MoveLeft(); }
if (GamepadInput::GetDPadRight()) { menu->MoveRight(); }
```
### Face Buttons (Position-Based)
```cpp
// These map to physical button locations, not labels
bool south = GamepadInput::GetButtonSouth(); // A / Cross (bottom)
bool east = GamepadInput::GetButtonEast(); // B / Circle (right)
bool west = GamepadInput::GetButtonWest(); // X / Square (left)
bool north = GamepadInput::GetButtonNorth(); // Y / Triangle (top)
// Useful for QTE sequences or when you need exact button positions
if (GamepadInput::GetButtonSouth())
{
qte->PressCorrectButton();
}
```
### Shoulder Buttons
```cpp
bool lb = GamepadInput::GetShoulderLeft(); // LB / L1
bool rb = GamepadInput::GetShoulderRight(); // RB / R1
```
### Connection Status
```cpp
// Check if gamepad is connected
if (GamepadInput::IsConnected(0))
{
// Player 1 gamepad connected
}
// Get gamepad type
InputDeviceType type = GamepadInput::GetGamepadType();
if (type == InputDeviceType::XboxController)
{
UI::ShowXboxButtons();
}
else if (type == InputDeviceType::PSController)
{
UI::ShowPlayStationButtons();
}
```
### Vibration/Rumble
```cpp
// Set vibration (platform-dependent)
GamepadInput::SetVibration(0.5f, 0.8f, 1.0f); // (low motor, high motor, duration)
// Stop vibration
GamepadInput::StopVibration();
```
---
## TouchInput - Mobile & Touch Features
For touchscreen platforms (Android, iOS, Wii U GamePad):
### Basic Touch Input
```cpp
#include <wv/input/TouchInput.h>
// Check if touchscreen is supported
if (TouchInput::IsSupported())
{
// Get number of active touches
int touchCount = TouchInput::GetTouchCount();
// Check if any finger is touching
if (TouchInput::IsTouching())
{
// Handle touch
}
}
```
### Primary Touch
```cpp
// Get the first/primary touch
Touch touch = TouchInput::GetPrimaryTouch();
if (touch.isActive)
{
glm::vec2 position = touch.position;
glm::vec2 delta = touch.deltaPosition;
// Check touch phase
if (touch.phase == Touch::Phase::Began)
{
// Touch just started
}
else if (touch.phase == Touch::Phase::Moved)
{
// Touch is moving
camera->Pan(delta.x, delta.y);
}
}
```
### Multi-Touch Support
```cpp
// Get all active touches
std::vector<Touch> touches = TouchInput::GetTouches();
for (const Touch& touch : touches)
{
// Process each touch point
UI::DrawTouchIndicator(touch.position);
}
// Or access by index
Touch touch0 = TouchInput::GetTouch(0); // First touch
Touch touch1 = TouchInput::GetTouch(1); // Second touch
// Pinch-to-zoom example
if (TouchInput::GetTouchCount() == 2)
{
Touch t0 = TouchInput::GetTouch(0);
Touch t1 = TouchInput::GetTouch(1);
float distance = glm::distance(t0.position, t1.position);
camera->Zoom(distance);
}
```
### Touch Phase Detection
```cpp
// Check for specific touch events
if (TouchInput::TouchBegan())
{
// New touch detected this frame
}
if (TouchInput::TouchMoved())
{
// Active touch moved this frame
}
if (TouchInput::TouchEnded())
{
// Touch was released this frame
}
```
### Platform Features
```cpp
// Check capabilities
bool multiTouch = TouchInput::SupportsMultiTouch();
int maxTouches = TouchInput::GetMaxTouchCount();
// Wii U GamePad specific
if (TouchInput::IsWiiUGamePad())
{
// Use GamePad-specific features
}
```
---
## Platform-Specific Notes
### Desktop (Windows/Linux/macOS)
- **Movement**: WASD or arrow keys → `MoveX/MoveY`
- **Look**: Mouse movement → `LookX/LookY`
- **Actions**: Mouse buttons, Space, etc. → `Action1/2/3, Jump`
- **Gamepad**: XInput controllers supported
### Mobile (Android/iOS)
- **Movement**: Virtual joystick (left side) → `MoveX/MoveY`
- **Look**: Touch drag (right side) → `LookX/LookY`
- **Actions**: Virtual buttons → `Action1/2, Jump`
- **Multi-touch**: Supported via `TouchInput`
### PlayStation (PS3/PS4)
- **Movement**: Left analog stick → `MoveX/MoveY`
- **Look**: Right analog stick → `LookX/LookY`
- **Actions**: DualShock buttons → `Action1/2/3/4`
- **Triggers**: L2/R2 → `Crouch/Sprint`
### Xbox Series X/S
- **Movement**: Left analog stick → `MoveX/MoveY`
- **Look**: Right analog stick → `LookX/LookY`
- **Actions**: ABXY buttons → `Action1/2/3/4`
- **Triggers**: LT/RT → `Crouch/Sprint`
### Nintendo Switch
- **Movement**: Left analog stick → `MoveX/MoveY`
- **Look**: Right analog stick → `LookX/LookY`
- **Actions**: ABXY buttons → `Action1/2/3/4`
- **Triggers**: ZL/ZR → `Crouch/Sprint`
### Nintendo Wii
- **Movement**: Nunchuk joystick or D-pad → `MoveX/MoveY`
- **Look**: Wiimote IR pointer → `LookX/LookY`
- **Actions**: A/B/1/2 buttons → `Action1/2/3/4`
### Nintendo GameCube
- **Movement**: Control stick → `MoveX/MoveY`
- **Look**: C-stick → `LookX/LookY`
- **Actions**: ABXY buttons → `Action1/2/3/4`
- **Triggers**: L/R analog triggers supported
### Nintendo Wii U
- **Movement**: Left analog stick → `MoveX/MoveY`
- **Look**: Right analog stick → `LookX/LookY`
- **Actions**: ABXY buttons → `Action1/2/3/4`
- **Touchscreen**: GamePad touchscreen via `TouchInput`
---
## Complete Usage Example
```cpp
#include <wv/core.h>
using namespace WillowVox;
class MyGame : public App
{
public:
void Start() override
{
Logger::Log("Game Started!");
}
void Update(const InputState& input) override
{
// === Movement ===
glm::vec2 movement = InputManager::GetMovementVector();
player->Move(movement * speed * App::m_deltaTime);
// === Camera/Look ===
glm::vec2 look = InputManager::GetLookVector();
camera->Rotate(look * sensitivity);
// === Actions ===
if (InputManager::GetButtonDown(InputAction::Jump))
{
player->Jump();
}
if (InputManager::GetButton(InputAction::Action1))
{
player->PrimaryAction();
}
if (InputManager::GetButtonDown(InputAction::MenuOpen))
{
menu->Toggle();
}
// === Platform-Specific ===
if (InputManager::IsGamepad())
{
// Advanced gamepad features
float rightTrigger = GamepadInput::GetTriggerRight();
if (rightTrigger > 0.5f)
{
player->Sprint();
}
}
else if (InputManager::IsTouchscreen())
{
// Touch-specific features
int touchCount = TouchInput::GetTouchCount();
if (touchCount == 2)
{
// Pinch to zoom
Touch t0 = TouchInput::GetTouch(0);
Touch t1 = TouchInput::GetTouch(1);
float dist = glm::distance(t0.position, t1.position);
camera->Zoom(dist);
}
}
}
void Render() override
{
// Your rendering code
}
private:
Player* player;
Camera* camera;
Menu* menu;
float speed = 5.0f;
float sensitivity = 2.0f;
};
```
---
## InputAction Reference
All abstract actions available in `InputAction` enum:
| Action | Description | Common Mapping |
|--------|-------------|----------------|
| `MoveForward` | Move forward | W, Up, D-pad Up, Left Stick Up |
| `MoveBackward` | Move backward | S, Down, D-pad Down, Left Stick Down |
| `MoveLeft` | Move left | A, Left, D-pad Left, Left Stick Left |
| `MoveRight` | Move right | D, Right, D-pad Right, Left Stick Right |
| `Action1` | Primary action | Mouse Left, A/Cross, Touch Button |
| `Action2` | Secondary action | Mouse Right, B/Circle |
| `Action3` | Tertiary action | X/Square |
| `Action4` | Quaternary action | Y/Triangle |
| `Jump` | Jump | Space, A/Cross |
| `Crouch` | Crouch | Ctrl, L2/LT, Z |
| `Sprint` | Sprint | Shift, R2/RT |
| `MenuOpen` | Open menu | Esc, Start, Plus |
| `MenuBack` | Back/Cancel | Esc, B/Circle, Minus |
| `CycleLeft` | Cycle items left | Q, LB/L1 |
| `CycleRight` | Cycle items right | E, RB/R1 |
---
## Best Practices
1. **Always use InputManager for basic input** - It works across all platforms
2. **Use GamepadInput only when you need advanced gamepad features** (triggers, vibration)
3. **Use TouchInput only for multi-touch or touch-specific features**
4. **Detect device type to show appropriate UI prompts** (keyboard vs gamepad vs touch)
5. **Test on all target platforms** - Input behavior may vary slightly
6. **Use GetButtonDown for single-press actions** (menus, attacks)
7. **Use GetButton for continuous actions** (movement, aiming)
8. **Normalize and multiply by deltaTime for frame-independent movement**
---
## Migration from Old Input System
If you're using the old `Input` class (keyboard/mouse only):
```cpp
// OLD (Desktop only)
if (Input::GetKey(Key::W))
player->Move(0, 1);
// NEW (All platforms)
glm::vec2 movement = InputManager::GetMovementVector();
player->Move(movement.x, movement.y);
```
```cpp
// OLD (Desktop only)
glm::vec2 mouseDelta = Input::GetMouseDelta();
// NEW (All platforms)
glm::vec2 lookDelta = InputManager::GetLookVector();
```
The new API is **backward compatible** - you can still use the old `Input` class for desktop-specific features, but `InputManager` is recommended for cross-platform projects.