Frontend
The module PulseFrontend is the part of a game around the levels: a title, the main menu, a loading screen between levels and the pause menu. It is off until you turn it on, so games with menus of their own are not touched.
Try it: run the setup step Start the game on a main menu in the Pulse window (Core, Set Up), then play the map /PulseCore/Examples/Frontend/LV_PulseFrontend_Example as Standalone Game. Press a key on the title, pick New Game, and press Escape in the level. In the editor (PIE) Escape ends the session: open the pause menu with the cheat PulseFrontendPause there.
Phases
The frontend follows the game through six phases (EPulseFrontendPhase):
| Phase | When | What shows |
|---|---|---|
Boot | The game started, no world is ready | The start screen of the engine |
Splash | The frontend map began play for the first time and Splash Screens are set | The logos, one after another |
Title | After the splash (first visit only) | The name of the game and “Press any key” |
Menu | After the title, and every time the game comes back to the frontend map | The main menu |
Loading | A level loads | The loading screen |
InGame | Any other level began play | The game; the pause menu opens with Escape |
Get Phase and On Phase Changed of UPulseFrontendSubsystem (game instance) tell where the game is; the message Pulse.Message.Frontend.PhaseChanged does too. A key or a click ends the splash and the title. The splash and the title show only once per run; in the editor the splash is skipped (Skip Splash In Editor).
Main menu and pause menu
Both menus are a UPulseFrontendMenu: the entries of the settings as buttons, a stack for the screens they open, and a question before entries that ask first. The defaults are /PulseCore/Frontend/W_PulseFrontendMainMenu (a column on the left, the frontend map behind it) and W_PulseFrontendPauseMenu (a window in the middle); their look comes from the UI theme of Pulse Foundation.
| Part | Type | What it is |
|---|---|---|
TitleText | Text | The game title (main menu) or “Paused” |
EntryList | Dynamic Entry Box | One UPulseFrontendMenuButton per entry |
EntryPanel | any widget | Hidden while a screen is open |
ScreenStack | Common Activatable Widget Stack | Settings, Credits and the menus of other plugins open here |
StatusText | Text | Why an entry cannot be picked now |
VersionText | Text | The project version (Project Settings > Description) |
ConfirmPanel, ConfirmText, ConfirmYesButton, ConfirmNoButton | The question of an entry |
All parts are optional. Escape, the right face button and the menu button go back one step: the question, the open screen (the settings ask about changes that were not applied), then the pause menu itself. The Blueprint functions Select Entry, Go Back, Push Screen, Answer Confirm and Refresh Entries do the same from your own buttons. Add > Pulse > Core > Frontend Menu starts a menu of your own look from the default main menu.
The pause menu opens with the input action IA_PulsePause (Escape and the menu button of a gamepad, mapping context IMC_PulseFrontend) in the phase InGame, on the HUD stack Pause Menu Stack (without the Pulse HUD in the viewport). It pauses the game only when nobody else plays (standalone); in a multiplayer game it is only a menu. While it is open the HUD hides its gameplay part.
Entries
The entries of both menus are lists in the settings (Main Menu Entries, Pause Menu Entries). Each has an Id, a Text, an Order (lowest first), Enabled, an optional Confirm Question and an Action:
| Action | What it does |
|---|---|
| Open Level | Opens a level with the loading screen; Options are URL options such as listen |
| Open Widget | Opens a screen in the stack of the menu |
| Console Command | Runs a command as the player |
| Settings | The settings screen of Pulse Core |
| Credits | The credits screen with the lines of Credits |
| Resume | Closes the pause menu (only shows there) |
| Return To Main Menu | Goes back to the frontend map (only shows with one); a client leaves the server |
| Quit | Quits the game |
| Message | Nothing itself: Blueprint reacts to Pulse.Message.Frontend.EntrySelected with the entry id |
Defaults: the main menu has New Game (the example level of Pulse Core until you set your own), Settings, Credits and Quit; the pause menu has Resume, Settings, Main Menu and Quit. An entry that cannot run now (a level that does not exist) shows disabled with the reason as tooltip.
Entries from bridges: a bridge adds its entries in StartupModule, so they show without setup. An entry the project changed stays as it is; to hide an entry of a bridge, turn Enabled off (a removed entry comes back).
// In the StartupModule of a bridge (example: a Load entry that opens a menu of the bridge)
FPulseFrontendAction_OpenWidget load;
load.WidgetClass = TSoftClassPtr<UCommonActivatableWidget>(FSoftClassPath(TEXT("/MyBridge/W_LoadMenu.W_LoadMenu_C")));
UPulseFrontendSettings::AddDefaultEntry(EPulseFrontendMenu::Main,
Pulse::Frontend::MakeEntry(TEXT("Load"), NSLOCTEXT("MyBridge", "Load", "Load"), 200, load));
Actions of your own derive from FPulseFrontendAction in C++ (Execute, IsAvailable with a reason, IsVisible).
Loading screen
OpenLevel (the Open Level action, Return To Main Menu) loads the level in the background first, so the loading screen shows real progress, and travels when it is in memory. Loads the frontend did not start (a server travel, a client joining a server, seamless travel) show the screen too; their progress is unknown until the level arrives, so the screen shows a throbber. The screen stays until the level began play, Minimum Loading Time passed, every hold was removed and, with Wait For Streaming, world partition streamed the cells around the players. After Maximum Loading Time it closes anyway and logs what it waited for.
Holds keep the screen up for work after the level began play, e.g. loading a save game or preparing shaders. The screen waits for every loading hold of Pulse Foundation (UPulseLoadingHoldSubsystem: Add Loading Hold with a reason, a text and a priority, Set Loading Hold Progress, Remove Loading Hold), so plugins hold it without depending on the frontend. While holds report progress, the last part of the bar follows them (the slower of them and the Minimum Loading Time); the status line shows the text of the most important hold, else “Loading”. Add Loading Hold (By Name) and Remove Loading Hold (By Name) of the frontend subsystem are a shortcut for a hold without text or progress.
UPulseLoadingHoldSubsystem* holds = UPulseLoadingHoldSubsystem::Get(this);
const FPulseHandle hold = holds->AddHold(TEXT("Save"), LOCTEXT("LoadingSave", "Loading the save"));
holds->SetProgress(hold, 0.5f);
holds->RemoveHold(hold);
The default W_PulseFrontendLoadingScreen is a UPulseFrontendLoadingScreen with TitleText, TipText, StatusText, ProgressBar and Throbber; Set Loading Progress, Set Tip and Set Status can be overridden in Blueprint. Tips are picked at random from Loading Tips and change after Tip Interval. The screen lives in the viewport, not in a world, so it stays while the level changes.
A project with a loading screen of its own (CommonLoadingScreen, a movie player screen) clears Loading Screen Class: the frontend still has its loading phase, the other screen draws.
The frontend map
The main menu needs a map: Frontend Map in the settings, which should also be the Game Default Map (Project Settings > Maps & Modes) so the game starts there. The setup step sets both. Give the map the game mode APulseFrontendGameMode (world settings, Game Mode Override): players get no pawn, the camera is a camera actor of the level with Auto Activate For Player set to Player 0. The example map is built that way; duplicate it for your own.
Menus of other plugins
UPulseFrontendPresenter is a presenter of Pulse Foundation (see “Where menus of plugins show” in its UI docs): it opens the menus of other plugins, for example the save and load menus of Pulse Save, in the screen stack of the open main or pause menu, else on a HUD stack, else in the viewport. Name it as Presenter Class in the settings of that plugin.
Settings
Project Settings > Pulse > Core > Frontend (UPulseFrontendSettings, DefaultGame.ini):
| Setting | Default | Description |
|---|---|---|
bEnableFrontend | false | Turns the frontend on |
FrontendMap | none | The map of the main menu |
GameTitle | empty | Title on the title screen and the main menu; empty: the project name |
MainMenuEntries, PauseMenuEntries | see above | Entries of the menus |
MainMenuClass, PauseMenuClass | W_PulseFrontendMainMenu, W_PulseFrontendPauseMenu | The menus |
PauseMenuStack | Pulse.HUD.Stack.Main | HUD stack of the pause menu |
CreditsScreenClass | W_PulseFrontendCredits | The credits screen |
Credits | one line | Lines of the credits |
bPauseInSinglePlayer | true | The pause menu pauses a standalone game |
PauseInputAction, PauseMappingContext | IA_PulsePause, IMC_PulseFrontend | Input of the pause menu |
PauseMappingPriority | 0 | Priority of the mapping context |
LoadingScreenClass | W_PulseFrontendLoadingScreen | The loading screen; empty for none |
LoadingTips | two tips | Tips of the loading screen |
TipInterval | 8 | Seconds until the next tip |
MinimumLoadingTime | 1 | Seconds the loading screen stays at least |
MaximumLoadingTime | 60 | Seconds after which it closes anyway |
bWaitForStreaming | true | Wait for world partition streaming |
LoadingScreenZOrder | 10000 | Viewport order of the loading screen |
SplashScreens | none | Logos before the title (image, seconds, background color) |
SplashScreenClass, TitleScreenClass | W_PulseFrontendSplashScreen, W_PulseFrontendTitleScreen | Start screens; no title class goes straight to the menu |
bSkipSplashInEditor | true | No logos when playing in the editor |
Debugging
Cheats PulseFrontendPhase, PulseFrontendPause, PulseFrontendEntry <id>, PulseFrontendBack, PulseFrontendLoading [seconds] and PulseFrontendMainMenu (Console); the snapshot category Frontend (phase, open menu and screen, loading state, holds) on the Live page of the Pulse Debugger; log category LogPulseFrontend.