Add or change a menu page¶
Every menu screen in the template is drawn from a Data Asset. The asset lists the rows of the page, and each row says which widget draws it and what its numbers are. Adding an option, a button, or a whole page is filling in an array. Only one case needs a graph edit, and it is called out below.
- The page class:
Content/TheLastTemplate/Blueprints/DataAssets/Widgets/Menu/BP_SettingsPageDataAsset - The pages that ship:
Content/TheLastTemplate/Blueprints/DataAssets/Widgets/Menu/Childs/ - The row widgets:
Content/TheLastTemplate/Blueprints/Widgets/Menu/Common/ - The screens that read them:
Content/TheLastTemplate/Blueprints/Widgets/Menu/Screens/ - The row struct:
Content/TheLastTemplate/Blueprints/Structures/Widgets/S_SettingRow
The pages that ship¶
| Page | Screen that reads it | What it holds |
|---|---|---|
DA_Page_MainMenu |
BP_MainMenuWidget |
Continue, New Game, Load Game, Options, Quit |
DA_Page_Pause |
BP_PauseMenuWidget |
Continue, Options, Save Game, Photo Mode, Quit to Main Menu |
DA_Page_Options |
BP_MenuOptionsRootWidget |
the list of the five option pages |
DA_Page_Audio |
BP_MenuSettingsPageWidget |
six volume sliders under one heading |
DA_Page_Graphics |
BP_MenuSettingsPageWidget |
ten quality selectors and a resolution scale slider |
DA_Page_Display |
BP_MenuSettingsPageWidget |
resolution, window mode, VSync, frame limit, HDR, brightness, calibrate |
DA_Page_Controls |
BP_MenuSettingsPageWidget |
the rebindable actions |
DA_Page_Language |
BP_MenuSettingsPageWidget |
one language selector |
DA_Page_Brightness |
BP_MenuBrightnessWidget |
the brightness slider and the HDR toggle of the calibration screen |
A page asset has three fields.
| Field | What it does |
|---|---|
Title Key |
The title drawn at the top of the screen. |
Rows |
The rows, in the order they appear. |
Build From Input |
Ticked on DA_Page_Controls only. The page then fills its key bind rows from the player's Enhanced Input mappings instead of taking the key from the array. |
The eight row widgets¶
Row Widget Class is the row type. There is no enum to pick from, you pick a widget class.
| Class | What the player sees |
|---|---|
BP_MenuItemWidget |
A plain button. Used by the main menu, the pause menu and the options list. |
BP_MenuRowSectionWidget |
A heading. It cannot be selected and is skipped when navigating. |
BP_MenuRowSliderWidget |
A slider with a number. |
BP_MenuRowSelectorWidget |
Left and right arrows over a fixed list of choices. |
BP_MenuRowToggleWidget |
An on and off switch. |
BP_MenuRowResolutionWidget |
Arrows over the resolutions the machine reports. The list comes from the engine, not from the row. |
BP_MenuRowKeyBindWidget |
A key icon the player can click to rebind. |
BP_MenuRowActionWidget |
A line with a chevron that opens another screen. |
The fields of one row¶
| Field | What it does |
|---|---|
ID |
The name the value is stored under, and what a screen matches on to know which row was pressed. |
Row Widget Class |
The widget that draws the row. |
Label Key |
The text of the row. Every shipped row uses the same string as ID. |
Desc Key |
The help line shown while the row is selected. None on headings. |
Min Value, Max Value |
The range of a slider. On a selector these are the first and last index, not values. |
Step Value |
How far one step moves. 5 on the volume sliders, 1 on every selector. |
Default Value |
The value used when the setting has never been set. |
Options Keys |
The list a selector walks through, for example q.low, q.medium, q.high, q.epic. |
Icon |
A key icon. Only the controls page fills it. |
Input Action |
Present on the struct. No shipped row sets it. |
Requires Restart |
Present on the struct. No shipped row sets it. |
Label Key and Desc Key are written as dotted keys so a localisation pass can pick them up later. See Translate the game into another language.
Add an option to a page that already exists¶
- Open the page, for example
DA_Page_Audio. - Add an entry to
Rows. - Set
Row Widget Classto the row type you want. - Type an
ID. Copy it intoLabel Key, and put<your id>.descinDesc Key. - Fill
Min Value,Max Value,Step ValueandDefault Value, orOptions Keysfor a selector. - Save and play. The row is there, the player can change it, and the value is written to the settings file.
Warning
A new ID is stored and reloaded on its own, but nothing acts on it. SG_MenuSettings is what turns an id into an engine call, in Apply Audio, Apply Graphics and Apply Display. Until you add your id to one of those, or read it yourself, the option moves and does nothing.
Make your new option do something¶
- Open
Content/TheLastTemplate/Blueprints/Misc/SG_MenuSettings. - Open
Apply Audio,Apply GraphicsorApply Display, whichever fits. - Add a branch for your id and do the work there.
Anywhere else in your game, call Get Value on SG_MenuSettings with your id to read the current setting.
Add a whole options page¶
- Duplicate
DA_Page_Audiointo the same folder and name it, for example,DA_Page_Gameplay. - Set
Title Keyand replace the rows with your own. - Open
DA_Page_Optionsand add a row:Row Widget ClassisBP_MenuItemWidget,IDisopt.gameplay,Label Keythe same,Desc Keyisopt.gameplay.desc. - Open
BP_MenuOptionsRootWidgetand find theSwitch on Stringthat turns a rowIDinto a page Data Asset. Add a pin namedopt.gameplayand plug your new asset into it. - Save both assets and play.
Step 4 is the only graph edit in the whole job. Skip it and the entry appears in the list but opens nothing.
Change the main menu and the pause menu buttons¶
Both are ordinary pages. Reordering, renaming or removing a button is done in DA_Page_MainMenu and DA_Page_Pause and nowhere else.
A button that does something new needs a target. The screen widget matches the row ID and calls the matching function:
BP_MainMenuWidget:Start New Game,Continue Game,Open Load Game,Open Options,Confirm Quit.BP_PauseMenuWidget:Resume Game,Save Game Now,Open Photo Mode,Quit to Main Menu.
BP_MainMenuWidget also has Refresh Locks, which locks rows the player cannot use through Lock Row on BP_MenuRowBaseWidget. That is where Continue and Load Game are disabled when there is no save.
Where a setting is stored, and when it is applied¶
Settings live in SG_MenuSettings, written to the save slot TLT_MenuSettings.
| Variable | Holds |
|---|---|
Values |
id to number, for every slider, selector and toggle |
Text Values |
id to text |
Key Binds |
the keys the player rebound |
Pending Changes |
what has been changed but not written yet |
Set Value writes, Get Value reads. On the settings screen, Apply Now pushes the page to the engine and Apply and Save also writes the file. Save Now writes the file on its own. While a page has unapplied changes the prompt bar grows an apply and a reset entry, and leaving the page opens a confirm pop up instead of going back.
The save files for a run are a different subject. See Save and load a game.
The prompt bar and the two pop ups¶
BP_MenuPromptBarWidget is the strip of key icons at the bottom of every menu screen. Screens fill it in their own Setup Prompts, with Clear Prompts then one Add Prompt per entry.
Warning
A prompt's label is also its click identifier. Two prompts with the same label on the same bar cannot be told apart, and the click goes to the wrong one.
Two pop ups are shared by every screen:
BP_MenuModalConfirmWidget, a yes and no question. Which question it asks comes fromE_MenuConfirmAction:QuitGame,DeleteSave,NewGame,ResetSettings,DiscardSettings,QuitToMainMenu. Add a value there to add a confirmation of your own.BP_MenuModalInfoWidget, one message and one OK.
The brightness calibration screen¶
BP_MenuBrightnessWidget is its own screen, not a settings page, but it builds its two rows from DA_Page_Brightness like everything else. It shows the three calibration plates T_UI_Cal_Shadows, T_UI_Cal_Midtones and T_UI_Cal_Brights while the player drags the slider.
It is reached from the display.calibrate row of DA_Page_Display, which is a BP_MenuRowActionWidget. If you want an action row that opens a screen of your own, that widget is where the screen to create is chosen.
Open your own level with the loading screen¶
Content/TheLastTemplate/Blueprints/Functions/BFL_LoadingLibrary has the two nodes you need:
Open Level with Loading Screen, which takes aLevel Name, puts upBP_LoadingScreenWidgetand opens the level behind it.Show Loading Screen Until Ready, which puts the screen up without changing level.
Two places name a level today:
BP_BootGameModehas aMenu Level Namevariable, set toL_MainMenu. That is where the game goes on boot.BP_MainMenuWidgetpasses a level name toLaunch Slot. That is the level the main menu starts. Change it to your own map and the whole main menu follows.
Write your own row type¶
- Right click
BP_MenuRowBaseWidgetand create a child widget Blueprint. - Build the visual in the designer.
- Override the ones you need:
Setup,Refresh Visual,Get Label,Get Description,Is Selectable,Accept,Navigate Left,Navigate Right,Commit Value. - Put your class in
Row Widget Classon a row.
Nothing else has to change. The page builds whatever class the row names.