- Added BPC_PlatformServiceAbstraction to centralize platform detection and SDK routing for achievements, cloud saves, and overlays. - Updated dependencies across various systems to utilize the new platform service for consistent platform handling. - Deprecated old platform enums in favor of a unified EPlatformFamily enum. - Enhanced documentation for affected systems to reflect changes in platform handling and dependencies.
331 lines
16 KiB
Markdown
331 lines
16 KiB
Markdown
# 128 — Enhanced Input Manager (`SS_EnhancedInputManager`)
|
||
|
||
> **⚡ C++ Status: Full Implementation** — `Source/PG_Framework/Public/Input/SS_EnhancedInputManager.h` provides the complete context stack management: Push/Pop context with priority ordering, input mode coordination, key rebinding, and action value queries. **Auto-created** by UE's subsystem system — no BP child needed. Access from any BP: `Get Game Instance → Get Subsystem(SS_EnhancedInputManager)`. You still need to create 22 IA_* + 5 IMC_* assets in the editor. See `docs/developer/cpp-integration-guide.md` for usage patterns.
|
||
>
|
||
> ---
|
||
|
||
## Purpose
|
||
Centralized Game Instance Subsystem that manages all UE5 Enhanced Input operations: Input Mapping Context push/pop with priority stack, platform-specific binding profiles, key rebinding, input mode coordination with [`SS_UIManager`](docs/blueprints/06-ui/44_SS_UIManager.md), and read-only input state queries for gameplay systems.
|
||
|
||
## Dependencies
|
||
- **Requires:** [`DA_InputMappingProfile`](docs/blueprints/14-data-assets/129_DA_InputMappingProfile.md) (platform profiles), [`GI_GameFramework`](docs/blueprints/01-core/04_GI_GameFramework.md) (subsystem access), [`BPC_PlatformServiceAbstraction`](docs/blueprints/01-core/150_BPC_PlatformServiceAbstraction.md) (central platform detection — replaces own platform enum)
|
||
- **Required By:** All gameplay systems that read input (`BPC_InteractionDetector`, `BPC_FirearmSystem`, `BPC_MovementStateSystem`, `BPC_CutsceneBridge`, `BPC_HidingSystem`, `BPC_ActiveItemSystem`, etc.)
|
||
- **Engine/Plugin Requirements:** Enhanced Input Plugin (UE5 built-in), `UEnhancedInputLocalPlayerSubsystem`
|
||
|
||
## Class Info
|
||
| Property | Value |
|
||
|----------|-------|
|
||
| **Parent Class** | `UGameInstanceSubsystem` |
|
||
| **Class Type** | Game Instance Subsystem |
|
||
| **Asset Path** | `Content/Framework/Core/SS_EnhancedInputManager` |
|
||
| **Implements Interfaces** | None |
|
||
|
||
---
|
||
|
||
## 1. Enums
|
||
|
||
### `E_InputContext`
|
||
| Value | Description |
|
||
|-------|-------------|
|
||
| `Default = 0` | Core gameplay (IMC_Default, Priority 0) |
|
||
| `Hiding = 1` | Hiding spot controls (IMC_Hiding, Priority 5) |
|
||
| `WristwatchUI = 2` | Inventory/watch navigation (IMC_WristwatchUI, Priority 10) |
|
||
| `Inspection = 3` | 3D item inspection (IMC_Inspection, Priority 20) |
|
||
| `UI = 4` | Full-screen menus/pause (IMC_UI, Priority 100) |
|
||
|
||
### `E_InputPlatform` *(deprecated — use EPlatformFamily from BPC_PlatformServiceAbstraction. This enum is kept for DA_InputMappingProfile compatibility but all runtime selection uses the unified enum)*
|
||
| Value | Description |
|
||
|-------|-------------|
|
||
| `PC_KeyboardMouse = 0` | Keyboard + Mouse (maps to `PC_Win64`, `PC_Linux`, `Mac`) |
|
||
| `Xbox = 1` | Xbox Series X\|S / Xbox One (maps to `Xbox_Series` or `Xbox_One`) |
|
||
| `PS5_DualSense = 2` | PlayStation 5 DualSense (maps to `PS5` or `PS5_Pro`) |
|
||
|
||
---
|
||
|
||
## 2. Structs
|
||
|
||
### `S_ActiveContext`
|
||
| Field | Type | Description |
|
||
|-------|------|-------------|
|
||
| `ContextType` | `E_InputContext` | Which context this is |
|
||
| `Priority` | `Int32` | Current priority (may differ from default if overridden) |
|
||
| `MappingContext` | `UInputMappingContext` | Reference to the IMC asset |
|
||
| `TimePushed` | `Float` | Game time when context was added |
|
||
| `bIsActive` | `Bool` | Whether currently active on the subsystem |
|
||
|
||
### `S_KeyBinding`
|
||
| Field | Type | Description |
|
||
|-------|------|-------------|
|
||
| `ActionName` | `FName` | IA_ name this binding is for |
|
||
| `Platform` | `E_InputPlatform` | Platform this binding applies to |
|
||
| `Key` | `FKey` | Current bound key |
|
||
| `DefaultKey` | `FKey` | Factory default key (for reset) |
|
||
| `bIsAxis` | `Bool` | Whether this is an axis binding |
|
||
|
||
---
|
||
|
||
## 3. Variables
|
||
|
||
### Configuration (Set via Initialize)
|
||
| Variable | Type | Default | Category | Description |
|
||
|----------|------|---------|----------|-------------|
|
||
| `InputProfile` | `DA_InputMappingProfile` | `None` | `Config` | Platform profile reference |
|
||
| `DefaultContextPriority` | `TMap<E_InputContext, Int32>` | `{Default:0, Hiding:5, WristwatchUI:10, Inspection:20, UI:100}` | `Config` | Default priority table |
|
||
|
||
### Internal (Private)
|
||
| Variable | Type | Default | Category | Description |
|
||
|----------|------|---------|----------|-------------|
|
||
| `ActiveContexts` | `TArray<S_ActiveContext>` | `Empty` | `State` | Currently pushed contexts (stack, highest first) |
|
||
| `CurrentBindings` | `TMap<E_InputPlatform, TArray<S_KeyBinding>>` | `Empty` | `State` | Current key bindings per platform |
|
||
| `DefaultBindings` | `TMap<E_InputPlatform, TArray<S_KeyBinding>>` | `Empty` | `State` | Factory default bindings |
|
||
| `CurrentInputMode` | `E_InputMode` | `GameOnly` | `State` | Current input mode (synced with SS_UIManager) |
|
||
| `bIsInitialized` | `Bool` | `false` | `State` | Whether Initialize has been called |
|
||
| `LocalPlayerSubsystem` | `UEnhancedInputLocalPlayerSubsystem` | `None` | `Cache` | Cached reference to the Enhanced Input subsystem |
|
||
|
||
---
|
||
|
||
## 4. Functions
|
||
|
||
### Public Functions
|
||
|
||
#### `Initialize` → `void`
|
||
- **Description:** Loads platform profile, caches Enhanced Input subsystem, builds default binding table.
|
||
- **Parameters:**
|
||
| Param | Type | Description |
|
||
|-------|------|-------------|
|
||
| `Profile` | `DA_InputMappingProfile` | Platform profile to load |
|
||
- **Blueprint Authority:** Any
|
||
- **Flow:**
|
||
1. Set InputProfile = Profile
|
||
2. Cache EnhancedInputLocalPlayerSubsystem via GetOwningPlayerController()
|
||
3. Populate DefaultBindings for each platform from DA_InputMappingProfile
|
||
4. Copy DefaultBindings to CurrentBindings
|
||
5. Set bIsInitialized = true
|
||
6. Broadcast OnInputManagerInitialized
|
||
|
||
#### `PushContext` → `void`
|
||
- **Description:** Pushes an Input Mapping Context onto the player's active contexts.
|
||
- **Parameters:**
|
||
| Param | Type | Description |
|
||
|-------|------|-------------|
|
||
| `ContextType` | `E_InputContext` | Which context to push |
|
||
| `PriorityOverride` | `Int32` | Optional priority override (-1 uses default) |
|
||
- **Blueprint Authority:** Any
|
||
- **Flow:**
|
||
1. Validate bIsInitialized and LocalPlayerSubsystem
|
||
2. If context already active: update priority if changed, return
|
||
3. Look up IMC from DA_InputMappingProfile for ContextType
|
||
4. Resolve priority: PriorityOverride if >= 0, else DefaultContextPriority[ContextType]
|
||
5. Call LocalPlayerSubsystem.AddMappingContext(IMC, Priority)
|
||
6. Add S_ActiveContext to ActiveContexts, sorted by priority descending
|
||
7. Broadcast OnContextPushed
|
||
|
||
#### `PopContext` → `void`
|
||
- **Description:** Removes an Input Mapping Context from the player's active contexts.
|
||
- **Parameters:**
|
||
| Param | Type | Description |
|
||
|-------|------|-------------|
|
||
| `ContextType` | `E_InputContext` | Which context to pop |
|
||
- **Blueprint Authority:** Any
|
||
- **Flow:**
|
||
1. Validate bIsInitialized
|
||
2. Find S_ActiveContext by ContextType
|
||
3. If not found: log warning, return
|
||
4. Call LocalPlayerSubsystem.RemoveMappingContext(IMC)
|
||
5. Remove from ActiveContexts
|
||
6. Broadcast OnContextPopped
|
||
|
||
#### `SetContextPriority` → `void`
|
||
- **Description:** Adjusts priority of an active context.
|
||
- **Parameters:**
|
||
| Param | Type | Description |
|
||
|-------|------|-------------|
|
||
| `ContextType` | `E_InputContext` | Target context |
|
||
| `NewPriority` | `Int32` | New priority value |
|
||
- **Flow:** Remove and re-add the IMC with new priority.
|
||
|
||
#### `GetActiveContexts` → `TArray<E_InputContext>`
|
||
- **Description:** Returns list of currently active context types. Read-only.
|
||
|
||
#### `IsContextActive` → `Bool`
|
||
- **Description:** Check if a specific context is active.
|
||
- **Parameters:**
|
||
| Param | Type | Description |
|
||
|-------|------|-------------|
|
||
| `ContextType` | `E_InputContext` | Context to check |
|
||
|
||
#### `IsActionPressed` → `Bool`
|
||
- **Description:** Read-only query: is an action currently pressed?
|
||
- **Parameters:**
|
||
| Param | Type | Description |
|
||
|-------|------|-------------|
|
||
| `ActionName` | `FName` | IA_ name to check |
|
||
- **Flow:** Delegates to `UEnhancedInputLocalPlayerSubsystem.IsPressed()`
|
||
|
||
#### `GetActionValue1D` → `Float`
|
||
- **Description:** Read-only query: current 1D axis value.
|
||
- **Parameters:**
|
||
| Param | Type | Description |
|
||
|-------|------|-------------|
|
||
| `ActionName` | `FName` | IA_ name to query |
|
||
|
||
#### `GetActionValue2D` → `FVector2D`
|
||
- **Description:** Read-only query: current 2D axis value.
|
||
- **Parameters:**
|
||
| Param | Type | Description |
|
||
|-------|------|-------------|
|
||
| `ActionName` | `FName` | IA_ name to query |
|
||
|
||
#### `RebindKey` → `Bool`
|
||
- **Description:** Rebinds an action to a new key for the given platform.
|
||
- **Parameters:**
|
||
| Param | Type | Description |
|
||
|-------|------|-------------|
|
||
| `ActionName` | `FName` | IA_ name |
|
||
| `NewKey` | `FKey` | New key to bind |
|
||
| `Platform` | `E_InputPlatform` | Which platform |
|
||
- **Flow:**
|
||
1. Update CurrentBindings[Platform]
|
||
2. Modify the IMC's key mapping for the action
|
||
3. Broadcast OnKeyRebound
|
||
4. Return true if successful
|
||
|
||
#### `ResetToDefaultBindings` → `void`
|
||
- **Description:** Resets all bindings for a platform to defaults.
|
||
- **Parameters:**
|
||
| Param | Type | Description |
|
||
|-------|------|-------------|
|
||
| `Platform` | `E_InputPlatform` | Which platform to reset |
|
||
|
||
#### `GetCurrentBindings` → `TMap<FName, FKey>`
|
||
- **Description:** Returns current key bindings for a platform (for settings UI).
|
||
- **Parameters:**
|
||
| Param | Type | Description |
|
||
|-------|------|-------------|
|
||
| `Platform` | `E_InputPlatform` | Which platform |
|
||
|
||
#### `SetInputModeUIOnly` → `void`
|
||
- **Description:** Switches to UI-only input mode (cursor visible, gameplay blocked).
|
||
- **Flow:** Calls `PC_PlayerController.SetInputMode(UIOnly)` and syncs with `SS_UIManager`
|
||
|
||
#### `SetInputModeGameOnly` → `void`
|
||
- **Description:** Switches to game-only input mode (cursor hidden).
|
||
- **Flow:** Calls `PC_PlayerController.SetInputMode(GameOnly)` and syncs with `SS_UIManager`
|
||
|
||
#### `SetInputModeGameAndUI` → `void`
|
||
- **Description:** Switches to game+UI input mode (cursor visible, game active).
|
||
- **Flow:** Calls `PC_PlayerController.SetInputMode(GameAndUI)` and syncs with `SS_UIManager`
|
||
|
||
---
|
||
|
||
## 5. Event Dispatchers
|
||
|
||
| Dispatcher | Parameters | Bind Access | Description |
|
||
|------------|-----------|-------------|-------------|
|
||
| `OnInputManagerInitialized` | — | `Public` | Fired after Initialize completes |
|
||
| `OnContextPushed` | `E_InputContext Context`, `Int32 Priority` | `Public` | Fired when a new context is activated |
|
||
| `OnContextPopped` | `E_InputContext Context` | `Public` | Fired when a context is removed |
|
||
| `OnInputModeChanged` | `E_InputMode NewMode` | `Public` | Fired when input mode changes |
|
||
| `OnKeyRebound` | `FName ActionName`, `FKey NewKey` | `Public` | Fired after key rebinding |
|
||
| `OnPlatformChanged` | `E_InputPlatform NewPlatform` | `Public` | Fired on input device hot-swap |
|
||
|
||
---
|
||
|
||
## 6. Overridden Events / Custom Events
|
||
|
||
### Event: `Initialize` (Subsystem)
|
||
- **Description:** Called by the engine when the subsystem is created. Does nothing — full init deferred to `Initialize(Profile)` to ensure DA is loaded first.
|
||
- **Flow:** Cache self-reference for `FL_GameUtilities::GetInputManager()`
|
||
|
||
### Event: `Deinitialize`
|
||
- **Description:** Cleanup on subsystem destruction.
|
||
- **Flow:**
|
||
1. Pop all active contexts
|
||
2. Clear cached references
|
||
3. Broadcast final state
|
||
|
||
---
|
||
|
||
## 7. Blueprint Graph Logic Flow
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
A[GI_GameFramework.Startup] --> B[SS_EnhancedInputManager.Initialize]
|
||
B --> C[Load DA_InputMappingProfile]
|
||
C --> D[Cache EnhancedInputLocalPlayerSubsystem]
|
||
D --> E[Build DefaultBindings]
|
||
E --> F[Broadcast OnInitialized]
|
||
|
||
G[PushContext] --> H{Already active?}
|
||
H -->|Yes| I[Update priority]
|
||
H -->|No| J[Lookup IMC from DA]
|
||
J --> K[AddMappingContext Priority]
|
||
K --> L[ActiveContexts sorted insert]
|
||
L --> M[Broadcast OnContextPushed]
|
||
|
||
N[PopContext] --> O{Found in ActiveContexts?}
|
||
O -->|Yes| P[RemoveMappingContext]
|
||
P --> Q[Remove from array]
|
||
Q --> R[Broadcast OnContextPopped]
|
||
|
||
S[RebindKey] --> T[Update CurrentBindings map]
|
||
T --> U[Modify IMC key mapping]
|
||
U --> V[Broadcast OnKeyRebound]
|
||
```
|
||
|
||
---
|
||
|
||
## 8. Communication Matrix
|
||
|
||
| Who Talks | How | What Is Sent |
|
||
|-----------|-----|-------------|
|
||
| `SS_EnhancedInputManager` | `Direct (UE5 API)` | `UEnhancedInputLocalPlayerSubsystem::AddMappingContext / RemoveMappingContext` |
|
||
| `SS_EnhancedInputManager` | `Direct` | `SS_UIManager::OnInputModeChanged` — input mode synchronization |
|
||
| `SS_EnhancedInputManager` | `Dispatcher` | `OnContextPushed/OnContextPopped` → Any listener (UI, audio, narrative) |
|
||
| `SS_EnhancedInputManager` | `Direct` | `SS_SettingsSystem::ApplyControlSettings` — key rebinding |
|
||
| `BPC_InteractionDetector` | `Function Call` | `SS_EnhancedInputManager::IsActionPressed("IA_Interact")` |
|
||
| `BPC_FirearmSystem` | `Function Call` | `SS_EnhancedInputManager::GetActionValue1D("IA_PrimaryAction")` |
|
||
| `BPC_MovementStateSystem` | `Function Call` | `SS_EnhancedInputManager::GetActionValue2D("IA_Move")` |
|
||
| `BPC_CutsceneBridge` | `Function Call` | `SS_EnhancedInputManager::PushContext/PopContext` |
|
||
| `BPC_HidingSystem` | `Function Call` | `SS_EnhancedInputManager::PushContext(Hiding) / PopContext(Hiding)` |
|
||
| `BPC_ActiveItemSystem` | `Function Call` | `SS_EnhancedInputManager::IsActionPressed("IA_QuickSlot1")` |
|
||
| `BPC_HapticsController` (148) | `Function Call` | `SS_EnhancedInputManager::GetControllerPlatform()` — for platform detection |
|
||
| `BPC_PlatformServiceAbstraction` (150) | `Function Call / Bind OnPlatformReady` | `GetDefaultInputProfile()` — selects correct DA_InputMappingProfile for detected platform |
|
||
| `WBP_PauseMenu` | `Function Call` | `SS_EnhancedInputManager::PushContext(UI) / PopContext(UI)` |
|
||
| `WBP_InventoryMenu` | `Function Call` | `SS_EnhancedInputManager::PushContext(WristwatchUI)` |
|
||
| `BP_PuzzleDeviceActor` | `Function Call` | `SS_EnhancedInputManager::PushContext(Inspection)` |
|
||
| `WBP_InteractionPromptDisplay` | `Dispatcher listener` | `OnKeyRebound` → update displayed key icons |
|
||
|
||
---
|
||
|
||
## 9. Validation / Testing Checklist
|
||
|
||
- [ ] Initialize correctly loads DA_InputMappingProfile and caches subsystem
|
||
- [ ] PushContext adds IMC at correct priority on EnhancedInputLocalPlayerSubsystem
|
||
- [ ] PopContext removes IMC and restores lower-priority context functionality
|
||
- [ ] Higher priority context correctly overrides lower priority bindings (e.g., WristwatchUI blocks IA_Move)
|
||
- [ ] IsActionPressed returns correct state for active context actions
|
||
- [ ] RebindKey persists for the session and dispatches OnKeyRebound
|
||
- [ ] ResetToDefaultBindings restores all keys to factory defaults
|
||
- [ ] SetInputModeUIOnly shows cursor and blocks gameplay inputs
|
||
- [ ] SetInputModeGameOnly hides cursor and restores gameplay inputs
|
||
- [ ] Edge case: Pushing same context twice updates priority instead of double-stacking
|
||
- [ ] Edge case: Popping a non-active context logs warning but doesn't crash
|
||
- [ ] Edge case: Input mode changes during cutscene (UI opens on top) correctly stacks
|
||
- [ ] Edge case: Controller hot-swap fires OnPlatformChanged and loads correct profile
|
||
|
||
---
|
||
|
||
## 10. Reuse Notes
|
||
|
||
- All gameplay systems should query input state through SS_EnhancedInputManager, never through raw EnhancedInputSubsystem calls
|
||
- Context priority ladder is configurable via DefaultContextPriority variable
|
||
- The SS_ prefix matches the existing `SS_UIManager`, `SS_SettingsSystem`, `SS_SaveManager` pattern
|
||
- Platform-specific IMCs allow controller glyphs (Xbox vs PS5 button icons) to differ
|
||
- For accessibility: hold-to-toggle actions (e.g., Crouch) can be configured as toggle vs hold via the IMC
|
||
- Quick Slot 1–8 inputs are Keyboard-only; gamepad uses IA_QuickSlotScroll axis
|
||
- This subsystem replaces the previously-referenced `BPC_InputManager` — all existing docs must be updated
|
||
|
||
---
|
||
|
||
*Blueprint Spec: Enhanced Input Manager. Conforms to TEMPLATE.md v1.0 — part of the UE5 Modular Game Framework, INPUT layer.* |