What the stack does
Each local player has a screen stack, the Rolly Save Core UI Stack Subsystem (a local player subsystem, category Rolly Save Core|UI). The top screen has focus; the screens below are hidden, or dimmed behind a dialog. Back (B, Escape) asks the top screen first: a screen can ask before it closes, a dialog answers Cancel.
- Input: when the first screen of any local player opens, the stack records the viewport’s input flags (ignore input, mouse capture and lock) and the cursor. While a player has a menu screen open, that player’s input stops at the screen (keys, sticks and clicks never reach the game), and while every local player has one open the viewport ignores input and frees the mouse. When the last screen closes, input becomes what Input After Screens asks for (by default exactly what was recorded, with focus back on the game), however the screens closed: Back, a node, a map change, Remove All Widgets or the player leaving. Keys held while a screen opens or closes are released for the game, so none stays stuck. The cursor shows while the first player (who owns the mouse) has a screen open that wants it, and hides while that player uses a pad.
- Split screen: each player has a stack in their own part of the screen, and one player’s screen leaves the other players in the game.
- Pausing: screens that ask for it pause a standalone game, through the game mode’s pause with a condition that holds while a screen wants it, so a pause of your game’s own is left alone. A listen server, a client and Play In Editor with players over the network never pause for one player’s screen. Project Settings > Plugins > Rolly Save Core UI > Pausing set to Never turns it off everywhere.
Open screens with the stack, never with Add to Viewport: the stack owns focus, the player’s input, the cursor, the pause and their restore on every close path.
Open a screen of your own
Blueprint
- Make a Widget Blueprint whose parent class is Rolly Save Core UI Screen.
- In its class defaults set Input Mode (Menu or Overlay), Pause Game, Keep Screen Below Visible and Show Mouse Cursor.
- Open it with Push Rolly Screen (from a player controller). Close it with Pop Rolly Screen, Close Rolly Screens or its own Close Screen; Is Rolly Screen Open tells whether one is open.
- Override On Back to refuse or ask first; On Shown, On Covered, On Closed and On Area Changed tell the screen what happens.
A main or pause menu of your own made this way shares the stack with the Rolly screens: its Settings button opens the settings screen of a settings product, and Back comes back to it. Made of the Rolly widgets (the palette’s Rolly Save Core category), it follows the theme too.
Get Rolly Screen Stack gives the player’s stack, with Push Screen, Pop Screen, Replace Top Screen, Close Screen (a screen and the ones above it), Close All Screens, Handle Back (does what Back does), Get Top Screen, Get Screen Count, Is Any Screen Open and the events On Screen Opened, On Screen Closed, On Stack Opened (the first screen opened) and On Stack Closed (the last one closed).
C++
#include "Screens/RollySaveCoreUIScreen.h"
#include "Widgets/RollySaveCoreUIText.h"
#include "MyCreditsScreen.generated.h"
UCLASS()
class UMyCreditsScreen : public URollySaveCoreUIScreen
{
GENERATED_BODY()
protected:
// Runs only when no Blueprint layout replaces the tree.
virtual void BuildDefaultTree() override
{
URollySaveCoreUIText* Title = MakePart<URollySaveCoreUIText>(TEXT("TitleText"));
Title->SetRoles(ERollySaveCoreUITextRole::Display, ERollySaveCoreUIColorRole::Text);
Title->SetText(NSLOCTEXT("MyGame", "CreditsTitle", "Credits"));
WidgetTree->RootWidget = Title;
}
};
// Opening it for a player (#include "Stack/RollySaveCoreUIStackSubsystem.h"):
if (URollySaveCoreUIStackSubsystem* Stack = URollySaveCoreUIStackSubsystem::Get(LocalPlayer))
{
Stack->PushScreen(UMyCreditsScreen::StaticClass());
}Build the default tree in BuildDefaultTree with parts named like the class’s BindWidgetOptional members, so a Blueprint layout can replace it. A screen of categories of rows (a codex, a controls list) derives from URollySaveCoreUICategoryScreen and supplies data only (CollectCategories, BuildRows, CollectDetail, and what Apply, Revert, Reset and Discard do): it gets the five layouts, layout switching at run time, the navigations, the detail forms, the footer, touch and split screen.
Add tabs and prompts to your screens
The tabs row and the footer prompts of the category screens (the settings screen is one) are components you can use in your own screens. Both follow the player’s input device by themselves.
- A Rolly Tab Strip shows tabs between the keys that switch them: Set Tabs with the labels, Set Selected Tab (no event), Select Previous Tab and Select Next Tab (they go around and fire On Tab Selected, as a click on a tab does). It shows the first key of the player’s device from Previous Tab Keys and Next Tab Keys (the shoulder buttons, Q and E, which sit by place on the keyboard layout in use: A and E on AZERTY; no key caps for a touch player); your screen calls Select Previous Tab and Select Next Tab when those keys are pressed.
- A Rolly Prompt Bar shows a prompt per entry of Set Prompts (an Id, a gamepad key, a keyboard key, a label, and whether it is available; an empty label hides the prompt, an unavailable one dims) with the key of the device the player uses, and On Prompt Clicked gives the Id of a prompt the player clicks or taps.
Show dialogs and toasts
- Show Rolly Dialog (a latent node with Confirmed and Cancelled pins) or the stack’s Show Dialog shows a title, a message, a confirm and a cancel button (or only confirm; their texts and looks are yours to set), with the safe answer focused unless you ask otherwise, and an optional countdown that answers by itself in real time with a shrinking bar. Back, and a dialog closed from outside (a map change), answer Cancelled. On a dialog: Answer, Get Seconds Remaining and the event On Dialog Result.
- Show Rolly Toast (a message and a kind: Info, Success or Warning) shows a short message at the top right of the player’s part of the screen that does not take focus or stop the player: newest on top, three at most, for at least the theme’s Toast Seconds (6) and longer for longer text. Toasts keep off an open screen’s header and its card: where one reaches into that corner, they sit at the top centre of the part of the screen beside it (narrower when that part is), or just below the header when nothing beside it is 240 wide.
Ask with panels and dialogs
Three screen classes ask more than Show Rolly Dialog does. They are set up and answer in C++ only (Setup, the name check, OnChosen, OnConfirmed have no Blueprint nodes); a Blueprint game asks with Show Rolly Dialog. Create one with the stack’s CreateScreen, set it up, then open it with PushCreatedScreen. Each is a panel over the screen below, which stays visible and dimmed.
- Panels (
URollySaveCoreUIPanelScreen): derive from it for a panel of your own, with a title and a message (SetTexts) and your parts added inBuildContent; a list added with a filling slot scrolls inside the panel. The panel takes the theme’s Dialog Width (640 units), or 720 for a question with three answers side by side, never wider than the area less 48 units (24 on short narrow areas); on Tiny areas it fills the area less the tiny margins. - Choice dialog (
URollySaveCoreUIChoiceDialog):Setupwith a title, a message and the answers (FRollySaveCoreUIChoice: an Id, a label, a button look and an optional icon), in a row or in a column (a list of actions on a row), the Id that Back answers and the answer focus opens on. Three answers in a row take the wider panel, wider still when their words need it, so they stay on one line.OnChosenfires once with the answer, after the dialog left the stack; a close from outside (a map change) answers the Back answer. - Name dialog (
URollySaveCoreUINameDialog):Setupwith a title, the text it starts with, the confirm button’s words, the longest text in characters (at least 1; an emoji counts as one), a check that returns what is wrong with a text, and where it opens (ERollySaveCoreUINameStart).SetFieldNamenames the field (“Title”).- A keyboard player types into the field with the text selected; a pad or touch player types on the on-screen keyboard, which capitalizes the first letter and each one after a space. In languages typed without keys (Chinese, Japanese, Korean) a pad player sees “Connect a keyboard to type.” instead.
- The check’s message shows under the field as the player types and dims the confirm button; pressing it then plays the Error sound and narration says the message. Brackets, quotes and control characters never type.
- Enter, the keyboard’s Done key (the menu button on a pad) and the confirm button confirm (
OnConfirmedwith the text, trimmed); Escape and B cancel (OnCancelled). - Keyboard opens typing. Confirm opens on the confirm button with the text offered, so Accept keeps it at once; Up goes to the field (a keyboard player types over the text, a pad player’s Accept brings the keyboard), and Back while typing goes back to the confirm button with the text kept.
#include "Screens/RollySaveCoreUINameDialog.h"
#include "Stack/RollySaveCoreUIStackSubsystem.h"
URollySaveCoreUIStackSubsystem* Stack = URollySaveCoreUIStackSubsystem::Get(LocalPlayer);
if (URollySaveCoreUINameDialog* Dialog = Stack != nullptr ? Cast<URollySaveCoreUINameDialog>(Stack->CreateScreen(URollySaveCoreUINameDialog::StaticClass())) : nullptr)
{
Dialog->Setup(NSLOCTEXT("MyGame", "RenameTitle", "Rename Save"), CurrentTitle, NSLOCTEXT("MyGame", "Rename", "Rename"), 32,
[](const FString& Text) { return Text.IsEmpty() ? NSLOCTEXT("MyGame", "TypeTitle", "Type a title.") : FText::GetEmpty(); },
ERollySaveCoreUINameStart::Confirm);
Dialog->OnConfirmed().AddLambda([](const FString& Title) { /* rename the save */ });
Stack->PushCreatedScreen(*Dialog);
}Draw over every player’s view
A widget that belongs to the whole game rather than one player (a saving indicator, a loading overlay) goes on FRollySaveCoreUIViewportLayer: Add(Widget, Offset) shows it over every player’s screens (Offset above Project Settings > Rolly Save Core UI > Viewport Z Order), AddAtZOrder at a Z order of your own, and it stays across map changes until Remove. Add returns false while there is no game viewport yet. A widget that draws itself inside the title-safe area gets the insets every Safe Zone pads by from FRollySaveCoreUISafeArea::GetInsets.
Choose where screens show
With Project Settings > Plugins > Rolly Save Core UI > Screen Layer set to Player (the default), each player’s host (the widget that holds the player’s screens) goes into the player’s part of the viewport, split-screen aware. A HUD your game adds with Add to Viewport draws above it, so pick Viewport (the whole viewport at Viewport Z Order) for a single-player game with such a HUD, or place the screens in a panel of your HUD:
Blueprint
Call Set Host Panel on the player’s stack with an Overlay of your HUD; None goes back to the game viewport. Every Rolly product can share that panel.
C++
if (URollySaveCoreUIStackSubsystem* Stack = URollySaveCoreUIStackSubsystem::Get(LocalPlayer))
{
Stack->SetHostPanel(MyHud->ScreensOverlay); // null goes back to the game viewport
}For a layer system of your own, such as Common UI, see Host screens in Common UI or your own layers.
A screen that must come before everything the game shows (a first-start setup, a question at boot) ticks Show Above Game Widgets in its class defaults. While it is open, the player’s screens sit above every widget the game adds to the viewport, at Project Settings > Plugins > Rolly Save Core UI > Above Game Z Order (10000), still in the player’s part of the screen and with the stack’s focus, input and pause handling; when it closes they go back to the Screen Layer, keeping their state. A host panel of your own (Set Host Panel) decides by itself and ignores it.
Read what the screens do to the game
The game instance’s Rolly Save Core UI Shared Subsystem tells whether screens pause the game (Is Paused By Screens), take every player’s input (Is Game Input Blocked By Screens) or are open at all (Are Rolly Screens Open, which the other Rolly products ask to share the game’s input).