Files
UE5-Modular-Game-Framework/docs/architecture/enhanced-input-system.md
2026-05-19 10:16:14 +00:00

214 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Enhanced Input System Architecture
## Problem Statement
The project has **no input system specification** despite 230+ cross-references to a non-existent [`BPC_InputManager`](../02-player/13_BPC_InputManager.md) across existing blueprint specs. UE5's Enhanced Input System must be architected into the framework using a centralized [`SS_EnhancedInputManager`](Game Instance Subsystem) that manages Input Mapping Context push/pop, priority, platform profiles, and input mode coordination with [`SS_UIManager`](docs/blueprints/06-ui/44_SS_UIManager.md).
## Proposed Solution
```mermaid
flowchart TD
A[Game Boot / GI_GameFramework Init] --> B[SS_EnhancedInputManager.Initialize]
B --> C[Load DA_InputMappingProfile]
C --> D[Cache platform-specific IMCs]
E[GM_CoreGameMode.OnPlayerPossess] --> F[SS_EnhancedInputManager.PushDefaultContext]
F --> G[Add IMC_Default Priority 0 via EnhancedInputLocalPlayerSubsystem]
H[Gameplay Event] --> I{Context Switch?}
I -->|Open Inventory| J[PushContext IMC_WristwatchUI Priority 10]
I -->|Pick Up Item| K[PushContext IMC_Inspection Priority 20]
I -->|Enter Hiding| L[PushContext IMC_Hiding Priority 5]
I -->|Open Pause| M[SS_UIManager.ShowMenu + PushContext IMC_UI Priority 100]
N[Exit Context] --> O[SS_EnhancedInputManager.PopContext]
O --> P[Remove IMC, restore lower priority contexts]
Q[SS_SettingsSystem.ApplyControlSettings] --> R[SS_EnhancedInputManager.RebindKey]
R --> S[Update IMC mappings via DA_InputMappingProfile]
```
### Architecture Decision: Centralized Subsystem (Option A)
`SS_EnhancedInputManager` is a **Game Instance Subsystem**, matching the project's existing [`SS_UIManager`](docs/blueprints/06-ui/44_SS_UIManager.md), [`SS_SettingsSystem`](docs/blueprints/12-settings/105_SS_SettingsSystem.md), and [`SS_SaveManager`](docs/blueprints/05-saveload/35_SS_SaveManager.md) pattern. It manages all Input Mapping Contexts globally, while individual systems request context pushes via a clean API (function calls + dispatchers).
### Context Priority Ladder
| Priority | Context | Trigger | Overrides |
|----------|---------|---------|-----------|
| 0 | `IMC_Default` | Persistent gameplay | Nothing |
| 5 | `IMC_Hiding` | Enter hiding spot | Movement, Interact |
| 10 | `IMC_WristwatchUI` | Open watch/inventory | Movement, Look |
| 20 | `IMC_Inspection` | Pick up 3D item | All below |
| 100 | `IMC_UI` | Pause/Settings/Journal | Everything |
Higher priority = takes precedence. Multiple contexts can be active simultaneously.
### Input Actions (IA_) Master Registry
#### Axis2D Inputs
| Action | Value Type | Used In | Description |
|--------|-----------|---------|-------------|
| `IA_Move` | Axis2D | IMC_Default | W/A/S/D + Left Stick → locomotion |
| `IA_Look` | Axis2D | IMC_Default | Mouse XY + Right Stick → camera |
| `IA_Inspect_Rotate` | Axis2D | IMC_Inspection | Mouse/Right Stick → rotate item |
| `IA_UI_Navigate` | Axis2D | IMC_WristwatchUI, IMC_UI | D-Pad/Arrows → menu navigation |
| `IA_Hide_Look` | Axis2D | IMC_Hiding | Mouse/Right Stick → look while hidden |
#### Axis1D Inputs
| Action | Value Type | Used In | Description |
|--------|-----------|---------|-------------|
| `IA_Inspect_Zoom` | Axis1D | IMC_Inspection | Scroll/LT-RT → zoom item |
| `IA_Hide_Peek` | Axis1D | IMC_Hiding | W/S → lean forward in hiding |
| `IA_QuickSlotScroll` | Axis1D | IMC_Default | Scroll wheel → cycle quick slots |
#### Digital (Bool) Inputs — Gameplay
| Action | Used In | PC Default | Gamepad Default | Description |
|--------|---------|------------|-----------------|-------------|
| `IA_Interact` | IMC_Default | E / Left Click | X / Square | Pick up, hold for physics-drag |
| `IA_PrimaryAction` | IMC_Default | LMB | RT / R2 | Fire weapon / Swing tool |
| `IA_SecondaryAction` | IMC_Default | RMB | LT / L2 | ADS / Shield |
| `IA_Sprint` | IMC_Default | L-Shift | L3 | Run (triggers stamina + stress) |
| `IA_Crouch` | IMC_Default | C / L-Ctrl | B / Circle | Sneak / crawl |
| `IA_Vault_Climb` | IMC_Default | Spacebar | A / Cross | Contextual parkour |
| `IA_Jump` | IMC_Default | Spacebar | A / Cross | Basic jump (coexists with Vault via context) |
| `IA_Flashlight` | IMC_Default | F | D-Pad Up | Toggle light |
| `IA_QuickHeal` | IMC_Default | Q / H | D-Pad Down | Consume health item |
| `IA_Reload` | IMC_Default | R | Y / Triangle | Reload weapon |
| `IA_OpenWatch` | IMC_Default | Tab / I | View / Touchpad | Wristwatch UI |
| `IA_PauseMenu` | IMC_Default | Esc / P | Menu / Options | Pause game |
| `IA_QuickSlot1``IA_QuickSlot8` | IMC_Default | 18 | None | Direct quick slot selection |
#### Digital (Bool) Inputs — Context-Specific
| Action | Used In | PC Default | Gamepad Default | Description |
|--------|---------|------------|-----------------|-------------|
| `IA_Inspect_Flip` | IMC_Inspection | F | Y / Triangle | Flip document |
| `IA_Cancel_Drop` | IMC_Inspection | RMB / Esc | B / Circle | Exit inspection |
| `IA_UI_Select` | IMC_WristwatchUI, IMC_UI | E / Enter | A / Cross | Confirm/equip |
| `IA_UI_Combine` | IMC_WristwatchUI | C | X / Square | Item combination |
| `IA_UI_DropItem` | IMC_WristwatchUI | X | Y / Triangle | Drop from inventory |
| `IA_CloseWatch` | IMC_WristwatchUI | Tab / Esc | B / Circle | Lower arm |
| `IA_UI_Back` | IMC_UI | Esc / Backspace | B / Circle | Back one menu level |
| `IA_Hide_HoldBreath` | IMC_Hiding | Spacebar (Hold) | LT+RT (Hold) | Suppress breathing |
| `IA_Exit_Hide` | IMC_Hiding | C / Esc | B / Circle | Leave hiding spot |
#### New Input Types Added (beyond user's original list)
| Action | Value Type | Used In | Description | Rationale |
|--------|-----------|---------|-------------|-----------|
| `IA_Jump` | Digital | IMC_Default | Separate from Vault for non-contextual jumps | Prevents accidental climbing when player just wants to jump |
| `IA_QuickSlotScroll` | Axis1D | IMC_Default | Cycle through 8 quick slots | Natural controller wheel support for inventory |
| `IA_QuickSlot1``IA_QuickSlot8` | Digital | IMC_Default | Direct slot access (KB only) | Quick weapon/item switching |
| `IA_UI_Back` | Digital | IMC_UI | Universal back navigation | Separates "back" from "cancel" semantics |
| `IA_ToggleAccessibility` | Digital | IMC_UI | Toggle accessibility features mid-game | Required by [`BPC_AccessibilitySettings`](../02-player/104_BPC_AccessibilitySettings.md) |
| `IA_SkipCutscene` | Digital | IMC_Default | Hold to skip (contextual) | Already referenced by [`BPC_CutsceneBridge`](../07-narrative/64_BPC_CutsceneBridge.md) |
## File Structure
```
docs/
blueprints/
15-input/ # NEW directory
128_SS_EnhancedInputManager.md # Central subsystem spec
14-data-assets/
129_DA_InputMappingProfile.md # Data Asset for platform profiles
Content/
Framework/
Input/ # NEW directory
Actions/ # IA_* Input Action assets
IA_Move.uasset
IA_Look.uasset
IA_Interact.uasset
... (all 30+ IA_ assets)
Contexts/ # IMC_* Input Mapping Context assets
IMC_Default.uasset
IMC_Inspection.uasset
IMC_WristwatchUI.uasset
IMC_Hiding.uasset
IMC_UI.uasset
DataAssets/
DA_InputMappingProfile.uasset # Platform profiles
```
## API Contracts
### SS_EnhancedInputManager Interface
```cpp
// === Public Functions ===
// Initialize with a profile
void Initialize(DA_InputMappingProfile Profile);
// Context management (stack-based)
void PushContext(E_InputContext ContextType, int32 PriorityOverride = -1);
void PopContext(E_InputContext ContextType);
void SetContextPriority(E_InputContext ContextType, int32 NewPriority);
TArray<E_InputContext> GetActiveContexts() const;
bool IsContextActive(E_InputContext ContextType) const;
// Input state queries (read-only for other systems)
bool IsActionPressed(FName ActionName) const;
float GetActionValue1D(FName ActionName) const;
FVector2D GetActionValue2D(FName ActionName) const;
// Key rebinding (called by SS_SettingsSystem)
void RebindKey(FName ActionName, FKey NewKey, E_InputPlatform Platform);
void ResetToDefaultBindings(E_InputPlatform Platform);
TMap<FName, FKey> GetCurrentBindings(E_InputPlatform Platform) const;
// Input mode coordination with SS_UIManager
void SetInputModeUIOnly();
void SetInputModeGameOnly();
void SetInputModeGameAndUI();
```
### Enums
```cpp
enum E_InputContext {
Default = 0,
Hiding = 1,
WristwatchUI = 2,
Inspection = 3,
UI = 4
};
enum E_InputPlatform {
PC_KeyboardMouse = 0,
Xbox = 1,
PS5_DualSense = 2
};
```
### Event Dispatchers
| Dispatcher | Payload | Description |
|------------|---------|-------------|
| `OnContextPushed` | `E_InputContext Context, int32 Priority` | Fired when a new context is activated |
| `OnContextPopped` | `E_InputContext Context` | Fired when a context is removed |
| `OnInputModeChanged` | `E_InputMode NewMode` | Syncs with SS_UIManager for cursor visibility |
| `OnKeyRebound` | `FName ActionName, FKey NewKey` | Fired after rebinding for UI update |
| `OnPlatformChanged` | `E_InputPlatform NewPlatform` | Fired on input device hot-swap |
### Communication Matrix
| Source | Target | Method | Data |
|--------|--------|--------|------|
| SS_EnhancedInputManager | UEnhancedInputLocalPlayerSubsystem | Direct (UE5 API) | Add/Remove Mapping Context |
| SS_EnhancedInputManager | SS_UIManager | Direct | Input mode changes |
| SS_EnhancedInputManager | SS_SettingsSystem | Direct | Key rebinding requests |
| SS_EnhancedInputManager | WBP_InteractionPromptDisplay | Dispatcher | Current action key icons |
| BPC_InteractionDetector | SS_EnhancedInputManager | Function Call | IsActionPressed for interact |
| BPC_FirearmSystem | SS_EnhancedInputManager | Function Call | GetActionValue1D for trigger |
| BPC_CutsceneBridge | SS_EnhancedInputManager | Function Call | PushContext/PopContext |
| BP_PuzzleDeviceActor | SS_EnhancedInputManager | Function Call | PushContext(Inspection) |
## Success Criteria
1. All 30+ Input Actions are created and mapped across all 3 platforms (PC, Xbox, PS5)
2. Context switching is seamless: pushing a higher-priority context overrides lower ones without blocking
3. Key rebinding via SS_SettingsSystem persists across sessions
4. Input mode changes (GameOnly ↔ UIOnly) correctly show/hide cursor
5. All existing specs that reference `BPC_InputManager` are updated to reference `SS_EnhancedInputManager`
6. Quick slot scrolling and direct selection work on both KB+M and gamepad
7. Hold inputs (HoldBreath, physics-drag) correctly trigger on hold and cancel on early release
8. Cutscene skip works via hold-to-skip (not tap)