370 lines
16 KiB
Markdown
370 lines
16 KiB
Markdown
# `BPC_DiegeticDisplay` — Diegetic Display System
|
||
|
||
**Parent Class:** `ActorComponent`
|
||
**Category:** Interaction / UI
|
||
**Target UE Version:** 5.5–5.7
|
||
**Build Phase:** 2 — Interaction
|
||
|
||
---
|
||
|
||
## 1. Overview
|
||
|
||
`BPC_DiegeticDisplay` manages any in-world screen that renders game UI directly inside the 3D scene — watches, PDAs, tablets, computer monitors, cockpit screens. Instead of traditional HUD overlays, the player looks down at their character's wrist (watch) or picks up a tablet to see inventory/map/messages rendered as a world-space widget on a static mesh.
|
||
|
||
The component provides a 6-mode state machine (`Off → Splash → Idle → Menu → Messaging → Mapping/Scanning`), handles input routing to the active widget, manages screen transitions (flicker, boot sequence, static interference), and communicates with other systems via Event Dispatchers.
|
||
|
||
---
|
||
|
||
## 2. Mermaid — Display Mode State Machine
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
A[Off] --> B{Power On?}
|
||
B -->|Yes| C[Splash]
|
||
C --> D[Idle]
|
||
D --> E{User Input?}
|
||
E -->|Open Menu| F[Menu]
|
||
E -->|Open Map| G[Mapping]
|
||
E -->|Receive Message| H[Messaging]
|
||
E -->|Activate Scan| I[Scanning]
|
||
F --> J{Close Menu?}
|
||
J -->|Yes| D
|
||
G --> K{Close Map?}
|
||
K -->|Yes| D
|
||
H --> L{Message Dismissed?}
|
||
L -->|Yes| D
|
||
I --> M{Scan Complete?}
|
||
M -->|Yes| D
|
||
D --> N{Idle Timeout?}
|
||
N -->|Yes| A
|
||
```
|
||
|
||
---
|
||
|
||
## 3. Enums
|
||
|
||
### `E_DiegeticDisplayMode`
|
||
|
||
| Value | Description |
|
||
|-------|-------------|
|
||
| `Off` | Screen completely off (black/no widget). |
|
||
| `Splash` | Boot-up animation playing (logo, startup sequence). |
|
||
| `Idle` | Default active state. May show time, low-priority info. |
|
||
| `Menu` | Full menu — inventory, settings, journal. |
|
||
| `Messaging` | Incoming/outgoing message display. |
|
||
| `Mapping` | Map or floorplan overlay. |
|
||
| `Scanning` | Active scanning mode (environment analysis, entity detection). |
|
||
|
||
### `E_ScreenEffect`
|
||
|
||
| Value | Description |
|
||
|-------|-------------|
|
||
| `None` | No effect — clean image. |
|
||
| `Static` | Analog TV static / interference. |
|
||
| `Flicker` | Rapid on/off flicker (power fluctuation). |
|
||
| `Glitch` | Digital artifact corruption. |
|
||
| `ScanLine` | CRT scan lines overlay. |
|
||
| `BootSequence` | OS-style boot animation (loading bars, text crawl). |
|
||
| `LowBattery` | Dim + pulsing warning overlay. |
|
||
|
||
### `E_DisplayInputMode`
|
||
|
||
| Value | Description |
|
||
|-------|-------------|
|
||
| `Locked` | Display ignores player input. |
|
||
| `Passthrough` | Input forwarded to active widget. |
|
||
| `Modal` | Input consumed entirely by display (menu open). |
|
||
|
||
---
|
||
|
||
## 4. Structs
|
||
|
||
### `S_DiegeticDisplayConfig`
|
||
|
||
| Field | Type | Description |
|
||
|-------|------|-------------|
|
||
| `DisplayName` | `FText` | Human-readable name (e.g., "Wrist Link", "PDA-7"). |
|
||
| `DefaultMode` | `E_DiegeticDisplayMode` | Mode to start in at BeginPlay. |
|
||
| `bStartPoweredOn` | `bool` | If false, starts in Off mode. |
|
||
| `WidgetClass` | `TSubclassOf<UUserWidget>` | World-space widget class to render on the screen. |
|
||
| `ScreenMeshComponent` | `FName` | Name of the static mesh component the widget renders on. |
|
||
| `ScreenSize` | `FVector2D` | Widget resolution in pixels (e.g., 256x144). |
|
||
| `InteractionDistance` | `float` | Max distance to interact with the display (0 = attached to player). |
|
||
| `bIsPlayerOwned` | `bool` | If true, attached to player (watch) vs. world object (terminal). |
|
||
| `IdleTimeoutSeconds` | `float` | Seconds of inactivity before powering off. 0 = never timeout. |
|
||
| `BootDuration` | `float` | Seconds the Splash animation plays. |
|
||
| `bHasMapMode` | `bool` | If true, Mapping mode is available. |
|
||
| `bHasScanMode` | `bool` | If true, Scanning mode is available. |
|
||
| `bReplicates` | `bool` | Whether display state is replicated. |
|
||
|
||
### `S_ScreenState`
|
||
|
||
| Field | Type | Description |
|
||
|-------|------|-------------|
|
||
| `CurrentMode` | `E_DiegeticDisplayMode` | Active display mode. |
|
||
| `ActiveEffect` | `E_ScreenEffect` | Currently playing visual effect. |
|
||
| `EffectIntensity` | `float` | 0–1 intensity of the active effect. |
|
||
| `InputMode` | `E_DisplayInputMode` | Current input routing mode. |
|
||
| `BatteryLevel` | `float` | 0–1 remaining battery (if applicable). |
|
||
| `bIsPoweredOn` | `bool` | Quick check for power state. |
|
||
|
||
### `S_MessagePayload`
|
||
|
||
| Field | Type | Description |
|
||
|-------|------|-------------|
|
||
| `SenderName` | `FText` | Name of message sender. |
|
||
| `MessageBody` | `FText` | Message text content. |
|
||
| `bIsUrgent` | `bool` | If true, forces display to Messaging mode with priority. |
|
||
| `AssociatedQuestTag` | `FGameplayTag` | Quest/objective this message relates to. |
|
||
| `AudioAttachment` | `USoundBase*` | Optional audio clip attached to message. |
|
||
|
||
---
|
||
|
||
## 5. Variables
|
||
|
||
### Configuration (Instance Editable, Expose On Spawn)
|
||
|
||
| Variable | Type | Description |
|
||
|----------|------|-------------|
|
||
| `DisplayConfig` | `S_DiegeticDisplayConfig` | Primary configuration struct. |
|
||
| `IdleWidget` | `TSubclassOf<UUserWidget>` | Widget to display in Idle mode. |
|
||
| `MenuWidget` | `TSubclassOf<UUserWidget>` | Widget to display in Menu mode. |
|
||
| `MessagingWidget` | `TSubclassOf<UUserWidget>` | Widget for incoming/outgoing messages. |
|
||
| `MapWidget` | `TSubclassOf<UUserWidget>` | Widget for mapping overlay. |
|
||
| `ScanWidget` | `TSubclassOf<UUserWidget>` | Widget for scanning mode. |
|
||
|
||
### State (Blueprint Read Only)
|
||
|
||
| Variable | Type | Description |
|
||
|----------|------|-------------|
|
||
| `CurrentState` | `S_ScreenState` | Struct holding all current screen state. |
|
||
| `ActiveWidget` | `UUserWidget*` | Reference to the currently displayed widget instance. |
|
||
| `ScreenMesh` | `UStaticMeshComponent*` | Cached reference to the screen mesh. |
|
||
| `IdleTimerHandle` | `FTimerHandle` | Handle for idle power-off timer. |
|
||
| `BootTimerHandle` | `FTimerHandle` | Handle for boot-up duration timer. |
|
||
| `PendingMessages` | `TArray<S_MessagePayload>` | Queue of messages to display. |
|
||
| `CurrentMessageIndex` | `int32` | Index into PendingMessages for cycling. |
|
||
|
||
### Input Handling (Blueprint Read Only)
|
||
|
||
| Variable | Type | Description |
|
||
|----------|------|-------------|
|
||
| `bInputConsumed` | `bool` | Whether the display is currently consuming input. |
|
||
| `InputActionBindings` | `TArray<FInputActionBinding>` | Active input bindings for display mode. |
|
||
|
||
---
|
||
|
||
## 6. Functions & Events
|
||
|
||
### Public Functions
|
||
|
||
| Function | Description |
|
||
|----------|-------------|
|
||
| `PowerOn` | Boots the display. Plays Splash sequence, then transitions to Idle. |
|
||
| `PowerOff` | Immediately turns off display, clears widget, kills idle timer. |
|
||
| `SetDisplayMode` | Transitions to any `E_DiegeticDisplayMode`. Plays transition effect. |
|
||
| `ApplyScreenEffect` | Applies a temporary `E_ScreenEffect` for a given duration. |
|
||
| `ClearScreenEffect` | Immediately clears active effect, returns to clean image. |
|
||
| `ReceiveMessage` | Adds a `S_MessagePayload` to the queue. If current mode is Idle, auto-switches to Messaging. |
|
||
| `DismissMessage` | Closes current message. If queue has more, shows next; else returns to Idle. |
|
||
| `OpenMenu` | Transitions to Menu mode. Locks input to display. |
|
||
| `CloseMenu` | Returns to Idle mode. Releases input. |
|
||
| `OpenMap` | Transitions to Mapping mode (if `bHasMapMode`). |
|
||
| `CloseMap` | Returns to Idle mode. |
|
||
| `StartScan` | Begins Scanning mode (if `bHasScanMode`). |
|
||
| `StopScan` | Ends Scanning mode, returns to Idle. |
|
||
| `ToggleDisplay` | Toggles between current mode and Off/Idle based on power state. |
|
||
| `IsDisplayActive` | Returns true if powered on and not Off/Splash/Boot. |
|
||
| `GetScreenState` | Returns the `S_ScreenState` struct. |
|
||
|
||
### Protected Functions
|
||
|
||
| Function | Description |
|
||
|----------|-------------|
|
||
| `BeginPlay` | Caches references, creates widget instance if auto-start. |
|
||
| `Tick` | If `ActiveEffect != None`, applies effect material parameter animation. |
|
||
| `CreateWidgetInstance` | Creates the world-space widget for the given mode class. Attaches to `ScreenMesh`. |
|
||
| `DestroyWidgetInstance` | Removes and destroys current widget. |
|
||
| `PlayBootSequence` | Timelines splash animation. On complete, calls `OnBootComplete`. |
|
||
| `OnBootComplete` | Transitions to Idle, starts idle timeout timer. |
|
||
| `StartIdleTimer` | Resets and starts the idle timeout. |
|
||
| `OnIdleTimeout` | Powers off the display. |
|
||
| `SetupInputForMode` | Binds/unbinds input actions based on `CurrentState.InputMode`. |
|
||
| `HandleMenuInput` | Processes navigation/select inputs in Menu mode. |
|
||
| `HandleMessageInput` | Processes dismiss/respond inputs in Messaging mode. |
|
||
| `HandleMapInput` | Processes pan/zoom inputs in Mapping mode. |
|
||
| `HandleScanInput` | Processes scan activation input. |
|
||
|
||
### Event Dispatchers
|
||
|
||
| Dispatcher | Payload | Description |
|
||
|------------|---------|-------------|
|
||
| `OnDisplayModeChanged` | `E_DiegeticDisplayMode NewMode`, `E_DiegeticDisplayMode PreviousMode` | Fired on any mode transition. |
|
||
| `OnDisplayPoweredOn` | — | Fired after boot sequence completes. |
|
||
| `OnDisplayPoweredOff` | — | Fired when display is turned off. |
|
||
| `OnMessageReceived` | `S_MessagePayload Message` | Fired when a new message enters the queue. |
|
||
| `OnMessageDismissed` | `S_MessagePayload Message` | Fired when a message is dismissed. |
|
||
| `OnScreenEffectStarted` | `E_ScreenEffect Effect`, `float Duration` | Fired when a screen effect begins. |
|
||
| `OnScreenEffectEnded` | `E_ScreenEffect Effect` | Fired when a screen effect ends. |
|
||
| `OnDisplayInputLocked` | `bool bIsLocked` | Fired when input mode changes to Locked or unlocked. |
|
||
|
||
---
|
||
|
||
## 7. Blueprint Graph Flow
|
||
|
||
```
|
||
Event BeginPlay
|
||
→ GetOwner → FindComponentByTag (ScreenMeshComponent name) → Cache ScreenMesh
|
||
→ If DisplayConfig.bStartPoweredOn → Call PowerOn
|
||
→ Else → Set CurrentState.CurrentMode = Off
|
||
|
||
PowerOn
|
||
→ Set CurrentState.bIsPoweredOn = true
|
||
→ Set CurrentState.InputMode = Locked
|
||
→ Broadcast OnDisplayModeChanged (Off → Splash)
|
||
→ PlayBootSequence
|
||
|
||
PlayBootSequence
|
||
→ ApplyScreenEffect (BootSequence)
|
||
→ Set Timer by Event (DisplayConfig.BootDuration, Call OnBootComplete)
|
||
|
||
OnBootComplete
|
||
→ ClearScreenEffect
|
||
→ Set CurrentState.CurrentMode = Idle
|
||
→ CreateWidgetInstance (IdleWidget)
|
||
→ Set CurrentState.InputMode = Passthrough
|
||
→ Broadcast OnDisplayPoweredOn
|
||
→ Broadcast OnDisplayModeChanged (Splash → Idle)
|
||
→ StartIdleTimer
|
||
|
||
SetDisplayMode
|
||
→ Store PreviousMode = CurrentState.CurrentMode
|
||
→ If PreviousMode == NewMode → return
|
||
→ DestroyWidgetInstance
|
||
→ Broadcast OnDisplayModeChanged (PreviousMode → NewMode)
|
||
→ Set CurrentState.CurrentMode = NewMode
|
||
→ Branch on NewMode:
|
||
— Menu → CreateWidgetInstance (MenuWidget), SetupInputForMode (Modal)
|
||
— Messaging → CreateWidgetInstance (MessagingWidget), SetupInputForMode (Modal)
|
||
— Mapping → CreateWidgetInstance (MapWidget), SetupInputForMode (Modal)
|
||
— Scanning → CreateWidgetInstance (ScanWidget), SetupInputForMode (Modal)
|
||
— Idle → CreateWidgetInstance (IdleWidget), SetupInputForMode (Passthrough), StartIdleTimer
|
||
→ If NewMode != Idle → Clear idle timer
|
||
|
||
ReceiveMessage
|
||
→ PendingMessages.Add(Message)
|
||
→ If CurrentState.CurrentMode == Idle:
|
||
→ SetDisplayMode (Messaging)
|
||
→ If CurrentState.CurrentMode == Messaging:
|
||
→ Update widget to show new message count
|
||
→ Broadcast OnMessageReceived
|
||
|
||
DismissMessage
|
||
→ Remove CurrentMessage from PendingMessages
|
||
→ If PendingMessages.Num() > 0:
|
||
→ Show next message
|
||
→ Else:
|
||
→ SetDisplayMode (Idle)
|
||
→ Broadcast OnMessageDismissed
|
||
|
||
PowerOff
|
||
→ ClearScreenEffect
|
||
→ DestroyWidgetInstance
|
||
→ Clear Input Bindings
|
||
→ Set CurrentState.bIsPoweredOn = false
|
||
→ Set CurrentState.CurrentMode = Off
|
||
→ Clear IdleTimerHandle
|
||
→ Broadcast OnDisplayPoweredOff
|
||
→ Broadcast OnDisplayModeChanged (previous → Off)
|
||
|
||
OpenMenu
|
||
→ SetDisplayMode (Menu)
|
||
|
||
CloseMenu
|
||
→ SetDisplayMode (Idle)
|
||
|
||
Event Tick (DeltaTime)
|
||
→ If ActiveEffect != None and ActiveEffectDuration > 0:
|
||
→ Update material parameter for effect animation (flicker intensity, static noise)
|
||
→ Decrement remaining duration
|
||
→ If duration expired → ClearScreenEffect
|
||
```
|
||
|
||
---
|
||
|
||
## 8. Replication
|
||
|
||
| Variable | Replication | Callback |
|
||
|----------|-------------|----------|
|
||
| `CurrentState.CurrentMode` | `RepNotify` | `OnRep_DisplayMode` — recreates widget on remote clients |
|
||
| `CurrentState.ActiveEffect` | `Replicated` | — |
|
||
| `CurrentState.bIsPoweredOn` | `Replicated` | — |
|
||
|
||
**Authority:** Server controls power/mode transitions. Client predicts input for Menu/Message dismissal, but server validates.
|
||
|
||
---
|
||
|
||
## 9. Widget Setup (Per-Mode)
|
||
|
||
| Mode | Widget Content |
|
||
|------|----------------|
|
||
| `Idle` | Time display, low-priority notifications, battery indicator. |
|
||
| `Menu` | Radial or list menu: Inventory, Journal, Settings, Map, Messages. |
|
||
| `Messaging` | Scrolling text log with sender avatar, reply options, audio playback. |
|
||
| `Mapping` | 2D floorplan with player position marker, discovered rooms, objective markers. |
|
||
| `Scanning` | Overlaid data readouts: entity heat signatures, material composition, structural integrity. |
|
||
|
||
All widgets are added as `UUserWidget` instances attached to the screen mesh via `AddToViewport`/`SetWidget` on a `UWidgetComponent`. The component handles creation/destruction; individual widgets handle their own internal state.
|
||
|
||
---
|
||
|
||
## 10. Dependencies & Communication
|
||
|
||
| System | Relationship |
|
||
|--------|--------------|
|
||
| `BPC_InteractionDetector` | Detects world terminals; calls `Interact_Implementation` on the host actor. |
|
||
| `BPC_InventoryComponent` | Menu mode reads inventory contents to display in widget. |
|
||
| `BPC_MappingSubsystem` | Supplies floorplan data to Map widget. |
|
||
| `BPC_ScanningSubsystem` | Supplies scan results to Scan widget. |
|
||
| `GI_GameFramework` | Provides game time, date, and phase info for idle widget display. |
|
||
| `BPC_StressSystem` | High stress may trigger screen flicker/glitch effects. |
|
||
| `BPC_HealthSystem` | Low health may apply low battery / dimming effect. |
|
||
| `BPC_PlayerMetricsTracker` | Logs display usage events for analytics. |
|
||
| `BPC_AdaptiveDifficulty` | May adjust idle timeout or boot duration based on player performance. |
|
||
| `Save/Load System` | Saves `CurrentState` and `PendingMessages` array for restore. |
|
||
| `Narrative Subsystem` | Pushes messages via `ReceiveMessage` for story-driven communication. |
|
||
|
||
---
|
||
|
||
## 11. Success Criteria
|
||
|
||
1. Display boots with splash sequence and transitions to idle.
|
||
2. Player can open/close menu from idle.
|
||
3. Receiving a message from narrative subsystem forces display to Messaging mode.
|
||
4. Player dismisses message and display returns to idle.
|
||
5. Display powers off after idle timeout; interact to power back on.
|
||
6. Screen effects (static, flicker, glitch) play on demand and clear correctly.
|
||
7. Stress/health systems trigger appropriate visual feedback on the display.
|
||
8. Multiplayer: display mode syncs across clients.
|
||
9. Save/load restores display mode, pending messages, and effect state.
|
||
10. Multiple displays (watch + terminal) operate independently with separate state.
|
||
|
||
---
|
||
|
||
## 12. Data Flow Summary
|
||
|
||
```
|
||
External System (e.g. Narrative)
|
||
→ calls ReceiveMessage (S_MessagePayload)
|
||
→ BPC_DiegeticDisplay.PendingMessages.Add
|
||
→ Auto-switches to Messaging mode if currently Idle
|
||
→ Broadcast OnMessageReceived
|
||
→ Widget shows message content
|
||
→ Player dismisses → DismissMessage
|
||
→ Broadcast OnMessageDismissed
|
||
→ If queue empty → return to Idle
|
||
|
||
Player Input (Menu)
|
||
→ Input routed via SetupInputForMode (Modal)
|
||
→ Widget handles navigation
|
||
→ On close → CloseMenu → SetDisplayMode (Idle) |