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).

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.

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.


PulseCore plugin documentation.

This site uses Just the Docs, a documentation theme for Jekyll.