214 lines
11 KiB
Markdown
214 lines
11 KiB
Markdown
# 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 | 1–8 | 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) |