How-To: Push & Pop Screens

Goal: open a menu screen on a layer, hand it data, close it, and optionally block input while a heavy widget streams in.

Prerequisites
Quick Start finished (policy + root layout + registered layers). Your screen derives from UCrimsonActivatableWidget (or any UCommonActivatableWidget).

1. Make the screen a Crimson activatable widget

Create your screen Blueprint with parent Crimson Activatable Widget. In Class Defaults, category Input, pick how it routes input while active:

InputConfig valueMeaningTypical use
DefaultLeave the current input config untouchedHUD elements, overlays that must not steal input
GameAndMenuUI receives input, unhandled input still reaches the gameInteraction prompts, radial menus, quick-slots
GameGame input onlyThe HUD layout itself
MenuUI captures everythingPause menu, settings, inventory

GameMouseCaptureMode / MenuMouseCaptureMode control mouse capture per mode; bIgnoreMoveInput / bIgnoreLookInput additionally freeze pawn movement/camera while the widget is active. See Concept: Input Routing & Activatable Widgets for how these apply and restore.

BP screen Class Defaults -> Input: Input Config = Menu, Game Mouse Capture Mode, Menu Mouse Capture Mode, Ignore Move/Look Input, Force Input Mode Tags On Activate, Restore Input Type On Deactivate.
Verify
With InputConfig = Menu, pushing the screen shows the cursor and stops pawn input; closing it restores gameplay input.

2. Push it

Push Content To Layer For Player (async): Owning Player = Get Player Controller, Widget Class = WBP_Inventory (soft), Layer Name = UI.Layer.GameMenu. BeforePush pin -> Cast to WBP_Inventory -> set its variables; AfterPush -> widget is active.

Use the async Push Content To Layer For Player when the class is a soft reference or you want the BeforePush hook. For an already-loaded hard class, the synchronous node of the same name on Crimson UI Extensions returns the widget directly - then set variables on the return value.

Verify
The screen appears on its layer; data set in BeforePush (or the init lambda) is visible on first frame.

3. Close it

Two equivalent paths: from inside the screen call Deactivate Widget (CommonUI removes a deactivated widget from its stack); from outside call Pop Content From Layer with the widget reference.

cpp
// Inside the widget:
DeactivateWidget();
// From outside (CrimsonCommon):
UCrimsonUIExtensions::PopContentFromLayer(Widget);
// Find-and-remove when you only know the class/instance:
Layout->FindAndRemoveWidgetFromLayer(Widget);
Verify
Closing the top widget re-activates the one below it on the same stack (CommonUI stack behavior).

4. Suspend input during transitions

The async push already suspends input while streaming (its bSuspendInputUntilComplete defaults to true). For your own transitions, Suspend Input For Player returns a token; pass the same token to Resume Input For Player. Both live on Crimson UI Extensions (CrimsonCommon) and are BlueprintCallable.

cpp
const FName Token = UCrimsonUIExtensions::SuspendInputForPlayer(PC, TEXT("CinematicIntro"));
// ... later ...
UCrimsonUIExtensions::ResumeInputForPlayer(PC, Token);

See also

  • How-To: Get the Building Blocks - all the getter chains used above.
  • Concept: Input Routing & Activatable Widgets - what happens on activate/deactivate.
  • How-To: Show Confirmation Dialogs - modal-layer pushes with a result callback.