add blueprints
This commit is contained in:
370
docs/blueprints/03-interaction/18_BPC_DiegeticDisplay.md
Normal file
370
docs/blueprints/03-interaction/18_BPC_DiegeticDisplay.md
Normal file
@@ -0,0 +1,370 @@
|
||||
# `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)
|
||||
Reference in New Issue
Block a user