Key icons and letting players rebind keys¶
No prompt in this template picks its own texture. A widget hands over an Input Action, the template looks up which key is bound to that action right now, and draws the matching picture. Change the key in IMC_Default, or let the player change it in the options menu, and every prompt on screen follows without you touching a widget.
Three assets do the whole job:
Content/TheLastTemplate/Blueprints/Functions/BFL_InputLibrary, which turns an Input Action into a key and a picture.Content/TheLastTemplate/Blueprints/DataAssets/Widgets/KeyPrompts/Childs/DA_KeyPrompts, the list that says which picture belongs to which key.Content/TheLastTemplate/Textures/Widgets/KeyPrompts/x80/, the pictures themselves.
If you have not read Change the controls yet, read it first. It covers IMC_Default and the actions that ship.
Inside DA_KeyPrompts¶
DA_KeyPrompts is a BP_KeyPromptSetDataAsset. It holds three arrays that are read at the same index.
| Field | What it holds |
|---|---|
Key List |
The key itself, as Unreal names it: E, LeftShift, SpaceBar, RightMouseButton, MouseWheelAxis |
Icon List |
The picture drawn for that key |
Name List |
The short text label for that key |
The set covers keyboard and mouse. Every picture in x80 is 80 pixels tall and between 80 and 220 pixels wide, because a key like SPACE needs more room than E. That is why a prompt has to keep the ratio when it builds its brush, instead of dropping the texture into a square box.
A number of pictures ship without a row in DA_KeyPrompts, among them T_Key_0 to T_Key_9, T_Key_At, T_Key_Question, T_Key_Euro and T_Mouse_Any. They are there for you to use.
Add a picture for a key that has none¶
- Put your texture in
Content/TheLastTemplate/Textures/Widgets/KeyPrompts/x80/. Keep the height at 80 and let the width grow with the label. - Open
DA_KeyPrompts. - Add one entry to
Key Listand pick the key. - Add one entry to
Icon Listand one toName List, at the same index. - Save.
The three arrays are read by index, so they must always have the same length and the same order. Add to one and forget the others and every key after that point draws the wrong picture, with no warning.
Ask for a prompt from your own Blueprint¶
BFL_InputLibrary has two functions. Both are Blueprint function library calls, so they work from any widget, actor or component.
| Function | In | Out |
|---|---|---|
Get Action Input Informations |
Action, World Context, Prompt Set |
Key, Icon, Display Name, Found |
Get Key Prompt Infos |
In Key, Prompt Set |
Icon, Display Name, Found |
Use the first one in almost every case: it reads the binding that is live for the player. Use the second only when you already hold a key and just want its picture.
To show a prompt in a widget of your own:
- Add a variable of type
BP_KeyPromptSetDataAsset, name itPrompt Set, and set its default toDA_KeyPromptsin the Details panel. - Add a variable of type
Input Actionfor the action you want to draw. - Call
Get Action Input Informations, feeding it that action,selfas the world context, and yourPrompt Set. - Branch on
Found. When it is false the action has no key at all, so hide the image and leave the text alone. - Build the brush from
Iconwith a width ofSizeX * Height / SizeY, so the picture keeps its shape.
Neither the action nor the prompt set is written into the graph as a path. They are variables you fill in the Details panel, which also means a widget you build yourself shows nothing until you fill them.
Three widgets already do this and are worth opening as examples: BP_TipWidget and its Set Tip function, BP_FinishWidget with its Finisher Action and its Refresh Key Icon, and BP_ShowcasePanelWidget.
BP_FinishWidget resolves its picture when the widget is built. If the player rebinds mid game the prompt keeps the old picture until something calls Refresh Key Icon again, which is why that function is public.
Tip
You do not need a Blueprint at all for a simple on screen hint. Drop a BP_TipZone in the level, set Tip Action and Tip Message, and the message appears with the right key picture while the player stands inside the box.
The Controls page in the options menu¶
The options menu already has a Controls page, and it really rebinds: the new key goes through Enhanced Input's player mappings and is written to SG_MenuSettings under Key Binds, so it survives a restart.
The page is a Data Asset, Content/TheLastTemplate/Blueprints/DataAssets/Widgets/Menu/Childs/DA_Page_Controls. Its Rows array holds two heading rows and seventeen rebindable ones. Each rebindable row uses these fields of S_SettingRow:
| Field | What it does |
|---|---|
ID |
The name of the mapping in IMC_Default. This is the only link between the row and the key |
Row Widget Class |
BP_MenuRowKeyBindWidget for a rebindable line, BP_MenuRowSectionWidget for a heading |
Label Key |
Text key for the action name, for example ctrl.act.moveforward |
Desc Key |
Text key for the help line. Every shipped row uses ctrl.act.desc |
Options Keys |
The default key, written as its Unreal key name: Z, LeftShift, SpaceBar, RightMouseButton |
Icon |
The picture that goes with that default key |
Label Key and Desc Key are text keys, not text. See Translate the game into another language.
Warning
ID must match, letter for letter, the Name inside the Player Mappable Key Settings of the matching row in IMC_Default. If it does not, the line still appears in the menu and the player can still press a key, and nothing at all gets rebound.
Two shipped rows are in exactly that state: ChangeLocomotion and ShoulderSwap have no mapping of that name in IMC_Default. They draw, they do not rebind. Give them a mapping name or delete the rows.
Add your own action to the Controls page¶
Say you added IA_Whistle and want the player to be able to move it.
- Open
Content/TheLastTemplate/Inputs/IMC_Defaultand find the mapping row forIA_Whistle. - Set its
Setting Behaviorso the row carries its ownPlayer Mappable Key Settings, then fill inName,Display NameandDisplay Category. - Open
DA_Page_Controlsand add a row toRows. - Set
Row Widget ClasstoBP_MenuRowKeyBindWidget. - Set
IDto the sameNameyou typed in step 2. - Set
Label KeyandDesc Keyto your text keys. - Set
Options Keysto the default key name andIconto its picture fromx80. - Save both assets.
Nothing else. You do not open a widget, and you do not touch the menu screens. Adding or reordering pages is covered in Add or change a menu page.
What the player sees while the game waits for a key¶
Activating a row opens BP_MenuRebindWidget over the page. It takes the keyboard focus and the next key pressed becomes the new binding. Its prompt bar shows Escape to back out without changing anything.
The small key chips in that bar, and in every menu footer, are BP_MenuKeyPromptWidget inside a BP_MenuPromptBarWidget. They are the same pictures from x80, so a menu prompt and an in game prompt always look alike.
Keyboard and mouse only¶
DA_KeyPrompts has no gamepad entries, and there are no gamepad pictures in x80. Because of that, Get Action Input Informations deliberately skips a pad: when an action has more than one key bound and the first one is a gamepad key, it takes the second. A pad binding therefore never blanks out the prompt for a keyboard player.
If you want pad prompts:
- Draw the pad pictures and import them the same way, one height, variable width.
- Make a second
BP_KeyPromptSetDataAssetnext toDA_KeyPromptsand fill its three arrays with pad keys. - Point each widget's
Prompt Setat the set that matches the device in use. - Change the key choice inside
Get Action Input Informations, which today always prefers the key that is not on a pad.
The Controls page is keyboard and mouse too. It rebinds the mapping name, so a pad binding on the same action is not shown and not touched.