Add a confirmation popup¶
Designer · 20 min · No code
Result: a Yes/No question drawn over your own menu screen, with the screen still visible behind a dimmed scrim. Yes runs your work once. No or Back closes only the popup, and the cursor returns to the button you were on.
Before you start¶
- Add a menu screen. You need a screen to ask from; this recipe uses its
W_Bestiary.
How popups work in XenoCore¶
A XenoCore popup is not Lyra's full-screen dialog. It is a small activatable widget pushed
into a stack inside the screen that asks, named OverlayStack. The screen stays drawn
underneath, and the popup's scrim dims it.
The shipped popup is UserInterface/W_XenoCore_ConfirmPopup (its parent class is
XenoCoreConfirmPopupBase). It already does the parts that are easy to get wrong:
- It handles Back, and Back means No, so Back never falls through and closes your screen.
- It sets its own input mode and starts the cursor on Yes, or on No when you ask it to.
- It has a title, a question, and an optional red warning line that collapses when empty.
The Ask Confirm node shows it and continues on exactly one of two pins, On Yes or On No, once, after the popup has closed.
Steps¶
1. Give your screen an overlay stack¶
- Open
W_Bestiaryand switch to the Designer tab. - If your root content is not already an Overlay, right-click it in the Hierarchy and choose Wrap With… › Overlay.
- From the Palette, drag a Common Activatable Widget Stack onto that overlay as its last child, so it draws on top.
- Rename it
OverlayStackand tick Is Variable at the top of the Details panel. - In its Slot settings, set Horizontal Alignment and Vertical Alignment to Fill.
- Set its Visibility to Self Hit Test Invisible, so it never blocks clicks when it is empty.
2. Ask¶
In W_Bestiary's Graph, where you want to ask (for example the click of a "Forget entry"
button):
- Store the widget the cursor is on, such as the clicked button, in a variable
ReturnFocus(a Widget object reference). - Add Ask Confirm (category XenoCore › Confirm) and set:
- Stack: drag in Get OverlayStack.
- Popup Class:
W_XenoCore_ConfirmPopup. - Title:
Forget entry. - Question:
Remove this creature from the bestiary? - Expand the node's advanced pins for Warning (
This cannot be undone.) and Focus Cancel (tick it for a question whose Yes cannot be undone, so a stray press answers No).
- From On Yes, do the work.
- From both On Yes and On No, call Set Focus on
ReturnFocus. - Compile and Save.
Nothing needs binding or unbinding: each Ask Confirm is its own node instance and fires once.
No also covers the unexpected
On No fires for No, for Back, when the popup is closed from outside while still asking (the screen under it closed), and when the popup cannot be shown at all (no stack, or no class; the Output Log says "Ask Confirm: no popup to ask with"). So a graph waiting on the answer is never left hanging.
3. Optional: your own popup look¶
Duplicate W_XenoCore_ConfirmPopup into MyGame/UI and restyle it. Keep its parent class
and these widget names, which the parent class looks for:
| Widget | Type | Required |
|---|---|---|
ConfirmButton, CancelButton |
CommonUI buttons | Yes: the popup will not compile without them |
TitleText, MessageText, WarningText |
Text blocks | Optional |
Make the text blocks Hit Test Invisible, then set Popup Class on the node to your copy.
Asking twice with one popup
Ask Confirm (Existing Popup) asks with a popup that is already on screen instead of pushing a new one. A new question replaces an open one, and the old one answers No.
For programmers: asking from a C++ screen
A C++ screen uses the same popup:
- Give the screen a
UCommonActivatableWidgetStackbound asOverlayStackand aTSubclassOf<UXenoCoreConfirmPopupBase>property set toW_XenoCore_ConfirmPopupon the Blueprint. Don't name the path in C++. - Push it with
OverlayStack->AddWidget<UXenoCoreConfirmPopupBase>(PopupClass), bind the popup'sOnDeactivated()to restore focus (callRemoveAll(this)first, because the popup is pooled), then call one of:AskWithAnswer(Title, Question, Warning, bFocusCancel, [this](bool bConfirmed){ ... }), which reports both answers, once, after the popup has closed;Ask(Title, Question, Warning, bFocusCancel, [this]{ ... }), which calls back on Yes only.
- Is Asking (also Blueprint-callable) is true while a question is open; the save screen uses it to ignore its own keys meanwhile.
UXenoCoreSaveScreenBaseis the worked example. See Add a mechanic by subclassing for setting up a C++ module.
Other screen helpers you can call from Blueprint¶
A Blueprint screen or HUD widget built on the XenoCore bases can also call these nodes:
| Node | On | What it does |
|---|---|---|
| Set Shown Immediate | Any HUD plate (XenoCoreHudPlateBase) |
Show or hide at once, with no fade. Changes opacity only, so the plate keeps ticking |
| Set Show Delay | Any HUD plate | Hold the fade-in back this many seconds, to stagger a column of plates. Fade-out is never delayed |
| Collapse All Except | Any HUD plate | Collapse every widget in the plate except one and the panels above it |
| Begin Hidden, Skip Intro | A HUD plate's own graph | Start hidden (cancel the entrance, then hide), or just cancel the entrance. Call from Construct on a plate that decides its own visibility |
| Set Target | Target plate (XenoCoreTargetPlateBase) |
Show an actor's name and level on the badge, or None to hide it |
| Focus Row, Get Focus Target | Trade row (XenoCoreTradeRowBase) |
Put the cursor on the row's button; the button itself, which is what can hold focus |
| Get Focus Target | Art row (XenoCoreArtRowBase) |
The same, for an Arts list row |
| Get Slot Index, Is Selectable | Save row (XenoCoreSaveRowBase) |
Which slot the row stands for; false for the autosave row while saving, and for a file from a newer build while loading |
Test it¶
- Play, open the menu, open Bestiary, and click the button that asks.
- The popup appears over the screen; the screen is dimmed but visible. With Focus Cancel ticked, the cursor is on No.
- Press B (keyboard Escape). Only the popup closes, and the cursor is back on the button.
- Ask again and choose Yes. The work runs once.
- Ask a third time and choose No. Nothing runs.
If it doesn't work¶
Fails silently: the cursor is lost after the popup closes
Nothing hands focus back automatically, and nothing is logged. Call Set Focus on the stored widget from both pins.
| Symptom | Fix |
|---|---|
| The popup covers the whole screen and the screen behind vanishes | You pushed it onto UI.Layer.Menu instead of OverlayStack. A layer shows only its top widget, so the popup replaced your screen. Give Ask Confirm the screen's own stack. |
| On No fires immediately and no popup appears | Stack or Popup Class is empty. The Output Log says "Ask Confirm: no popup to ask with". |
| Back closes my screen as well | You are using a popup of your own that is not a child of XenoCoreConfirmPopupBase. Such a popup must tick Is Back Handler in its Class Defaults, or Back falls through to the screen under it, which closes and takes the popup with it. |
| The popup asset will not compile | It is missing ConfirmButton or CancelButton, or they are not CommonUI buttons. See step 3. |