Skip to content

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::DiscoverRune returns true on first encounter).

Convention: one root widget at viewport level, switched between gameplay/menu sub-widgets via a UWidgetSwitcher.

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

  1. Player overlaps an IInteractableInterface actor.
  2. Character calls OnPlayerNearby. The actor lights up / shows local visual feedback.
  3. HUD reads the closest interactable's prompt via GetInteractionPrompt and shows it.
  4. 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.h
  • Source/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. FText on rune words / definitions / prompts is in place, so flipping a string table on later is straightforward, but no LOCTEXT discipline 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.