> For the complete documentation index, see [llms.txt](https://azuriohs-organization.gitbook.io/r-type/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://azuriohs-organization.gitbook.io/r-type/subsystems/our-subsystems/human-machine-interface.md).

# Human Machine Interface

## Table of Contents

* [Introduction](#introduction)
* [Overview](#overview)
* [Architecture](#architecture)
* [Getting Started](#getting-started)
* [Core Components](#core-components)
  * [Input System](#input-system)
  * [Input Mapper](#input-mapper)
  * [Human Machine Interface](#human-machine-interface)
* [Input Binding](#input-binding)
* [Input Handling](#input-handling)
* [Input Modes](#input-modes)
* [Advanced Features](#advanced-features)
* [Examples](#examples)
* [Best Practices](#best-practices)
* [Troubleshooting](#troubleshooting)

***

## Introduction

The Human Machine Interface (HMI) is a C++ input handling subsystem designed for the R-Type game engine. It provides a unified interface for processing user input from various sources (keyboard, mouse, and gamepad) and converting them into semantic actions.

This HMI subsystem is designed as a modular library that can be dynamically loaded into the R-Type game engine, following the plugin architecture pattern. It implements the `IHumanMachineInterface` interface from the common engine subsystem, allowing for easy swapping between different input handling implementations.

***

## Overview

### Features

* **Multi-Input Support**: Keyboard, mouse, and gamepad input handling
* **Input Mapping**: Configurable mapping from raw input to semantic actions
* **Input Modes**: Different input modes (Gameplay, Text Input) for context-aware processing
* **Input Locking**: Ability to temporarily disable input processing
* **Action Queuing**: Accumulate actions for batch processing
* **Metadata Support**: Optional metadata attachment to inputs

### Dependencies

* **C++20 Standard Library**: Required for `std::optional`, `std::any`, `std::tuple`
* **Common Engine**: Depends on the common engine interfaces

### Build Requirements

* CMake 3.16.0 or higher
* C++20 compiler

***

## Architecture

### Module Structure

The HMI subsystem follows a layered architecture:

```
HMI Module (Entry Point)
├── Input System
│   ├── Input Structure
│   ├── Type Enum (Keyboard, Mouse, Gamepad, GamepadAxis)
│   ├── KeyCode Enum
│   ├── MouseCode Enum
│   ├── GamepadCode Enum
│   ├── AxisGamepad Enum
│   └── Action Enum (Pressed, Released)
├── Input Mapper
│   ├── IInputMapper (Interface)
│   └── InputMapper (Implementation)
│       └── Input Bindings (map)
└── Human Machine Interface
    ├── IHumanMachineInterface (Interface)
    └── HumanMachineInterface (Implementation)
        ├── Input Mapper
        ├── Action Queue
        ├── Input Mode
        └── Input Lock State
```

### Entry Point

The module exports an entry point function that returns a `HumanMachineInterface` instance:

```cpp
extern "C" Subsystems::HMI::HumanMachineInterface *entryPoint(void);
```

Additionally, it exports a separate entry point for the input mapper:

```cpp
extern "C" Subsystems::HMI::InputMapper *entryPointInputMapper(void);
```

This allows the engine to dynamically load the HMI library at runtime.

***

## Getting Started

### Building the Module

1. **Configure CMake**:

```bash
cd lib/HMI/V1
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
```

2. **Build**:

```bash
cmake --build build
```

The compiled library (`libhmi-v1.dylib` on macOS, `.so` on Linux, `.dll` on Windows) will be placed in the `lib/` directory.

### Basic Usage

```cpp
#include "Subsystems/HMI/IHumanMachineInterface.hpp"
#include "Subsystems/HMI/Input.hpp"

// Create HMI instance (usually loaded dynamically)
auto hmi = std::make_unique<Subsystems::HMI::HumanMachineInterface>();

// Get input mapper
auto& mapper = hmi->GetInputMapper();

// Bind keyboard input to action
mapper.Bind({HMI::Type::Keyboard, HMI::KeyCode::Space}, "JUMP");

// Handle input
HMI::Input input;
input.type = HMI::Type::Keyboard;
input.key = HMI::KeyCode::Space;
input.action = HMI::Action::Pressed;
hmi->HandleInput(input);

// Poll actions
auto actions = hmi->PollActions();
for (const auto& [actionName, action, metadata] : actions) {
    if (actionName == "JUMP" && action == HMI::Action::Pressed) {
        // Handle jump
    }
}

// Clear actions
hmi->ClearActions();
```

***

## Core Components

### Input System

The input system defines the basic input types and structures.

#### Input Types

The `HMI::Type` enum defines input source types:

* `UnknownType`: Unknown input type
* `Keyboard`: Keyboard input
* `Mouse`: Mouse input
* `Gamepad`: Gamepad button input
* `GamepadAxis`: Gamepad analog axis input

#### Key Codes

The `HMI::KeyCode` enum defines keyboard keys:

**Letters**: `A` through `Z`

**Numbers**: `Num0` through `Num9`

**Arrow Keys**: `Up`, `Down`, `Left`, `Right`

**Special Keys**: `Space`, `Enter`, `Escape`, `Tab`, `Shift`, `Ctrl`, `Alt`

**Punctuation**: `Underscore`, `Plus`, `Minus`, `Asterisk`, `Slash`, `Dot`, `Comma`, `Semicolon`, `Colon`, `Quote`, `Backslash`, `Pipe`, `Backquote`

**Editing Keys**: `Backspace`, `Delete`, `Insert`, `Home`, `End`, `PageUp`, `PageDown`

**Function Keys**: `F1` through `F12`

#### Mouse Codes

The `HMI::MouseCode` enum defines mouse buttons:

* `UnknownMouse`: Unknown mouse button
* `MouseLeft`: Left mouse button
* `MouseRight`: Right mouse button
* `MouseMiddle`: Middle mouse button (scroll wheel)
* `MouseX1`: Extra mouse button 1
* `MouseX2`: Extra mouse button 2

#### Gamepad Codes

The `HMI::GamepadCode` enum defines gamepad buttons:

**Face Buttons**: `GamepadButtonA`, `GamepadButtonB`, `GamepadButtonX`, `GamepadButtonY`

**Shoulder Buttons**: `GamepadButtonLB`, `GamepadButtonRB` (Left/Right Bumpers)

**Trigger Buttons**: `GamepadButtonLT`, `GamepadButtonRT` (Left/Right Triggers)

**Stick Buttons**: `GamepadButtonLS`, `GamepadButtonRS` (Left/Right Stick Press)

**Menu Buttons**: `GamepadButtonStart`, `GamepadButtonSelect`, `GamepadButtonHome`, `GamepadButtonBack`, `GamepadButtonMenu`, `GamepadButtonView`

**D-Pad**: `GamepadButtonUp`, `GamepadButtonDown`, `GamepadButtonLeft`, `GamepadButtonRight`

#### Gamepad Axes

The `AxisGamepad` enum defines gamepad analog axes:

* `GamepadAxisUnknown`: Unknown axis
* `GamepadAxisLeftX`: Left stick X-axis
* `GamepadAxisLeftY`: Left stick Y-axis
* `GamepadAxisRightX`: Right stick X-axis
* `GamepadAxisRightY`: Right stick Y-axis
* `GamepadAxisTriggerLeft`: Left trigger axis
* `GamepadAxisTriggerRight`: Right trigger axis

#### Input Actions

The `HMI::Action` enum defines input actions:

* `UnknownAction`: Unknown action
* `Pressed`: Input pressed/down
* `Released`: Input released/up

#### Input Structure

The `Input` struct represents a single input event:

```cpp
struct Input {
    Type type;           // Input type (Keyboard, Mouse, Gamepad, etc.)
    std::size_t key;     // Key code (KeyCode, MouseCode, GamepadCode, etc.)
    Action action;       // Action (Pressed, Released)
    std::any metadata;  // Optional metadata
};
```

**Example:**

```cpp
HMI::Input input;
input.type = HMI::Type::Keyboard;
input.key = HMI::KeyCode::Space;
input.action = HMI::Action::Pressed;
input.metadata = std::any(); // Optional
```

### Input Mapper

The `InputMapper` class maps raw inputs to semantic actions.

**Key Methods:**

* `Bind(input, action)`: Bind an input to an action name
* `GetAction(input, mode)`: Get the action for an input based on current mode

**Example:**

```cpp
auto& mapper = hmi->GetInputMapper();

// Bind keyboard key to action
mapper.Bind({HMI::Type::Keyboard, HMI::KeyCode::Space}, "JUMP");
mapper.Bind({HMI::Type::Keyboard, HMI::KeyCode::W}, "MOVE_UP");

// Bind mouse button to action
mapper.Bind({HMI::Type::Mouse, HMI::MouseCode::MouseLeft}, "SHOOT");

// Bind gamepad button to action
mapper.Bind({HMI::Type::Gamepad, HMI::GamepadCode::GamepadButtonA}, "JUMP");
```

### Human Machine Interface

The `HumanMachineInterface` class is the main interface for input handling.

**Key Methods:**

* `HandleInput(input)`: Process an input event
* `PollActions()`: Get all accumulated actions
* `ClearActions()`: Clear the action queue
* `GetInputMapper()`: Get the input mapper
* `SetInputMode(mode)`: Set the input mode
* `SetInputLock(locked)`: Lock or unlock input processing

***

## Input Binding

### Binding Inputs

Bind inputs to semantic action names using the input mapper:

```cpp
auto& mapper = hmi->GetInputMapper();

// Keyboard bindings
mapper.Bind({HMI::Type::Keyboard, HMI::KeyCode::W}, "MOVE_UP");
mapper.Bind({HMI::Type::Keyboard, HMI::KeyCode::S}, "MOVE_DOWN");
mapper.Bind({HMI::Type::Keyboard, HMI::KeyCode::A}, "MOVE_LEFT");
mapper.Bind({HMI::Type::Keyboard, HMI::KeyCode::D}, "MOVE_RIGHT");
mapper.Bind({HMI::Type::Keyboard, HMI::KeyCode::Space}, "JUMP");
mapper.Bind({HMI::Type::Keyboard, HMI::KeyCode::Escape}, "PAUSE");

// Mouse bindings
mapper.Bind({HMI::Type::Mouse, HMI::MouseCode::MouseLeft}, "SHOOT");
mapper.Bind({HMI::Type::Mouse, HMI::MouseCode::MouseRight}, "AIM");

// Gamepad bindings
mapper.Bind({HMI::Type::Gamepad, HMI::GamepadCode::GamepadButtonA}, "JUMP");
mapper.Bind({HMI::Type::Gamepad, HMI::GamepadCode::GamepadButtonX}, "SHOOT");
mapper.Bind({HMI::Type::Gamepad, HMI::GamepadCode::GamepadButtonUp}, "MOVE_UP");
```

### Binding Gamepad Axes

Bind gamepad axes for analog input:

```cpp
// Gamepad axes
mapper.Bind({HMI::Type::GamepadAxis, HMI::AxisGamepad::GamepadAxisLeftX}, "MOVE_HORIZONTAL");
mapper.Bind({HMI::Type::GamepadAxis, HMI::AxisGamepad::GamepadAxisLeftY}, "MOVE_VERTICAL");
mapper.Bind({HMI::Type::GamepadAxis, HMI::AxisGamepad::GamepadAxisRightX}, "LOOK_HORIZONTAL");
mapper.Bind({HMI::Type::GamepadAxis, HMI::AxisGamepad::GamepadAxisRightY}, "LOOK_VERTICAL");
```

**Note:** Axes typically have continuous values stored in the input metadata.

### Multiple Bindings

You can bind multiple inputs to the same action:

```cpp
// Both Space and A button trigger JUMP
mapper.Bind({HMI::Type::Keyboard, HMI::KeyCode::Space}, "JUMP");
mapper.Bind({HMI::Type::Gamepad, HMI::GamepadCode::GamepadButtonA}, "JUMP");
```

You can also bind the same input to multiple actions by rebinding (the last binding takes precedence):

```cpp
mapper.Bind({HMI::Type::Keyboard, HMI::KeyCode::Space}, "JUMP");
// Later...
mapper.Bind({HMI::Type::Keyboard, HMI::KeyCode::Space}, "SPRINT"); // Replaces JUMP binding
```

***

## Input Handling

### Processing Inputs

Handle inputs through the HMI:

```cpp
HMI::Input input;
input.type = HMI::Type::Keyboard;
input.key = HMI::KeyCode::Space;
input.action = HMI::Action::Pressed;

hmi->HandleInput(input);
```

The HMI will:

1. Check if input is locked (if locked, ignore)
2. Query the input mapper for the action
3. If an action is found, add it to the action queue

### Polling Actions

Poll accumulated actions after handling inputs:

```cpp
auto actions = hmi->PollActions();

for (const auto& [actionName, action, metadata] : actions) {
    if (actionName == "JUMP" && action == HMI::Action::Pressed) {
        // Handle jump
        player.Jump();
    } else if (actionName == "MOVE_UP" && action == HMI::Action::Pressed) {
        // Handle movement
        player.MoveUp();
    }
}
```

### Clearing Actions

Clear the action queue after processing:

```cpp
hmi->ClearActions();
```

This is typically done at the end of each frame:

```cpp
while (gameRunning) {
    // Process inputs
    for (const auto& input : rawInputs) {
        hmi->HandleInput(input);
    }

    // Poll and handle actions
    auto actions = hmi->PollActions();
    for (const auto& [actionName, action, metadata] : actions) {
        HandleAction(actionName, action, metadata);
    }

    // Clear actions for next frame
    hmi->ClearActions();

    // ... game logic ...
}
```

***

## Input Modes

The HMI supports different input modes for context-aware processing.

### Input Modes

* `GAMEPLAY`: Normal gameplay input processing
* `TEXT_INPUT`: Text input mode (keyboard input bypasses mapper)

### Setting Input Mode

```cpp
// Set to gameplay mode
hmi->SetInputMode(Subsystems::HMI::IHumanMachineInterface::InputMode::GAMEPLAY);

// Set to text input mode
hmi->SetInputMode(Subsystems::HMI::IHumanMachineInterface::InputMode::TEXT_INPUT);
```

### Text Input Mode

In `TEXT_INPUT` mode, keyboard inputs bypass the input mapper and generate `"TEXT_INPUT"` actions:

```cpp
hmi->SetInputMode(Subsystems::HMI::IHumanMachineInterface::InputMode::TEXT_INPUT);

// Keyboard input will generate TEXT_INPUT action
HMI::Input input;
input.type = HMI::Type::Keyboard;
input.key = HMI::KeyCode::A;
input.action = HMI::Action::Pressed;
hmi->HandleInput(input);

auto actions = hmi->PollActions();
// actions will contain: ("TEXT_INPUT", Pressed, metadata)
```

Use text input mode for text fields, chat input, or other text entry scenarios.

***

## Advanced Features

### Input Locking

Temporarily disable input processing:

```cpp
// Lock input
hmi->SetInputLock(true);

// Inputs will be ignored until unlocked
hmi->HandleInput(input); // Ignored

// Unlock input
hmi->SetInputLock(false);

// Inputs will be processed again
hmi->HandleInput(input); // Processed
```

Use input locking to:

* Pause gameplay
* Display menus
* Prevent input during transitions

### Metadata

Attach optional metadata to inputs:

```cpp
HMI::Input input;
input.type = HMI::Type::Mouse;
input.key = HMI::MouseCode::MouseLeft;
input.action = HMI::Action::Pressed;

// Store mouse position in metadata
struct MousePosition {
    float x, y;
};
input.metadata = std::make_any<MousePosition>(MousePosition{100.0f, 200.0f});

hmi->HandleInput(input);

// Retrieve metadata in actions
auto actions = hmi->PollActions();
for (const auto& [actionName, action, metadata] : actions) {
    if (actionName == "SHOOT") {
        try {
            auto mousePos = std::any_cast<MousePosition>(metadata);
            // Use mouse position
        } catch (const std::bad_any_cast& e) {
            // Handle error
        }
    }
}
```

### Gamepad Axis Values

For gamepad axes, store axis values in metadata:

```cpp
HMI::Input axisInput;
axisInput.type = HMI::Type::GamepadAxis;
axisInput.key = HMI::AxisGamepad::GamepadAxisLeftX;
axisInput.action = HMI::Action::Pressed; // Or Released for dead zone

// Store axis value (-1.0 to 1.0)
float axisValue = 0.75f;
axisInput.metadata = std::make_any<float>(axisValue);

hmi->HandleInput(axisInput);

// Retrieve axis value
auto actions = hmi->PollActions();
for (const auto& [actionName, action, metadata] : actions) {
    if (actionName == "MOVE_HORIZONTAL") {
        try {
            float value = std::any_cast<float>(metadata);
            player.SetMoveSpeed(value);
        } catch (const std::bad_any_cast& e) {
            // Handle error
        }
    }
}
```

***

## Examples

### Complete Input System Setup

```cpp
#include "Subsystems/HMI/IHumanMachineInterface.hpp"
#include "Subsystems/HMI/Input.hpp"
#include <iostream>

class InputHandler {
public:
    InputHandler(Subsystems::HMI::IHumanMachineInterface* hmi) : _hmi(hmi) {
        SetupInputBindings();
    }

    void SetupInputBindings() {
        auto& mapper = _hmi->GetInputMapper();

        // Movement bindings
        mapper.Bind({HMI::Type::Keyboard, HMI::KeyCode::W}, "MOVE_UP");
        mapper.Bind({HMI::Type::Keyboard, HMI::KeyCode::S}, "MOVE_DOWN");
        mapper.Bind({HMI::Type::Keyboard, HMI::KeyCode::A}, "MOVE_LEFT");
        mapper.Bind({HMI::Type::Keyboard, HMI::KeyCode::D}, "MOVE_RIGHT");

        // Action bindings
        mapper.Bind({HMI::Type::Keyboard, HMI::KeyCode::Space}, "JUMP");
        mapper.Bind({HMI::Type::Mouse, HMI::MouseCode::MouseLeft}, "SHOOT");

        // Menu bindings
        mapper.Bind({HMI::Type::Keyboard, HMI::KeyCode::Escape}, "PAUSE");

        // Gamepad bindings
        mapper.Bind({HMI::Type::Gamepad, HMI::GamepadCode::GamepadButtonA}, "JUMP");
        mapper.Bind({HMI::Type::Gamepad, HMI::GamepadCode::GamepadButtonX}, "SHOOT");
        mapper.Bind({HMI::Type::Gamepad, HMI::GamepadCode::GamepadButtonStart}, "PAUSE");
    }

    void ProcessInputs(const std::vector<HMI::Input>& rawInputs) {
        for (const auto& input : rawInputs) {
            _hmi->HandleInput(input);
        }
    }

    void HandleActions() {
        auto actions = _hmi->PollActions();

        for (const auto& [actionName, action, metadata] : actions) {
            if (action == HMI::Action::Pressed) {
                if (actionName == "JUMP") {
                    std::cout << "Jump!" << std::endl;
                } else if (actionName == "SHOOT") {
                    std::cout << "Shoot!" << std::endl;
                } else if (actionName == "MOVE_UP") {
                    std::cout << "Move up" << std::endl;
                } else if (actionName == "MOVE_DOWN") {
                    std::cout << "Move down" << std::endl;
                } else if (actionName == "MOVE_LEFT") {
                    std::cout << "Move left" << std::endl;
                } else if (actionName == "MOVE_RIGHT") {
                    std::cout << "Move right" << std::endl;
                } else if (actionName == "PAUSE") {
                    std::cout << "Pause menu" << std::endl;
                }
            }
        }

        _hmi->ClearActions();
    }

private:
    Subsystems::HMI::IHumanMachineInterface* _hmi;
};

// Usage
int main() {
    auto hmi = std::make_unique<Subsystems::HMI::HumanMachineInterface>();
    InputHandler handler(hmi.get());

    // Game loop
    while (gameRunning) {
        // Get raw inputs from render subsystem
        std::vector<HMI::Input> rawInputs = GetRawInputs();

        // Process inputs
        handler.ProcessInputs(rawInputs);

        // Handle actions
        handler.HandleActions();

        // ... game logic ...
    }

    return 0;
}
```

### Text Input Mode

```cpp
class TextInputHandler {
public:
    TextInputHandler(Subsystems::HMI::IHumanMachineInterface* hmi) : _hmi(hmi) {}

    void EnableTextInput() {
        _hmi->SetInputMode(Subsystems::HMI::IHumanMachineInterface::InputMode::TEXT_INPUT);
    }

    void DisableTextInput() {
        _hmi->SetInputMode(Subsystems::HMI::IHumanMachineInterface::InputMode::GAMEPLAY);
    }

    void ProcessTextInput() {
        auto actions = _hmi->PollActions();
        std::string text;

        for (const auto& [actionName, action, metadata] : actions) {
            if (actionName == "TEXT_INPUT" && action == HMI::Action::Pressed) {
                // Extract character from metadata
                // This depends on how the render subsystem encodes text input
                // Example: metadata might contain KeyCode or character value
            }
        }

        _hmi->ClearActions();
    }

private:
    Subsystems::HMI::IHumanMachineInterface* _hmi;
};
```

### Input Locking Pattern

```cpp
class GameStateManager {
public:
    GameStateManager(Subsystems::HMI::IHumanMachineInterface* hmi) : _hmi(hmi) {}

    void ShowMenu() {
        _hmi->SetInputLock(true);
        // Show menu UI
    }

    void HideMenu() {
        _hmi->SetInputLock(false);
        // Hide menu UI
    }

    void PauseGame() {
        _hmi->SetInputLock(true);
        // Pause game logic
    }

    void ResumeGame() {
        _hmi->SetInputLock(false);
        // Resume game logic
    }

private:
    Subsystems::HMI::IHumanMachineInterface* _hmi;
};
```

### Configurable Key Bindings

```cpp
class KeyBindingManager {
public:
    void LoadBindings(Subsystems::HMI::IHumanMachineInterface* hmi, const std::string& configFile) {
        auto& mapper = hmi->GetInputMapper();

        // Load from config file (JSON, INI, etc.)
        // Example bindings from config
        std::map<std::string, std::pair<HMI::Type, std::size_t>> bindings = {
            {"JUMP", {HMI::Type::Keyboard, HMI::KeyCode::Space}},
            {"MOVE_UP", {HMI::Type::Keyboard, HMI::KeyCode::W}},
            {"SHOOT", {HMI::Type::Mouse, HMI::MouseCode::MouseLeft}},
        };

        for (const auto& [action, input] : bindings) {
            mapper.Bind(input, action);
        }
    }

    void SaveBindings(Subsystems::HMI::IHumanMachineInterface* hmi, const std::string& configFile) {
        // Save current bindings to config file
    }

    void RebindAction(Subsystems::HMI::IHumanMachineInterface* hmi,
                     const std::string& action,
                     std::pair<HMI::Type, std::size_t> newInput) {
        auto& mapper = hmi->GetInputMapper();
        mapper.Bind(newInput, action);
    }
};
```

***

## Best Practices

### Input Binding

* **Use semantic action names**: Use descriptive names like `"JUMP"`, `"SHOOT"` instead of `"SPACE"`, `"MOUSE_LEFT"`
* **Support multiple bindings**: Allow players to bind multiple inputs to the same action
* **Separate gameplay bindings**: Keep gameplay bindings separate from UI bindings
* **Load from config**: Load key bindings from configuration files for user customization

### Input Processing

* **Process inputs once per frame**: Handle inputs at a consistent point in the game loop
* **Clear actions after polling**: Always call `ClearActions()` after processing actions
* **Batch processing**: Process all inputs, then poll all actions, then clear

### Input Modes

* **Switch modes contextually**: Switch to `TEXT_INPUT` mode when text fields are active
* **Restore gameplay mode**: Always restore `GAMEPLAY` mode when leaving text input

### Input Locking

* **Use for menus**: Lock input when showing menus or dialogs
* **Unlock properly**: Always unlock input when closing menus or resuming gameplay
* **Nested menus**: Be careful with nested menus and unlock order

### Memory Management

* **Poll regularly**: Poll actions regularly to prevent queue buildup
* **Clear actions**: Always clear actions after processing
* **Avoid metadata overhead**: Keep metadata lightweight

### Performance

* **Efficient polling**: Poll actions once per frame, not multiple times
* **Action filtering**: Filter actions efficiently based on action names
* **Avoid unnecessary copies**: Use references when possible

***

## Troubleshooting

### Common Issues

**Actions not being generated:**

* Verify input bindings are registered: Check that `Bind()` was called
* Ensure input type and key match exactly: `{HMI::Type::Keyboard, HMI::KeyCode::Space}`
* Check if input is locked: Call `SetInputLock(false)` if needed
* Verify input mode: Ensure correct input mode is set

**Actions queue building up:**

* Ensure `ClearActions()` is called after processing
* Poll actions regularly in the game loop
* Check for infinite loops or early returns before clearing

**Text input not working:**

* Set input mode to `TEXT_INPUT`: `hmi->SetInputMode(InputMode::TEXT_INPUT)`
* Verify keyboard input is being passed to `HandleInput()`
* Check that input mode is restored to `GAMEPLAY` after text input

**Invalid input errors:**

* Ensure input type and key are valid: Both must be non-zero
* Check enum values: Use correct enum values for `Type` and key codes
* Verify input structure: Ensure all required fields are set

**Gamepad input not working:**

* Verify gamepad is connected and recognized by the render subsystem
* Check gamepad code mappings: Use correct `GamepadCode` values
* For axes: Use `GamepadAxis` type and `AxisGamepad` codes

**Metadata casting errors:**

* Use `std::any_cast` carefully: Wrap in try-catch blocks
* Verify metadata type: Ensure metadata type matches expected type
* Document metadata: Document what metadata each action type expects

**Input locking issues:**

* Ensure unlock is called: Always unlock when done
* Check for exceptions: Ensure unlock is called even if exceptions occur
* Verify lock state: Check lock state before handling inputs

***

## API Reference

For detailed API documentation, refer to the header files:

* `IHumanMachineInterface.hpp`: Main HMI interface
* `HumanMachineInterface.hpp`: HMI implementation
* `IInputMapper.hpp`: Input mapper interface
* `InputMapper.hpp`: Input mapper implementation
* `Input.hpp`: Input types and structures

***

## Version Information

* **Version**: 1.0.0
* **Build System**: CMake 3.16.0+
* **C++ Standard**: C++20
* **Platform Support**: macOS, Linux, Windows

***

## License

This HMI subsystem is part of the R-Type project (EPITECH, 2025).

***

## Contributing

When contributing to the HMI subsystem:

1. Follow the existing code style
2. Add documentation for new features
3. Update this documentation file
4. Test with multiple input devices (keyboard, mouse, gamepad)
5. Ensure backward compatibility with the `IHumanMachineInterface` interface
6. Add unit tests for input mapping and processing

***

*Last Updated: 2025*
