UI / Menus¶
UMG-based, mostly Blueprint-authored. The C++ side is thin: it spawns the HUD, owns the rune definition widget hooks, and routes interaction prompts. Menus are a Blueprint discipline.
URuneDefinitionWidget¶
The world-space card that pops up when the player approaches a slot with a rune in it. C++ base, Blueprint subclass for visual layout.
BindWidget rule: Each UPROPERTY with meta = (BindWidget) or BindWidgetOptional must use a C++ member name that exactly matches the widget name in the UMG designer hierarchy — case-sensitive. If the Blueprint widget is named RuneWordText but the C++ field is RuneWordTEXT, the widget subclass fails to compile or the binding is null at runtime.
Bind widgets (meta = (BindWidget)):
BackgroundImage(UImage) — artist-provided background.RuneWordText(UTextBlock) — the rune word.DefinitionText(UTextBlock) — the multi-line definition.WordTypeText(UTextBlock,BindWidgetOptional) — optional NOUN/VERB label.
Public:
SetRuneData(URuneDataAsset*)— populates fields from the data asset.ClearWidget()— empty state.GetWordTypeString(EWordType)— helper for the optional label.
NativeConstruct runs at first display. The default implementation is empty; the BP subclass typically does its own animation entry there.
The widget is hosted by ARuneSlot::DefinitionUIComponent (a UWidgetComponent configured to render world-space). ARuneSlot::ShowDefinitionUI sets the rune data and toggles visibility; HideDefinitionUI clears.
HUD¶
ARephraseCharacter::HUDWidgetClass is a TSubclassOf<UUserWidget> field. BeginPlay instantiates it (HUDWidgetInstance) and adds it to the viewport. That's the entire C++ contract.
Designers wire everything else inside the BP:
- Carry-state indicator (player has rune / no rune).
- Interaction prompts (the text from
IInteractableInterface::GetInteractionPrompt). - Sentence preview (when the current calculator's slots are partially filled).
- Discovery toast (a small notification when
UPlayerRuneKnowledge::DiscoverRunereturns true on first encounter).
Convention: one root widget at viewport level, switched between gameplay/menu sub-widgets via a UWidgetSwitcher.
Menus (status)¶
| Menu | Status |
|---|---|
| Main menu / title screen | Blueprint stub |
| Pause menu | not implemented |
| Settings (volume, key rebind, resolution) | not implemented |
| Save slot picker | not applicable today (single save slot, see SaveLoad) |
Menus are Blueprint-only and live under Content/UI/. New menu work is the responsibility of the Generalist Engineer + Tech Designer pairing; engineers add C++ hooks only when the menu needs to call into game systems that aren't already Blueprint-callable.
Interaction prompt flow¶
- Player overlaps an
IInteractableInterfaceactor. - Character calls
OnPlayerNearby. The actor lights up / shows local visual feedback. - HUD reads the closest interactable's prompt via
GetInteractionPromptand shows it. - On
OnPlayerLeave, HUD hides the prompt.
The HUD's prompt rendering is BP-driven — the C++ side just exposes the closest interactable as a property the BP can read.
Debug UI¶
The G-key debug mode is technically a UI toggle: ARephraseCharacter::ToggleDebugMode flips bDebugMode and fans the change out to every ARuneSlot::SetDebugTextVisible. The slot then shows or hides its DebugRuneWordText (a UTextRenderComponent, not a UMG widget — 3D text in the world).
No engineering-side overlay yet. If we add a runtime stats overlay (active sentence count, registry size, frame-time histograms), it goes into a dedicated WBP_DebugOverlay widget the character spawns alongside the HUD.
Source files¶
Source/Rephrased_Demo/RuneDefinitionWidget.hSource/Rephrased_Demo/RephraseCharacter.h(HUD spawn hook)Source/Rephrased_Demo/RuneSlot.h(DefinitionUIComponent,DebugRuneWordText)
Known constraints¶
- Single HUD widget class. Multiple HUD modes (e.g. exploration vs. puzzle-active) are handled inside the single widget via Blueprint state machines, not by swapping widget classes.
- No localization plumbing yet.
FTexton rune words / definitions / prompts is in place, so flipping a string table on later is straightforward, but noLOCTEXTdiscipline today. - The widget component on slots renders world-space, which is fine for the current camera but doesn't auto-scale with FOV. If the camera FOV changes per scene, designers tune the widget component's scale per slot.
Change history¶
- 2026-05-23 — Gabriel Li — BindWidget case-sensitivity warning; Glossary link for TSubclassOf.
- 2026-05-08 — Gabriel Li — Added baseline change history section for weekly wiki maintenance.