Rolly Docs

Rolly Settings

Game settings from a data asset: you list the settings, and Rolly Settings keeps their values, applies them, asks the player to confirm risky changes, reverts them, saves them, lets players rebind their keys and gives every split-screen player their own, without C++. A ready settings screen comes with it, built in code on the Rolly UI design system and restyled with one theme asset; open it from any menu of yours.

Version
0.1.0 beta
Engine
UE 5.8+
Platforms
Windows, macOS, Linux, Linux Arm64, Android, iOS
Multiplayer
Settings are local to each machine and player; nothing replicates
Dependencies
Engine modules and the Enhanced Input engine plugin (listed below)
Modules
  • RollySettings Runtime
  • RollySettingsUI ClientOnly
  • RollySettingsEditor Editor
  • RollySettingsCore Runtime
  • RollySettingsCoreUI ClientOnly
  • RollySettingsCoreEditor Editor
On this sheet

State of this version (0.1.0, in development): the settings model, the runtime, saving, the Blueprint API, the console commands, the built-in library (display, graphics, picture, audio, controls, accessibility and an example gameplay setting), the controls (key rebinding through Enhanced Input, sensitivity and invert modifiers, button prompt queries), the settings screen on the Rolly UI design system (five layouts: Tabs, Side Rail, Centered Panel, Couch Hub and Side Drawer; six theme presets; its dialogs, toasts and key capture) and the editor asset tools are in place. The live theme preview in the editor, preset thumbnails, Create Theme from Preset and one theme shared by several Rolly products come next.

Quick start (about 10 minutes)

  1. Enable the plugin (Edit > Plugins > search “Rolly Settings”) and restart the editor.
  2. Create a collection: right-click in the Content Browser > Rolly > Rolly Settings Collection for an empty one, or Tools > Rolly > Create Settings Collection from Defaults… for one that already holds every built-in setting, ready to edit.
  3. Open it, add a category (give it a Display Name, for example “Gameplay”), and add settings to it. For each setting pick a kind (Toggle, Choice, Slider, Key Binding, Key Mappings or Action), then fill in:
    • Tag: a Gameplay Tag that identifies the setting (add your own in Project Settings > Gameplay Tags, for example MyGame.Settings.HeadBob);
    • Display Name and Description: what the player reads;
    • Scope: Shared (one value for the machine) or Per Player (each split-screen player has their own);
    • Apply Mode: Immediate, On Apply or Requires Restart;
    • Binding: leave it empty (or pick Stored Only) to only keep the value, pick a built-in binding (Window Mode, Scalability Group, Sound Class Volume and the others listed under Bindings) to drive an engine value, or pick a Blueprint binding you wrote (a child class of Rolly Setting Custom Binding) to make the value do something in your game.
  4. Save the asset. If something is wrong, the Message Log says what and how to fix it (right-click the asset > Asset Actions > Validate Assets runs the same checks).
  5. Open Project Settings > Plugins > Rolly Settings and assign the collection.
  6. In a widget or a player controller Blueprint: Get Rolly Settings Subsystem, then Get Float Value / Set Float Value (or Bool, Option, or the text form with Get Setting Value / Set Setting Value), Apply Settings, and bind On Setting Changed to react to changes.
  7. Press Play. Type rolly.settings.dump in the console to see every setting with its value.

Without a collection in Project Settings, the built-in library is used, so the subsystem always has settings. For key rebinding and the look sensitivity and invert settings, also follow the setup under Controls.

The settings screen, in two more minutes:

  1. Call Open Rolly Settings (category Rolly|Settings|Screen) with the player controller: from the Settings button of your own menu, or from an input action in your player controller Blueprint. The screen opens on the player’s Rolly screen stack, which takes the player’s keys, shows the cursor and pauses a standalone game while the screen is open. Back (B, Escape) or the gamepad’s menu button closes it, and asks first when changes wait for Apply.
  2. Press Play. Everything works with a gamepad, a keyboard or a mouse, and follows the player’s device. See The settings screen for the details.
  3. Pick a layout in Project Settings > Plugins > Rolly Settings Core UI > Layout: Tabs (the default), Rail, Panel, Hub or Drawer (see Choosing a layout).
  4. For a look of your own, create a Rolly Settings Core UI Theme data asset (it starts as a copy of Ember) and pick it in Project Settings > Plugins > Rolly Settings Core UI > Theme (see Themes).

Rolly Settings brings the settings screen, not a menu system: open it from your own main and pause menus, made with UMG, Common UI or anything else. Menus made as Rolly screens share the player’s screen stack with it (see The screen stack).

Concepts

  • Collection: a data asset with categories of settings. It is only a definition: while the game runs it is never written to; the values live in the subsystems. A running session keeps the settings it started with, so rows you add, remove or replace during Play In Editor take effect at the next Play.
  • Setting kinds: Toggle, Choice, Slider, Key Binding, Key Mappings (the player’s whole key list) and Action (a button). Each kind has its own properties and text form (below).
  • Binding: where a value goes when it takes effect, and where it comes from. One class per target: the built-in ones drive engine values (window, graphics, audio), your own drive your game. Every call receives the player it works for.
  • Scope: Shared values belong to the machine and are applied once, whatever the number of local players. Per Player values belong to one local player.
  • Apply Mode: Immediate values take effect and are kept as soon as they change. On Apply values wait for Apply. Requires Restart values are saved on Apply and take effect at the next start (also when the binding saves the value itself, see Values and flows).
  • Confirmation: an On Apply setting with Needs Confirmation is applied but not kept until the player confirms. Without an answer it goes back after the timeout (real time, so it keeps counting while the game is paused).
  • Conditions: Visible When hides a setting and Enabled When disables it while another setting’s value does not match. Platforms limits a setting to some platforms. A binding can also report that a feature is missing (no HDR display, a single monitor), which hides the setting.
  • Per-platform defaults: Platform Defaults gives a setting another default on some platforms.

Structure

Module Loads in What it holds
RollySettings Games, servers and the editor The settings model and flows, the subsystems and their Blueprint API, the bindings, saving, the built-in library, the controls
RollySettingsUI Games and the editor, never a dedicated server The settings screen with its rows, dialogs and key capture, and the Open and Close Settings API
RollySettingsEditor The editor Asset tools, the checks on save, the cook hook, the Play In Editor restore and the automated tests
RollySettingsCore Games, servers and the editor The shared foundation: setup reports, validation, and the input device tracker behind the button prompts
RollySettingsCoreUI Games and the editor, never a dedicated server The Rolly UI design system: the theme and its presets, the widgets every Rolly screen is made of, the five layout templates, the per-player screen stack, dialogs and toasts (see Themes and The screen stack)
RollySettingsCoreEditor The editor The Message Log listing, the design system’s cook hook, its test support and its tests

The last three are the shared Rolly foundation, carried inside this plugin under this product’s name, so several Rolly products in one project never clash. How the code is organised (the folders of each module, the path of a value from the collection to the engine and the screen, the extension points and where the tests live) is in Docs/ARCHITECTURE.md.

Built-in library

The built-in library is built in code, so it needs no content. The game uses it when Project Settings name no collection, and Tools > Rolly > Create Settings Collection from Defaults… copies it into a new asset for you to edit: reorder, remove, rename, change defaults, add your own settings. Tags start with Rolly.Settings.; the table leaves that part out.

“Engine” in the Saved column means the engine saves the value in GameUserSettings.ini; “Rolly” means RollySettings.ini (see Saving). Every engine-backed setting is Shared, because the engine holds one value for the whole game. Settings marked * need confirmation after Apply.

Category Setting (tag) Kind and apply mode Saved Shown
Display Window Mode* (Display.WindowMode) Choice: Windowed, Windowed Fullscreen, Fullscreen (where exclusive fullscreen works); On Apply Engine Where the game has a window of its own (not on phones)
Resolution* (Display.Resolution) Choice for the window mode and monitor the player has chosen, before Apply too: in Fullscreen the sizes that monitor supports, otherwise common sizes that fit it, always with its native size; On Apply Engine Not in Windowed Fullscreen, which always fills the monitor
Monitor* (Display.Monitor) Choice of the connected monitors, named as the system names them; On Apply Engine Two or more monitors
VSync (Display.VSync) Toggle; On Apply Engine Unless the project fixes r.VSync in [SystemSettings]
Frame Rate Limit (Display.FrameRateLimit) Choice: Unlimited, 30, 60, 90, 120, 144, 165, 240; On Apply Engine Desktop platforms
Resolution Scale (Display.ResolutionScale) Choice of the engine’s resolution presets (Default, Performance, Balanced, Quality, Native, or the project’s own), Custom while the value matches none; On Apply Engine Always
HDR (Display.HDR) Toggle; On Apply Engine The project allows HDR output and a display supports it
HDR Brightness (Display.HDRBrightness) Slider, 80 to 400 nits of paper white (203 is the reference); On Apply Engine While HDR is on
Graphics Overall Quality (Graphics.OverallQuality) Choice: Low, Medium, High, Epic, Cinematic, and Custom while the groups below differ; On Apply Engine Always
View Distance, Anti-Aliasing Quality, Shadows, Global Illumination, Reflections, Post Processing, Textures, Effects, Foliage, Shading, Landscape (Graphics.ViewDistance, .AntiAliasingQuality, .Shadows, .GlobalIllumination, .Reflections, .PostProcessing, .Textures, .Effects, .Foliage, .Shading, .Landscape) Choice per scalability group, as many levels as the group has; On Apply Engine Always
Anti-Aliasing Method (Graphics.AntiAliasingMethod) Choice: Default, Off, FXAA, TAA, TSR (where supported), SMAA, MSAA (only with the forward renderer on desktop); On Apply Rolly Always
Auto-Detect (Graphics.AutoDetect) Action: runs the hardware test and proposes graphics values (see Values and flows) Where the game renders
Picture Brightness (Picture.Brightness) Slider, 70 % to 150 % of the project’s display gamma; Immediate Rolly While HDR is off
Audio Master Volume (Audio.Master) Slider 0 to 100 %: the volume of everything the game plays; Immediate Rolly Always
Music, Effects, Voice Volume (Audio.Music, .Effects, .Voice) Slider 0 to 100 % for the engine’s Music, SFX and Voice sound classes; Immediate Rolly When the sound class loads
Controls Key Bindings (Controls.KeyMappings) Key Mappings: one row per player-mappable action of your mapping contexts, with a keyboard and mouse column and a gamepad column (see Controls); Per Player, Immediate Enhanced Input’s key file While Enhanced Input’s user settings are on (the default)
Mouse Sensitivity, Gamepad Sensitivity (Controls.MouseSensitivity, .GamepadSensitivity) Slider 10 % to 500 % (a multiplier, 1 is 100 %) on a logarithmic track, so 100 % sits near the middle; for the Rolly Settings Sensitivity modifier in your look mappings; Per Player, Immediate Rolly Always
Invert Vertical Look (Controls.InvertLookY) Toggle for the Rolly Settings Invert modifier in your look action; Per Player, Immediate Rolly Always
Controller Prompts (Controls.ControllerPrompts) Choice: Auto, Xbox, PlayStation, Nintendo, Generic; which gamepad buttons your prompts show (Auto follows the gamepad in use); Per Player, Immediate Rolly Always
Accessibility Subtitles (Accessibility.Subtitles) Toggle for the engine’s subtitles; Immediate Rolly Unless the project forces subtitles off
Subtitle Size (Accessibility.SubtitleSize) Choice: Small, Medium, Large, Extra Large; Per Player, stored only, for your own subtitle display to read Rolly Always
Colour Vision Deficiency (Accessibility.ColorVisionDeficiency) Choice: Off, Deuteranopia, Protanopia, Tritanopia; corrects the colours of the whole picture; Immediate Rolly Not on iOS and Android
Correction Strength (Accessibility.ColorVisionSeverity) Slider 0 to 100 %; Immediate Rolly While a deficiency is chosen
Interface Size (Accessibility.UIScale) Slider, 75 % to 200 % of the project’s application scale; On Apply Rolly Always
High Contrast Interface (Accessibility.HighContrast) Toggle: every Rolly screen in its theme’s High Contrast Colours, with outlined panels and a 3-unit focus ring; Immediate; it sets the shared rolly.ui.contrast, so every installed Rolly product follows it. On a first start it follows the system’s high contrast mode (Windows) Rolly Always
Reduce Motion (Accessibility.ReduceMotion) Toggle: Rolly screens stop sliding, growing and scrolling smoothly, and fades last 100 ms or less; Immediate; it sets the shared rolly.ui.motion (0 on, 1 off), so every installed Rolly product follows it. On a first start it follows the system’s request for fewer animations (Windows: Show animations off) Rolly Always
Gameplay Field of View (Gameplay.FieldOfView) Slider 60 to 120 degrees; Per Player, stored only: an example of a value your camera reads with Get Float Value Rolly Always

Category tags: Rolly.Settings.Category.Display, .Graphics, .Picture, .Audio, .Controls, .Accessibility, .Gameplay. Every built-in category has its icon (see Categories and pictures). The sensitivity and invert settings only hold values: they change the game once the modifiers are in your mapping contexts (see Controls).

Defaults. The setting’s own default wins; a binding only supplies one that cannot be known in advance: Resolution defaults to the monitor’s native size, Monitor to the primary monitor. The built-in library takes its defaults from the project’s own configuration, so using it never changes how a project looks: Window Mode from the engine’s default window mode, the quality levels at the engine default (Epic), Brightness from the engine’s Display Gamma, Subtitles from the engine’s Subtitles Enabled, Interface Size from Project Settings > User Interface > Application Scale. Anti-Aliasing Method and Resolution Scale default to Default, which removes the player’s choice so the project’s own setting applies. A collection created from the defaults holds those values; change them there. With the built-in library a Reset gives these defaults, which can differ from what the project’s own configuration started the player with: Windowed Fullscreen and Epic quality where the project’s DefaultGameUserSettings.ini starts players in Fullscreen at High quality.

Setting kinds

Kind Text form of its value Main properties
Toggle true or false (also accepts 1, 0, any letter case) Default Value
Choice the chosen option’s Id Options (Id + Display Name), Default Option (empty: first option), Options From Binding
Slider a number with a dot, no grouping (0.5, 90) Min Value, Max Value, Step (0: smooth), Default Value, Display Format ({Value} %), Display Multiplier, Logarithmic Scale
Key Binding the key’s name (SpaceBar, Gamepad_FaceButton_Bottom), empty for no key Default Key. Without a binding it only stores a key; with the Enhanced Input Key binding it is one key of the player’s Enhanced Input keys (see Controls).
Key Mappings no value; the settings screen expands it into the player’s key rows None: the rows come from your mapping contexts. Per Player, with the Key Mappings binding.
Action no value; pressing it runs its binding Button Text

The text form never depends on the player’s language: a German player’s save file reads 0.5, not 0,5. Sliders clamp to their range and snap to the nearest step. Values are compared after parsing, so 0.50 equals 0.5 and TRUE equals true.

Logarithmic Scale lays a slider’s track out by ratio, for multipliers such as sensitivities: equal distances on the track are equal ratios of the value, so from 0.1 to 5 the value 1 sits at 59 % of the track instead of 18 %. The saved value, the steps and the display do not change. It needs a Min Value above 0 (validation reports one at 0 or below, and the track then stays even). Value To Track Position and Track Position To Value give the same mapping to a slider widget of your own.

The default a reset gives is, in order: the Platform Defaults entry for the current platform, then a default the binding knows, then the setting’s own default.

Bindings

Binding What it does
(none) or Stored Only Keeps the value; your game reads it with Get Value or On Setting Changed. Example: Field of View.
Window Mode, Screen Resolution, Monitor, VSync, Frame Rate Limit, Resolution Scale, HDR Output, HDR Brightness (Paper White), Overall Graphics Quality, Scalability Group Engine values that the engine saves in GameUserSettings.ini. Rolly Settings changes the engine’s user settings object (your project’s subclass included), applies each kind of change once per Apply and saves once.
Anti-Aliasing Method, Console Variable Set a console variable at the Game Override priority, which beats Project Settings and device profiles. The option Default removes the player’s choice, so the project’s own value applies again. Console Variable takes any variable (an upscaler’s switches, for example) and hides the setting while the variable does not exist (its plugin is not loaded).
Graphics Auto-Detect For an Action: runs the engine’s hardware test and proposes values for the graphics settings of the same scope. Work Scale (1 to 10) trades precision for time; Propose Resolution Scale adds a resolution preset.
Brightness (Display Gamma), Main Volume, Sound Class Volume, Subtitles, Colour Vision Deficiency, Colour Vision Deficiency Severity, UI Scale Engine values that the engine does not save; Rolly Settings saves them and applies them at start. Sound Class Volume takes any sound class (its children follow); pick your project’s classes if its sounds use others than the engine’s Music, SFX and Voice.
Key Mappings For the Key Mappings setting: a Reset of its category or of all settings puts the player’s keys back to the mapping contexts’ defaults. Hides the setting while Enhanced Input’s user settings are off. Per Player.
Enhanced Input Key For a Key Binding: one key of the player’s Enhanced Input keys, named by Mapping Name (the Name of the action’s Player Mappable Key Settings) and Column (Keyboard Mouse or Gamepad). Setting the value rebinds the key and saves it at once in Enhanced Input’s key file; Rolly Settings stores nothing. Its default is the mapping context’s key. A refused key (reserved, used by another row, the other column) leaves the key in use. Hidden while the column does not exist or cannot change. Per Player; Immediate or On Apply, never Requires Restart.
Controller Prompts For a Choice with Options From Binding: Auto, Xbox, PlayStation, Nintendo, Generic. Get Gamepad Family returns the chosen family, or with Auto the family of the gamepad in use. Per Player.
Your Blueprint binding Create a Blueprint class with Rolly Setting Custom Binding as its parent and override what you need: Apply Value (make the value take effect), Read Value, Get Default Value, Is Supported (false hides the setting), Get Options (for a Choice with Options From Binding), Propose Values (for an Action: values for other settings that wait for Apply, as Auto-Detect does), Reset Values (a Reset covered a setting without a value, such as Key Mappings: put the data it stands for back to its defaults) and Finish Applying (called once after a group of values was applied through the binding: write your save game there, once). Tick Saved Elsewhere when your own code saves the value; Rolly Settings then reads it at start-up instead of storing it, and Has Saved Value tells it whether the player has a saved value yet (return false before your save game exists, and the collection’s default is applied). For a Requires Restart setting with Saved Elsewhere, override Store Value For Next Start to write the value where your game reads it when it starts, and return true; without it, Rolly Settings keeps the value until the next start and calls Apply Value then. Inside any of these functions, Get Other Setting Value reads another setting of the same scope as the player sees it, a change that waits for Apply included; options built from it follow that setting at once (see Values and flows).

Each built-in binding’s tooltip says which kind of setting it needs and what it changes, and the setup checks report a mismatch. Window Mode, Screen Resolution, Monitor, Resolution Scale, Overall Graphics Quality, Scalability Group and Anti-Aliasing Method supply their own options, so tick Options From Binding on their Choice; Frame Rate Limit uses the Choice’s own options, with Ids in frames per second (0 for no limit). The engine bindings change one value for the whole game, so use them on Shared settings. The controls bindings (Key Mappings, Enhanced Input Key, Controller Prompts) belong to one player, so use them on Per Player settings; validation reports a Shared one as an error.

Every function receives a Rolly Setting Context with the game instance, the local player (empty for Shared settings) and that player’s controller (empty until the player has one). World nodes work inside the functions. Keep Apply Value safe to call more than once with the same value: values are applied when a player joins and again when the player gets a new controller, for example after a map change.

In C++, a new target is a new subclass of URollySettingBinding: override ReadValue, ApplyValue, GetDefaultValue, IsSupportedFor, GetDynamicOptions, IsSavedExternally, CheckSavedValue, StoreValueForNextStart, SupportsNextStartValues, ProposeValuesFor, ResetOwnValues (the reset of a setting without a value), FinishApplyingValues, GetAssetsToCook (assets the binding loads by path, which the cook then includes) and ValidateBinding as needed. The context of every call carries the values of the other settings of the same scope as the player sees them (Context.FindValue by tag, Context.FindValueOfBinding by binding class), valid for that call only. Bindings live in a shared asset, so keep no per-player state in them.

Values and flows

Each setting has a value (what the player chose and the screen shows), an applied value (what took effect) and a saved value (what the save file holds).

Call Effect
Set (any Set node) Immediate: takes effect and is kept. On Apply and Requires Restart: waits.
Apply Settings Applies the waiting values and saves them; Requires Restart values are saved for the next start. Settings with Needs Confirmation are applied but wait for Confirm Settings; returns true then, and On Confirmation Started fires.
Confirm Settings Keeps and saves the values that waited for confirmation.
Revert Settings Puts back the values from before that Apply. The same happens when the timeout passes (TimedOut), and when the player or the game leaves before an answer (Cancelled).
Discard Pending Changes Forgets values that wait for Apply (for Back without applying). Immediate values stay.
Reset All To Defaults, Reset Category To Defaults Sets the settings back to their defaults and applies them like Apply, with a confirmation when one of them needs it. A setting without a value resets through its binding: Key Mappings puts the player’s keys back to the mapping contexts’ defaults (and saves them).
Execute Action Runs an Action’s binding. When the binding proposes values (Auto-Detect), they become values that wait for Apply: the player sees them first and keeps them with Apply or drops them with Discard Pending Changes.

A Shared confirmation belongs to the player whose Apply started it: only that player is asked, and only that player can confirm or revert it. If another player applies Shared changes before that player answers, the confirmation moves to the other player: the first player’s On Confirmation Ended fires with Superseded and nothing is reverted. The values stay applied, and the other player’s answer decides for all of them, the first player’s included: Confirm keeps them, while Revert, the timeout or leaving puts back the values from before the first unanswered Apply. When the first player also had Per Player values waiting, their confirmation stays open for those.

Values that wait for Apply are shared too: a Shared value one player changed but did not apply is applied by another player’s Apply and dropped by another player’s Discard Pending Changes. Per Player values wait for their own player only.

One group, one engine apply. An Apply, a Revert (by call, timeout or leaving), a Reset, a Set of an Immediate value and the start each apply their values as one group. At the end of the group every binding it used gets Finish Applying once. The engine bindings use it to apply each kind of change once (one window change, one scalability change, one frame rate change) and to save GameUserSettings.ini once, however many values changed.

Values the engine changes itself. Alt+Enter, dragging the window to a new size, a scalability console command or another plugin can change engine values behind Rolly Settings’ back. Rolly Settings reads the values the engine saves again when the engine reports such a change (a new resolution, new scalability levels, the engine’s own video mode revert) and after every group, and On Setting Changed fires for each value that changed. Refresh Values does the same on demand: call it when a settings screen opens. A value that waits for Apply or for a confirmation is left alone.

First start. For a setting whose binding saves the value itself, the start asks the binding whether the player has a saved value; the engine bindings answer whether GameUserSettings.ini existed when the game started. On a fresh install (or after the project’s settings version made the engine delete the file) the collection’s defaults are applied through the binding and saved, so a new player gets the Default Option you chose (for example Medium quality) instead of the engine’s. The built-in library skips this: without a collection of your own, the project’s engine configuration (DefaultGameUserSettings.ini, device profiles) decides until the player changes a value.

A confirmation nobody answered. When an Apply that needs confirmation covers settings whose binding saves the value itself (Window Mode, Resolution, Monitor), Rolly Settings first writes the values to go back to into RollySettings.ini, then applies. Confirm and Revert remove them again. If the game quits during the countdown, the values are put back and GameUserSettings.ini is saved again while the game shuts down, so the next start opens in the previous mode. If the game crashes or is killed, the next start applies the values it wrote (before the first map) and removes them, and the window takes the recovered size as soon as it exists.

Options that follow other settings. A binding may build its options from another setting of the same scope, as the player sees it: the Resolution list is for the Window Mode and Monitor the player has picked, before Apply too. Rolly Settings notes which settings a binding reads while it builds the options. When the player changes one of them, the dependent options follow at once, and a value they no longer offer becomes the dependent setting’s default (a size the newly picked monitor lacks becomes that monitor’s native size), with On Setting Changed for both. Discard Pending Changes brings back both values, and Apply applies them together. A Reset computes such defaults again once every setting it covers is back at its default, so Resolution gets the native size of the monitor the reset picked, not of the monitor before it. Settings follow each other up to four deep: when a longer chain, or two settings whose options read each other, would still change a value there, Rolly Settings stops and reports a setup warning.

Requires Restart and bindings that save the value themselves. When a binding saves the value itself (Saved Elsewhere, or an engine setting), Apply offers the new value to the binding’s Store Value For Next Start. A binding that stores it where the game reads it at start (an engine config file, your save game) returns true. Otherwise Rolly Settings keeps the value in RollySettings.ini, applies it through the binding at the next start and then removes it from the file, because the binding keeps it from there on. The built-in engine bindings always leave it to Rolly Settings: GameUserSettings.ini holds the values in effect, and the next start applies the kept value before the first map. A binding that can do neither (its SupportsNextStartValues returns false) cannot be used with Requires Restart: validation reports it as an error, and Apply reports it and puts the value back instead of losing it silently.

Controls

Rolly Settings shows, changes and saves the keys of your Enhanced Input actions, and Enhanced Input applies them. The look settings reach the game through two input modifiers, and a device tracker tells your prompts what the player uses.

Setup (about 10 minutes)

  1. Project Settings > Engine > Enhanced Input > User Settings: keep Enable User Settings on (the default in 5.8). Project Settings > Engine > Input > Default Player Input Class must be an Enhanced Input player input: Enhanced Player Input (the editor switches projects to it), or Rolly Settings Player Input for split-screen (below).
  2. Give every input action the player may rebind Player Mappable Key Settings with a unique Name, a Display Name and a Display Category (the heading the row appears under). A mapping can have its own instead (Setting Behavior: Override Settings), which a move action needs: W, A, S and D each need a Name of their own (Move Forward, Move Back and so on).
  3. Project Settings > Plugins > Rolly Settings > Mapping Contexts: add the mapping contexts that hold those mappings. Rolly Settings registers them for every player as soon as the player has a controller, and cooks them. Contexts your own code registers with Enhanced Input’s user settings are listed too, after these.
  4. Put the look modifiers into your mapping contexts (Sensitivity and invert, below).
  5. The built-in library already has a Controls category. In your own collection, add a Per Player setting of kind Key Mappings with the Key Mappings binding, and the sliders, toggle and choice you want. Your settings screen builds the key list with Get Control Rows and captures keys with the key capture nodes.

Rows and columns. Get Control Rows returns one row per player-mappable name of the registered contexts, in the order the contexts list them, grouped by Display Category (a row without one goes under General). Each row has a keyboard and mouse column and a gamepad column. A column exists only where a mapping context gives the action a default key of that kind: Enhanced Input puts a player’s key only where a context key of the same kind was, so an action with only a keyboard key cannot get a gamepad button from the player. A column is read-only for an axis (the mouse movement, a stick) and for several keys under one name. Keys are never removed, only replaced: every column keeps a key. Only the active key profile is shown and changed. The rows are built on every call, so keep your own copy and build it again on On Controls Changed.

Keys a column takes. The keyboard and mouse column takes keyboard keys and mouse buttons (the wheel steps included), the gamepad column gamepad buttons (the triggers and stick directions as buttons included). Axes (the mouse movement, a stick or trigger value), touch and motion keys and Any Key are refused.

Conflicts. A key that another row uses in the same column is a conflict when both rows belong to one conflict group. All contexts form one group by default; give contexts that are never active together (on foot, in a vehicle) different groups in Project Settings, and their rows may share keys. Refused as well, each with a reason for the player: the reserved keys (Escape, the gamepad’s menu button, F11 while it toggles fullscreen, the console keys outside Shipping, and Project Settings’ Reserved Keys), keys of mappings in the registered contexts of the same group that are not player mappable (a Pause action on P), and keys of actions with Reserve All Mappings. When exactly one other row uses the key, the two can swap: that row gets this row’s previous key. When more rows use it, the player picks another key. Resets never check keys, so Find Key Conflicts lists the keys several rows share after one.

Key capture. For a settings screen:

  1. Begin Key Rebind (row, column) when the player picks a column; show “press a key”.
  2. Pass the key the player presses next to Finish Key Rebind. An accepted key is bound and saved, and the capture ends. A conflict with one other row waits for an answer: show the result’s Reason, then Confirm Key Swap swaps the keys and Cancel Key Rebind keeps both. A refused key (reserved, taken, the other column) keeps the capture open for another key; show the Reason.
  3. Cancel Key Rebind when the player presses Escape or Back (both are reserved, so they never bind).

Rebind Key does the same in one call, with Swap When Taken deciding a conflict.

Saving. A key change takes effect at once (Enhanced Input applies it to live input at the end of the frame) and is saved at once in Enhanced Input’s key file: <Slot>.sav in the SaveGames folder (Saved/SaveGames/EnhancedInputUserSettings.sav in the editor; the slot is Project Settings > Engine > Enhanced Input > Input Settings Save Slot Name). So changes in the key list stay outside Apply, Discard Pending Changes and confirmations. A change made while the player has no player controller (during travel) is saved as soon as the next controller arrives. Reset Control Row, Reset All Controls, and a Reset of the Controls category or of all settings (through the Key Mappings setting) put keys back to the contexts’ defaults and save.

One key as a setting. For a key in another category, or behind a condition, add a Key Binding setting with the Enhanced Input Key binding (Mapping Name and Column), Per Player. It works like any setting (Get Setting Value gives the key’s name, Set Setting Value rebinds, On Apply waits for Apply), its default is the context’s key, and Enhanced Input saves it. A refused key leaves the key in use; Check Key tells why.

Sensitivity and invert. Two Enhanced Input modifiers read the settings of the player whose input they change:

  • Rolly Settings Sensitivity multiplies the input by a Slider setting (Setting Tag: Rolly.Settings.Controls.MouseSensitivity on the mouse look mapping, Rolly.Settings.Controls.GamepadSensitivity on the stick look mapping), and by an optional factor per axis. Put it last in the modifiers of each look mapping, after dead zones and response curves.
  • Rolly Settings Invert negates the chosen axes (Y by default) while a Toggle setting is on (Rolly.Settings.Controls.InvertLookY). Put it last in the modifiers of the look action, so it covers mouse and gamepad at once. For a one-axis action, tick Invert X.

Both work for one, two and three axes and let a button’s value through. They keep the setting’s value until one of the player’s settings changes, so a call costs a few comparisons and a multiplication. Without a Rolly Settings subsystem (a dedicated server, an editor preview) the input passes unchanged. A tag that names no setting of the right kind is reported once, and the input passes unchanged.

Button prompts. Every player has a device tracker: Get Input Method (keyboard and mouse, gamepad, touch), Get Gamepad Family (Xbox, PlayStation, Nintendo, Generic), Get Input Device Names, and the event On Input Method Changed. Buttons and keys switch the method at once. A stick or trigger switches it only past Gamepad Analog Switch Threshold (Project Settings > Plugins > Rolly Settings Core, 0.5 of full travel), so a drifting stick does not flip the prompts, and the mouse switches it after a move of more than 3 pixels. Call Ignore Next Mouse Move after your interface hides, shows or centres the cursor. The family comes from the device’s names through the Device Families table in Project Settings > Plugins > Rolly Settings Core. Get Prompt Key For Action gives the key to show for an action in the method in use; Get Keys For Action gives all keys of a column (the player’s keys, else the live mappings, else the contexts’ defaults), for actions that are not player mappable too. The Controller Prompts setting overrides the family, because the engine alone cannot tell every pad: on Windows a PlayStation pad usually arrives through Steam Input as an Xbox pad.

Split-screen on PC. Enhanced Input saves the keys of every local player to the same file on desktop, so players overwrite each other’s keys. Set Project Settings > Engine > Input > Default Player Input Class to Rolly Settings Player Input: the first player keeps the file (the keys of a single-player game stay where they are), and every other player gets a file of their own with _<platform user index> added (EnhancedInputUserSettings_1.sav). Development builds report a setup warning when two local players share one key file.

The settings screen

The RollySettingsUI module (it loads in games and the editor, never on a dedicated server) builds the settings screen in C++ with the Rolly UI design system of the RollySettingsCoreUI module (see Structure): no assets and no Common UI are needed. The screen opens on the player’s screen stack, which shows each local player’s screens in that player’s part of the screen (see The screen stack).

Opening and closing. Open Rolly Settings opens the screen on top of the player’s screens, Open Rolly Settings At opens it at a category (its tag, for example Rolly.Settings.Category.Accessibility for an accessibility prompt at the first start; in the couch hub the category’s page opens, and Back then goes to the hub), Close Rolly Settings closes it with its questions and key capture, and Is Rolly Settings Open tells whether it is open (category Rolly|Settings|Screen). They take the player controller of the player whose screen it is; a split-screen game passes each player’s own. Get Rolly Settings UI gives that player’s Rolly Settings UI Subsystem (a local player subsystem) with the same functions and Get Settings Screen.

Choosing a layout. The screen is laid out in one of the design system’s five layout templates. Pick one by id in Project Settings > Plugins > Rolly Settings Core UI > Layout (empty: the theme’s Layout, which is Tabs unless you change it), in the theme asset, or while the game runs with the theme subsystem’s Set Layout. Switching while the screen is open keeps the category, the focused row, its scroll position and every change that waits for Apply.

Layout (id) What it shows Made for
Tabs (Tabs) The title, tabs between the keys that switch them, the list, the detail panel at the right (a strip under the list below 1600 units wide), the prompts at the bottom Most games, PC first; the default
Side Rail (Rail) A rail of categories with their icons at the left, the list under the category’s name, the detail at the right. Two levels: focus starts in the rail, Accept or Right opens the list, Back returns to the rail. On narrow areas the rail becomes a switcher over the list (one level) Many categories, RPGs, strategy and management, 21:9 and 32:9 screens
Centered Panel (Panel) An 880-unit card over the dimmed game: “Settings”, a switcher with the category and position dots, the list, a detail strip and the prompts, all in the card Small sets of settings, pause menus, split screen, casual and mobile games
Couch Hub (Hub) Big tiles with each category’s icon and a live summary of its values, then a page per category: an “All settings” link, the category’s name, its position (“1 / 7”), the list, the setting’s preview picture in a column on wide areas (only in a category with pictures; the list takes the width otherwise), and a description band. Large density by default Console, TV and Steam Deck play, touch tablets
Side Drawer (Drawer) A 560-unit drawer at the right (or left: Drawer Side) of the screen over the running game: the switcher, rows with the control under the name, a detail strip, the prompts. The game keeps running and is not paused; the player’s input goes to the drawer. It has one level, so its Back prompt reads Close: Back closes the drawer and returns to the game. In split screen it docks to the outer edge of the player’s part of the screen Games that never pause, quick tuning while the change shows (brightness, field of view, volume, sensitivity)

Every layout works with a gamepad, a keyboard, a mouse and touch, in split screen and at every Interface Size. Dialogs and key capture centre in the player’s part of the screen (with the Side Drawer layout, in the drawer).

What every layout shows:

  • The categories that have something to show on this machine, as tabs, a rail, a switcher or tiles.
  • One row per kind: a switch for Toggle, chevrons around the value for Choice, a slider with the value for Slider, a button for Action, a key cap for Key Binding and the key list for Key Mappings (a row per action, grouped by category, with a Keyboard & Mouse column and a Gamepad column; the settings after the key list get an Options heading of their own, so they do not read as part of its last group). Hidden settings disappear and disabled ones dim, following Visible When and Enabled When as the player changes values. A dot marks a value that waits for Apply, and a restart icon a value that was applied and waits for a restart.
  • The detail: the focused setting’s name and description, its preview picture when it has one, and its facts, each with its icon: the value in full when its row cuts it short (“Current: …”), not available right now and why, changed and waiting for Apply, takes effect after a restart, the seconds a confirmation gives to keep the value, and the default value. A side panel lists them; a strip or a band (narrow areas, the panel, the drawer, the hub’s pages) runs the name into the description and says the facts in one line, the default value first so a short line never cuts it. A setting without a description still shows its facts, in every layout and at every size: a strip or a band then says them in its line.
  • The footer: how many changes wait for Apply (“2 changes to apply”), and prompts with the keys of the device in use: keyboard keys for keyboard and mouse, the buttons of the gamepad family for a pad (Xbox letters, PlayStation shapes, Nintendo or a generic pad). When the footer runs out of room the prompts wrap to a second line, then the least important ones go (Reset first, then Revert Changes, Category and Apply; Accept and Back always show); on the smallest areas (640 x 360, a 4-player split at 150 %) they keep to one line, so the list keeps its room. A notice under the title says when applied changes need a restart, and after an Apply a short toast says the settings were applied (unless the keep-or-revert question asks already).

Key names. A key has one name on the whole screen, the one its cap shows, for the pad the player holds: the caps, the Default facts, a Key Binding’s value, the refusals of key capture and the swap question all say “Left Click”, “Space”, “RT” on an Xbox pad or “R2” on a PlayStation pad (arrows, directions and the PlayStation shapes are drawn on their caps and named in words: “Up Arrow”, “D-pad Up”, “Cross”). Code of your own gets the same names from FRollySettingsCoreKeyNames::GetName (Input/RollySettingsCoreKeyNames.h).

Categories and pictures. In the collection, a category can name an Icon (Display, Graphics, Picture, Audio, Controls, Accessibility, Gameplay, Camera or Interface; shown in the rail and on the hub’s tiles) and a Summary (the text of its hub tile; empty shows its first values, kept up to date, with the setting’s name where the value alone says nothing: a toggle, a slider, a choice showing On or Off, and an option two settings show: “Windowed Fullscreen”, “VSync On”, “Master Volume 80 %”, “Colour Vision Deficiency Off”, “View Distance High”). A setting’s Preview (a texture or a material, 16:9) shows with its description, in the detail panel or in the hub page’s preview column; a category’s Preview stands in for its settings that have none. All three are optional.

Keys (gamepad, keyboard):

  • Up and down (directional pad, stick, arrows) move between rows; past the last row focus goes around to the first, and before the first to the last (the theme’s Wrap Navigation). Home and End go to the first and the last row, Page Up and Page Down a page at a time.
  • Left and right change the value: a slider by one step (on a logarithmic track by the same ratio each time), a switch on with right and off with left. In the key list they pick the column.
  • Accept (bottom face button, Enter, Space) acts on the row: flips a switch, moves a choice on, runs an action, starts key capture.
  • The shoulder buttons or Q and E show the previous and next category at any level (they go around), and each category remembers its row. X or F applies. View or Backspace drops the changes that wait for Apply. Y or R resets the category to its defaults after a question.
  • Two levels: in the side rail, Accept or Right opens the list and Back returns to the rail (Tab and Shift+Tab move between them too); in the couch hub, the directional pad moves in the grid of tiles (it stops at the edges), Accept opens a page and Back returns to its tile.
  • B or Escape at the top level, or the gamepad’s menu button at any level, closes the screen, and first asks whether to drop changes that wait for Apply (Keep Editing has focus).
  • The mouse clicks rows, chevrons, switches, tabs, rail items, tiles and prompts, drags sliders, and moving it over a row gives that row focus while the player uses keyboard and mouse (a hidden cursor that jitters while a pad is in use does not take focus).
  • Touch: a row acts when the finger lifts from it, and a press that moves more than 12 units scrolls instead; tabs, rail items, tiles, chevrons and switches take taps; the prompts become buttons with their labels, a Back button shows in the header, and the focus look hides.

The keys are class defaults of the screen (category Keys), so a Blueprint subclass can change them.

Flows:

  • Values that wait for Apply stay waiting when the screen closes another way than Back (Close Rolly Settings, Close Rolly Screens, a map change, Remove All Widgets, the player leaving): the next Apply applies them, and Discard Pending Changes drops them.
  • After an Apply that needs confirmation (the display settings, or any setting with Needs Confirmation), the keep-or-revert dialog opens by itself, wherever Apply was called: Revert has focus, so a player who cannot read the screen gets the old settings back with Accept or by waiting, and the seconds left count down in real time with a shrinking bar. It closes on every end of the confirmation (kept, reverted, timed out, cancelled, taken over by another player). A map change, or the screens being removed (Remove All Widgets), does not answer it: the countdown keeps running, and the dialog comes back with the player’s controller in the new map, or the next frame. Closing the screens from code (Close Rolly Settings, Close Rolly Screens) answers Revert. Turn the dialog off with Show Confirmation Dialog if your game shows its own.
  • Key capture: Accept on a key cell opens “Press a key” (“Press a button” for the Gamepad column) with the action’s name and a bar for the time left. The next key is taken before the screens or the game see it: any keyboard key, mouse button or wheel for the Keyboard & Mouse column, any gamepad button, trigger or stick direction for the Gamepad column. A pad reports a trigger or stick press at once, at a small value, so the capture waits while it is held and takes it once it passes half of its travel (a trigger) or 80 % (a stick); a drifting stick never gets there and is ignored. Escape or the gamepad’s menu button cancels, and so do the countdown (Key Capture Timeout Seconds; a player with only a mouse cancels by waiting, since every mouse button can be bound) and switching to another window. A refused key keeps the capture open and says why (another column’s device, a reserved key, a fixed mapping). A key that one other row uses asks whether to swap the two keys: Swap, or Cancel to change nothing (Cancel has focus).
  • Every layout fits the area it gets. It lays out in a centred region at most 21:9 wide (the backdrop fills the rest), so a 32:9 screen keeps a readable width, while each player of a horizontal split keeps the full width. Under 800 units high (split screen one above the other) the title goes, the margins shrink and a split-screen player’s badge moves to the footer; below 1600 units wide the detail becomes a strip or a band; rows narrower than 640 units put their control under the name (switches stay beside it); a long name wraps to a second line before it reaches the value, and a value too long for its column ends with an ellipsis (the detail says it in full); a question’s buttons wrap to a second line when their labels do not fit; tabs scroll with the keys that switch them kept in view at both ends; the hub shows the tile columns that fit; prompts wrap, then drop by priority. Below 640 x 360 units (a 4-player split at 150 % Interface Size) the screen lays out at 640 x 360 and scales down to fit, the only case where text gets smaller.

Themes

Every screen, row, dialog and prompt draws with the Rolly UI design system of the RollySettingsCoreUI module. Widgets ask the theme for roles (Surface, Accent, the Title text role), never for literal colours or sizes, so one theme asset restyles the whole interface, live.

Ember, the default. With no theme assigned the screens use Ember, the built-in theme: near-black panels, off-white text and controls, and an orange accent kept small (the focus ring, the primary button, the selected tab’s underline, the picked key cell, progress bars). Its text passes 4.5:1 contrast on every panel (WCAG AA), controls and the focus ring 3:1, and its High Contrast Colours 7:1 with a 3-unit ring. Focus never relies on colour alone: the focused row has a ring and a fill.

Presets. Six themes are built in, in code: Ember (the default), Paper (warm light surfaces, ink text, a teal accent, a bar for focus; for cozy, casual, strategy and mobile games), Tactical (olive near-black, a lime accent, square corners, condensed capitals, monospaced values, corner brackets for focus; shooters and simulations), Neon (indigo with a magenta accent, a cyan focus ring with a glow, round shapes, a gradient backdrop; arcade, party and rhythm games), Glass (translucent panels over the dimmed game, a white ring, a cyan accent; background blur off by default, one token turns it on) and High Contrast (black, white outlines everywhere, a yellow 3-unit ring, no transparency). Every preset passes the design spec’s contrast checks, which the automated tests compute. The theme subsystem’s Set Preset switches to one for the session; Make Preset Theme gives one as a new theme object for code to adjust.

Your own theme, without C++:

  1. In the Content Browser: Add > Rolly > Rolly Settings Core UI Theme. The editor asks for a preset: the six presets side by side, each drawn as a screen with its name and what it suits. The new asset is an exact copy of the one you pick; name it as any new asset. (A Data Asset of class Rolly Settings Core UI Theme starts as Ember.)
  2. Edit its tokens; each has a tooltip.
    • Colours: the 22 colour roles (Backdrop, Scrim, Surface, Surface Raised, Surface Sunken, Outline, Outline Strong, Text, Text Muted, Text Disabled, Accent, On Accent, Control, Focus, Focus Fill, Hover Fill, Pending, Warning, Danger, Success, Key Cap, Key Cap Text), and High Contrast Colours, used while high contrast is on.
    • Typography: a Display, a Primary and a Mono font (empty: the engine’s built-in Roboto), and ten text roles (Display, Title, Heading, Tab, Label, Value, Button, Body, Caption, Key Cap), each with its font slot, size, letter spacing, case and line height.
    • Layout and Density (in Look): the layout template (see Choosing a layout), and Compact (x0.9), Standard, Large (x1.3) or Auto (the layout’s own: Large for the couch hub), which multiplies text, the spacing inside components and component sizes, for a desk or a couch. Project Settings > Rolly Settings Core UI > Layout and Density win over the theme’s.
    • Spacing and Sizes (advanced): the spacing steps, the row, control and glyph heights, the value, detail and dialog widths, the screen margins and the widest content.
    • Shape: corner radii, hairline and outline widths, Focus Style (Ring, the default, Bar, Brackets or Fill), Focus Width and Focus Glow (a soft glow around the ring).
    • Elevation and Backdrop: shadow colour, the backdrop’s gradient, vignette and blur (off by default; where blur cannot run the backdrop draws more opaque instead).
    • Motion: durations, easings, the enter distance and Motion Scale (0 stops movement).
    • Sounds: Navigate, Change, Accept, Back, Error, Open, Close and Notify, none by default. Give them the Sound Class your effects or interface volume controls.
    • Glyphs and Icons: Glyph Tints draws face buttons in their family colours (Glyph Tint Colors; a colour below 3:1 on the key cap is never drawn); Glyph Overrides relabel a key or a button per family (keyboard and mouse, Xbox, PlayStation, Nintendo, generic), draw it round or show your own image (a new label is the key’s name everywhere: on its cap, in its Default fact, in refusals and questions); Icon Overrides replace a built-in icon with a brush of yours.
    • Behaviour: Wrap Navigation (lists go around from the last row to the first), Hover Moves Focus, Show Option Dots and Toast Seconds.
    • Players: the four split-screen player colours and Player Badge Text, the colour of the “P2” on them.
  3. Right-click the asset > Use as the Rolly UI Theme for All Rolly Products (or the same button above its preview). Every installed Rolly product now draws with it; with Rolly Settings alone nothing else changes. To give only this product a look of its own instead, set Project Settings > Plugins > Rolly Settings Core UI > Theme Source to Asset and pick it in Theme. Either way it is always cooked.

Saving the theme checks it and says what to fix: a colour pair below its contrast (text 4.5:1, controls and focus 3:1, high contrast 7:1; a see-through backdrop is checked over a white and a black game frame), a text role that would read too small, a focus width under 2, capitals on long text, and a sound without a Sound Class. A theme that cannot be loaded in the game falls back to Ember with a setup error.

The theme’s editor. Open the asset: a Preview category at the top of its details shows the settings screen of the built-in library in your theme, live, restyled with every edit and every undo. Its toolbar switches the Layout (Tabs, Side Rail, Centered Panel, Couch Hub, Side Drawer), the Prompts (keyboard, Xbox, PlayStation, Nintendo, generic, touch), the Size (1920 x 1080, the Steam Deck, a player of a 2- or 4-player split, 21:9), Contrast and Motion (with Play Enter to watch the entrance), and has Open Preview Window (a resizable window with the screen up to real size, driven by your keyboard and mouse), Use for All Rolly Products and Reset to Preset (one undo step). Under the preview a line sums up the checks (“All 25 contrast checks pass, in the High Contrast Colours too. Smallest text 20.5 px (18 needed at Standard).”) and every problem follows with its fix, a colour to try included (“Lighten TextMuted (try 7F8186) or darken Surface”): the same messages Data Validation gives when you save. Content Browser thumbnails show each theme as a small screen in its colours. The preview never calls a setting, never touches the game’s settings and never changes the game’s look.

One look for every Rolly product. Every Rolly product carries its own copy of the design system, and they share a look in three layers: Project Settings > Plugins > Rolly Settings Core UI > Theme Source of each product (Shared, the default, follows the shared theme; Preset and Asset give that product its own look); the shared theme, [RollyUI] Theme in your project’s DefaultGame.ini (an asset path or Preset:<id>; Use as the Rolly UI Theme for All Rolly Products writes it, one key, nothing else); and while the game runs the console variables rolly.ui.theme (a theme asset’s path or a preset id, over the shared theme), rolly.ui.motion (0 to 1) and rolly.ui.contrast (0 or 1), which every product follows at once. A theme of another Rolly product’s class works too: its values are copied by name. If you remove the product that owns the shared theme’s class, every product falls back to Ember and says so, with the fix: while both are installed, right-click that theme > Duplicate as this product’s theme, and share the copy. Screens of several Rolly products open and close in any order for the same player; each product gives the game its input back only when no Rolly screen is open any more.

An Interface Theme setting (recipe). Rolly Settings has no built-in theme setting, because the themes a game offers are its own. Add one to your collection: a Choice named Interface Theme, with the Console Variable binding, Variable Name rolly.ui.theme and Default Value Default, and options whose ids are what to show: Default (named, for example, Game Default; it removes the player’s choice, so the shared theme applies again), presets as Preset:Paper or Preset:HighContrast, and your theme assets as their paths (/Game/UI/RT_Cozy.RT_Cozy). Choosing one restyles every Rolly product at once, and the choice is saved with the other settings. Every theme you offer must be cooked: share one of them, or reference the others from your own content.

While the game runs: editing the theme asset during Play In Editor restyles the open screens at once. The Rolly Settings Core UI Theme Subsystem (an engine subsystem, category Rolly Settings Core|UI) has Set Theme (empty goes back to the theme of Project Settings), Set Preset, Set Layout, Set Density, Set High Contrast (the High Contrast Colours, a 3-unit ring and outlined panels), Set Reduced Motion (no movement, fades of 100 ms or less) and the event On Theme Changed. They apply to every local player, and open screens restyle in place: focus, scroll position and waiting changes stay as they were. What the game sets here lasts for its session: when a Play In Editor session ends, the theme of Project Settings comes back with high contrast and reduced motion off, so the next session and the editor start from the project’s look. The built-in High Contrast Interface and Reduce Motion settings drive the same switches, so players choose them in the Accessibility category (they start from the system’s own preferences). High contrast and reduced motion are kept in the shared rolly.ui.contrast and rolly.ui.motion, so they reach the screens of every installed Rolly product, whoever sets them (a setting, Set High Contrast, the console).

Widget Blueprints of your own follow the theme too: call Listen To Rolly Theme in Event Pre Construct (or add the Rolly Theme Listener extension), add the Rolly Theme Aware interface and implement On Rolly Theme Changed, and restyle there with Get Rolly Theme Color, Get Rolly Theme Font, Make Rolly Surface Brush and Get Rolly Motion Scale. The event runs when the widget shows and on every theme, contrast or motion change while it is on screen.

Layouts of your own

Every screen and piece is an ordinary user widget whose default layout is built in C++. A Widget Blueprint subclass with a layout of its own keeps it: the C++ code drives the widgets whose names match its parts, and a part the layout leaves out only turns its feature off. Each part’s tooltip (in the class’s variables) says which widget type it needs and what the code sets on it, and a layout of your own adapts to split screen in On Area Changed. Without a layout, a subclass keeps the built-in one and can still change the class defaults. Everything in this section works in Blueprint, without C++.

What Where you pick it Parts (widget names)
The settings screen (parent class Rolly Settings Screen) Project Settings > Plugins > Rolly Settings Screen > Settings Screen Class Backdrop, TitleText, NoticeText, NoticeIcon, PlayerBadge, TouchBackButton, TabStrip, RailList, CategorySwitcher, HubTiles, CategoryTitle, ListPanel, SettingsList, DescriptionPanel, DescriptionTitle, DescriptionText, DescriptionLine, DescriptionPreview, DescriptionStatus, PendingCounter, PendingCounterText, PromptBar. Without a layout of your own the screen puts its parts into the layout template in use; with one, your layout decides and the parts you leave out turn their feature off
A layout template (parent class Rolly Tabs Template, Rolly Side Rail Template, Rolly Centered Panel Template, Rolly Couch Hub Template or Rolly Side Drawer Template) Project Settings > Plugins > Rolly Settings Core UI > Template Classes, per layout id Named Slots named Backdrop, Header, Navigation, Content, Detail, Footer and (the hub) Preview: arrange them in the designer, and the screen fills them. The template still decides how the parts behave for each area, through its traits (the navigation, the detail form, what Back and Reset say, option dots under choices), which come with the parent class you pick, never with the id
Key capture (Rolly Settings Key Capture Screen) The same page: Key Capture Screen Class Backdrop, Panel, ActionText, TitleText, MessageText, TimeoutBar, CancelPrompt
Dialogs: keep-or-revert, discard, reset, key swap (Rolly Settings Core UI Dialog) Project Settings > Plugins > Rolly Settings Core UI > Dialog Class Backdrop, Panel, TitleText, MessageText, CountdownText, CountdownBar, ConfirmButton, CancelButton
Rows (Rolly Settings Toggle Row, Choice Row, Slider Row, Action Row, Key Binding Row, Key Mapping Row, or any subclass of Rolly Settings Setting Row) Row Classes, a map from setting kind to row: Project Settings > Plugins > Rolly Settings Screen for every screen, or the class defaults of your settings screen subclass (category Rows), whose entries win for the same kind. A setting shows with the row of its own class, else of its nearest parent class: a kind of your own (a C++ subclass of Rolly Setting or of a built-in kind) gets a row here, and a subclass of a built-in kind keeps the built-in row until you list one. The Key Mappings entry names the rows of the key list Every row: Background, FocusFrame, PendingDot, NameText, StatusIcon, ValueBox. Then Switch and ValueText (Toggle); ValueText, PreviousButton and NextButton (Choice); Slider and ValueText (Slider); ActionButton and ActionText (Action); KeyGlyph (Key Binding); KeyboardButton, GamepadButton, KeyboardGlyph, GamepadGlyph, KeyboardChanged, GamepadChanged, KeyboardTitle and GamepadTitle (Key Mapping)
The tabs row and the footer prompts (Rolly Tab Strip, Rolly Prompt Bar) Your settings screen layout: a widget of that class, or of a Blueprint subclass of it with a layout of its own, named TabStrip or PromptBar Tab Strip: TabScroll (a horizontal Scroll Box), TabBar (the panel it fills with tabs), PreviousTabGlyph, NextTabGlyph. Prompt Bar: PromptPanel (a Wrap Box lets the prompts wrap)
Tabs and prompts (Rolly Tab, Rolly Prompt) The class defaults of your settings screen subclass, category Parts (the screen hands them to its tab strip and prompt bar) Tab: LabelText, Underline. Prompt: Background, Glyph, SecondGlyph, LabelText
Rail items and tiles (Rolly Rail Item, Rolly Tile) The same category Parts: Rail Item Class, Tile Class Rail Item: Background, SelectionBar, IconImage, LabelText, PendingDot, FocusFrame. Tile: Background, IconImage, NameText, SummaryText, PendingBadge, PendingText, FocusFrame
Toasts (Rolly Toast) Project Settings > Plugins > Rolly Settings Core UI > Toast Class Panel, StatusIcon, MessageText

The screen’s other class defaults: the keys (category Keys) and Ask Before Discarding.

The screen stack

The stack comes with the design system (category Rolly Settings Core|UI). The settings screen is one screen on it, and screens of your own can share it.

  • Each local player has a screen stack, the Rolly Settings Core UI Stack Subsystem (a local player subsystem; Get Rolly Screen Stack from a player controller). Push Screen, Pop Screen, Replace Top Screen, Close Screen (a screen and the ones above it) and Close All Screens work on it, and Handle Back does what Back does. Back (B, Escape) asks the top screen first: the settings screen asks before it drops changes, a dialog answers Cancel. The top screen has focus; the screens below are hidden, or dimmed behind a dialog. Events: On Screen Opened, On Screen Closed, On Stack Opened (the first screen opened) and On Stack Closed (the last one closed). Set Host Panel shows the player’s screens inside a panel of your own (an Overlay of your HUD) instead of the game viewport; None goes back to the viewport.
  • 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. The optional Menu Input Mode Tag (Project Settings > Plugins > Rolly Settings Screen) is on a player’s Enhanced Input mode while a screen takes that player’s input, so mapping contexts that exclude it stop for that player only.
  • Pausing: screens that ask for it pause a standalone game, the settings screen included, 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. Pausing set to Never turns it off everywhere, and a settings screen subclass can turn its Pause Game off.
  • Your own screens: make a Widget Blueprint whose parent class is Rolly Settings Core UI Screen, set Input Mode (Menu or Overlay), Pause Game, Keep Screen Below Visible and Show Mouse Cursor in its class defaults, and open it with Push Rolly Screen. Override On Back to refuse or ask first; On Shown, On Covered, On Closed and On Area Changed tell it what happens. A main or pause menu of your own made this way shares the stack with the settings screen: its Settings button calls Open Rolly Settings, and Back comes back to it. Made of the Rolly widgets (the palette’s Rolly Settings Core category: Rolly Text, Surface, Icon, Glyph, Progress Bar, List, Button, Tab Strip and Prompt Bar), it follows the theme too.
  • Tabs and prompts of your own screens: the settings screen’s tabs row and footer are components you can use too. 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); 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. Both follow the player’s input device by themselves.
  • Toasts: Show Rolly Toast (a message and a kind: Info, Success or Warning) shows a short message at the top 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.
  • Dialogs: Show Rolly Dialog (a latent node with Confirmed and Cancelled pins) or the stack’s Show Dialog show a title, a message, a confirm and a cancel button (or only confirm), 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.
  • Where screens show: with Screen Layer 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.

Common UI or your own layers

A game with its own layer system, Common UI for example, puts each player’s host into one of its layers with a presenter: a small C++ class implementing IRollySettingsCoreUIPresenter (Present, Dismiss, IsPresented, and optionally GetAreaSize for the compact layouts), handed to each player’s stack with URollySettingsCoreUIStackSubsystem::SetPresenter. With Common UI:

  • Add the host to a slot of your root layout (for example an overlay above your activatable widget stacks) in Present, and remove it in Dismiss. The host is a plain user widget; it does not need to be an activatable widget.
  • While Rolly screens are open the host keeps the player’s input from the game, and Common UI’s action router still sees the player’s keys: switch your Common UI input config to Menu in On Stack Opened and back in On Stack Closed (with Input After Screens set to Custom if Common UI manages the viewport’s input mode itself). A game with an input policy of its own can replace the whole input handling instead: URollySettingsCoreUISharedSubsystem::SetInputHandler with a class implementing IRollySettingsCoreUIInputHandler.
  • The screens do not use Common UI’s bound actions: they read Accept and Back from the engine’s navigation config, so they work the same inside and outside Common UI.

Blueprint API

The settings nodes are on Rolly Settings Subsystem (a local player subsystem), category Rolly|Settings. Get it with the Get Rolly Settings Subsystem node from a widget or a player controller; a GameMode or a level actor has no local player.

Node Notes
Get Setting Value, Set Setting Value Any kind, in its text form
Get Bool Value, Set Bool Value Toggle (another kind is reported; Get gives false, Set changes nothing)
Get Float Value, Set Float Value Slider (another kind is reported; Get gives 0, Set changes nothing)
Get Option Value, Set Option Value, Get Options Choice (another kind is reported; Get gives None, Set changes nothing). Options from a binding (resolutions, monitors) are read when asked, so they follow what the player has chosen: the Resolution list follows the Window Mode and Monitor before Apply.
Get Display Value The value as the player reads it (On, 75 %, an option’s name)
Get Default Value, Find Setting, Get Settings Collection Definitions
Is Setting Visible, Is Setting Enabled Conditions, platforms and binding support
Execute Action Action settings; proposed values wait for Apply
Refresh Values Reads again the values the engine saves itself; call it when a settings screen opens
Apply Settings, Confirm Settings, Revert Settings, Discard Pending Changes Flows
Reset All To Defaults, Reset Category To Defaults Resets (a category needs a tag for this node)
Has Pending Changes, Is Confirmation Pending, Get Confirmation Seconds Remaining, Is Restart Required State

Events: On Setting Changed (tag, value; also for shared values another player changed and for values the engine changed itself), On Settings Applied (restart required), On Confirmation Started (seconds), On Confirmation Ended (Confirmed, Reverted, TimedOut, Cancelled, or Superseded when another player applied Shared changes while yours were waiting for confirmation and now decides for both; see Values and flows). Close the keep-or-revert dialog on every result; only Reverted, TimedOut and Cancelled mean the previous values are back. If one Apply held both Per Player and Shared values and another player then took over the Shared part, your later result (Reverted, TimedOut or Cancelled) covers only your Per Player values.

Controls nodes, category Rolly|Settings|Controls (see Controls for the rules behind them):

Node Notes
Are Controls Ready True once the player has had a controller and Enhanced Input has made the player’s key settings; the rows are empty before
Get Control Rows, Find Control Row The key rows: mapping name, display name, category, action, and per column (Keyboard Mouse, Gamepad) whether it exists, whether it can change, the current key, the default key and whether the player changed it
Check Key What a key would do to a row’s column, without changing anything: Accepted, Unchanged, Conflict (with the rows that use the key, and whether a swap is possible), Reserved, Taken By Fixed Mapping, Taken By Reserved Action, Wrong Column, Not Bindable, Not Rebindable or Not Ready, with a Reason to show the player
Rebind Key Binds in one call; Swap When Taken decides a conflict with one other row
Begin Key Rebind, Finish Key Rebind, Confirm Key Swap, Cancel Key Rebind, Is Key Rebind Active Key capture for a settings screen
Reset Control Row, Reset All Controls, Find Key Conflicts Resets, and the keys several rows share after one
Get Keys For Action, Get Prompt Key For Action The keys of an action for a column, or the key to show for the input method in use
Get Reserved Keys Keys no row can take
Get Input Method, Get Gamepad Family, Get Input Device Names, Ignore Next Mouse Move Button prompts

Controls events: On Controls Changed (the keys changed or became available: build the list again) and On Input Method Changed (input method, gamepad family: switch the prompts).

Tags are not limited to Rolly.Settings: built-in settings use Rolly.Settings.*, your own may use any tag.

The game instance subsystem Rolly Settings Shared Subsystem exposes Get Settings Collection and Is Using Built In Library.

Settings screen nodes, category Rolly|Settings|Screen (see The settings screen). They take the player controller of the player whose screen they open; a split-screen game passes each player’s own.

Node Notes
Open Rolly Settings Opens the settings screen on top of the player’s screens (the class of Project Settings, or the built-in one)
Open Rolly Settings At The same, at a category (its tag): selected, and in the couch hub its page opened
Close Rolly Settings, Is Rolly Settings Open Closes it with its questions and key capture; tells whether it is open
Get Rolly Settings UI The player’s Rolly Settings UI Subsystem: Open Settings, Close Settings, Is Settings Open, Get Settings Screen

On the settings screen: Select Tab, Get Selected Tab, Get Tab Count, Open Category With Tag, Apply Changes, Revert Changes, Request Reset and Get Pending Count, and what every Rolly screen has: Close Screen, Get Stack, Is Top Screen and Get Area Size.

Screen stack, dialog and theme nodes, category Rolly Settings Core|UI (see The screen stack and Themes):

Node Notes
Get Rolly Screen Stack The player’s Rolly Settings Core UI Stack Subsystem: Push Screen, Pop Screen, Replace Top Screen, Close Screen, Close All Screens, Handle Back, Get Top Screen, Get Screen Count, Is Any Screen Open, Show Dialog, Set Host Panel, and the events On Screen Opened, On Screen Closed, On Stack Opened and On Stack Closed
Push Rolly Screen, Pop Rolly Screen, Close Rolly Screens, Is Rolly Screen Open The stack, from a player controller
Show Rolly Dialog Latent: shows a dialog (title, message, button texts and looks, confirm only, which answer has focus, countdown) and fires Confirmed or Cancelled once
Show Rolly Toast Shows a toast (message, kind) to the player
Rolly Settings Core UI Theme Subsystem (an engine subsystem) Set Theme, Get Theme, Set Preset, Make Preset Theme, Set Layout, Get Layout, Set Density, Get Density, Set High Contrast, Is High Contrast, Set Reduced Motion, Is Reduced Motion, Get Motion Scale, and the event On Theme Changed
Listen To Rolly Theme, Get Rolly Theme Color, Get Rolly Theme Font, Make Rolly Surface Brush, Get Rolly Motion Scale For Widget Blueprints of your own that follow the theme (see Themes)

On a dialog: Answer, Get Seconds Remaining and the event On Dialog Result. The game instance’s Rolly Settings 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).

Console commands

Each command works on the first local player of the console’s game, or on another one with player=<index>.

Command Effect
rolly.settings.dump [player=N] Every setting with its kind, scope, value, applied and saved value, and whether it is hidden or disabled
rolly.settings.set <Tag> <Value> [player=N] Changes a value (text form)
rolly.settings.apply [player=N] Applies waiting values
rolly.settings.reset [Category] [player=N] Resets everything, or one category by tag or display name
rolly.settings.confirm, rolly.settings.revert Answers a pending confirmation

The commands are not cheats, so game code can run them in any build through the engine’s Exec.

Saving

  • Values are saved to RollySettings.ini in the user’s saved config folder, next to GameUserSettings.ini (for example Saved/Config/Windows/RollySettings.ini, or under %LOCALAPPDATA% for installed Shipping builds on Windows). It is a file of its own because the engine may delete GameUserSettings.ini when a project bumps its settings version.
  • Sections: [RollySettings.Shared] and [RollySettings.Player.<platform user index>]; keys are setting tag names. On desktop the platform user index is the controller slot (the first player is 0).
  • Only values that differ from the default are written, so a default changed by a game update reaches players who never changed that setting. Renamed tags are followed through Gameplay Tag redirects. Values that no setting of the collection owns are kept unchanged at every save: content that is not loaded yet (a Game Feature, DLC), a newer or older build of the game.
  • The file names its format in section [RollySettings], key FormatVersion (1 today); a file without it is read as format 1. A file of a newer format (written by a newer version of Rolly Settings, for example when a player goes back to an older build) is read but never written in that session, with a setup warning, so its data survives.
  • Writing happens on Apply, Confirm, Reset, when a player or the game leaves, and when a mobile app goes to the background or the system ends it; never on every slider move.
  • -RollySettingsINI=<path> on the command line moves the file; -nowrite stops all writes.
  • Storage Class in Project Settings chooses where values go: Ini File (default), Memory Only (nothing is saved; for kiosks, demos and tests), or your own subclass of URollySettingsStorage (override LoadValues, SaveValues and Flush) to use your save system.
  • Values a binding saves itself are not written by Rolly Settings, except a Requires Restart value that waits for the next start (see Values and flows). The built-in display and graphics settings are saved by the engine in GameUserSettings.ini, once per group of values; the anti-aliasing method, brightness, volumes, subtitles, colour vision, interface size, high contrast and reduce motion are saved in RollySettings.ini.
  • While a confirmation of such values is pending, the values to go back to wait in [RollySettings.Shared.Unconfirmed] (and [RollySettings.Player.<platform user index>.Unconfirmed]); the sections disappear on Confirm or Revert (see Values and flows).
  • In the editor (Play In Editor, tests) nothing is written to GameUserSettings.ini: the editor’s file is shared by every project on the machine.
  • The player’s keys are saved by Enhanced Input in its own key file (<Slot>.sav in the SaveGames folder, see Controls), after each change; RollySettings.ini holds none of them. A backup or cloud copy of a player’s settings needs both files. The other Controls values (sensitivity, invert, prompts) are Per Player values in RollySettings.ini.

Project Settings (Plugins > Rolly Settings)

Option Default Notes
Collection empty (built-in library) Always cooked, see below
Storage Class Ini File Where values are saved
Confirmation Timeout Seconds 15 1 to 120
Validate Collection At Startup on Reports collection problems when the game starts (development builds)
Mapping Contexts empty The mapping contexts whose player-mappable actions the key list shows, each with a Conflict Group (empty: the default group). Registered for every player, always cooked. See Controls
Reserved Keys Escape, Gamepad Special Right Keys no row can take. F11 (while it toggles fullscreen) and, outside Shipping, the console keys are added to them

Project Settings (Plugins > Rolly Settings Screen)

Option Default Notes
Settings Screen Class, Key Capture Screen Class empty (built-in) Blueprint subclasses with layouts of your own (see Layouts of your own). Always cooked
Show Confirmation Dialog on The keep-or-revert dialog after an Apply that needs confirmation
Menu Input Mode Tag empty Added to the player’s Enhanced Input mode while a screen takes the player’s input
Key Capture Timeout Seconds 10 2 to 60
Row Classes empty (the built-in rows) A row class per setting kind (see Layouts of your own), for every settings screen; a screen subclass’s own Row Classes win for the same kind. Always cooked

Project Settings (Plugins > Rolly Settings Core UI)

Option Default Notes
Theme Source Shared Shared: the theme every Rolly product shares (rolly.ui.theme while it is set, else [RollyUI] Theme in DefaultGame.ini, else Ember). Preset: Theme Preset. Asset: Theme (see Themes)
Theme Preset Ember For Theme Source Preset: Ember, Paper, Tactical, Neon, Glass or HighContrast
Theme empty (Ember) For Theme Source Asset: a Rolly Settings Core UI Theme asset (see Themes). Always cooked
Layout empty (the theme’s: Tabs) Tabs, Rail, Panel, Hub or Drawer (see Choosing a layout)
Density Auto Compact, Standard or Large; Auto takes the theme’s, else the layout’s own (Large for the hub)
Drawer Side Right The side the Side Drawer docks to; in split screen it docks to the outer edge of the player’s part of the screen
Dialog Class empty (built-in) A Blueprint subclass of Rolly Settings Core UI Dialog with a layout of your own. Always cooked
Template Classes empty (built-in) Per layout id, a Blueprint subclass of a Rolly template with a layout of your own (see Layouts of your own). Always cooked
Toast Class empty (built-in) A Blueprint subclass of Rolly Toast with a layout of your own. Always cooked
Screen Layer Player Player: each player’s part of the screen. Viewport: the whole viewport, above a HUD added with Add to Viewport
Viewport Z Order 100 For Screen Layer Viewport
Input After Screens Previous What input becomes when the last screen closes: Previous (as recorded), Game Only, Game And UI, or Custom (nothing changes; set it in On Stack Closed)
Pausing Standalone Only Standalone Only or Never

Project Settings (Plugins > Rolly Settings Core)

Option Default Notes
Device Families XInput, Xbox, DualSense, DualShock, PS4, PS5, Switch, Pro Controller, Joy-Con names Which gamepad family a device’s name means: exact names first, then parts of names (Match Part Of Name); anything else is Generic
Gamepad Analog Switch Threshold 0.5 0.05 to 1: how far a stick or trigger must move before the prompts switch to the gamepad

Setup checks and messages

Saving a collection checks it (Data Validation, on by default); right-click > Asset Actions > Validate Assets, or Tools > Validate Data for the whole project, does the same on demand. It reports, each with its fix: empty rows, missing, unregistered or duplicate tags (a duplicated row keeps the tag of its original), missing display names, bad slider ranges and steps, defaults outside the range, choices without options, option problems, bad platform defaults, conditions without a tag, on an unknown setting, on the setting itself, on an Action or with a value the target cannot have, loops of conditions, slider conditions that compare with a value off the slider’s steps or a threshold outside its range (warnings), settings that need confirmation but do not wait for Apply, and Requires Restart settings whose binding saves the value itself but cannot keep it for the next start. For the built-in bindings it also reports a binding on the wrong kind of setting (a Window Mode binding on a Slider), an engine binding on a Per Player setting (warning), a binding that supplies options without Options From Binding ticked (warning), colour vision options whose Id is not a deficiency, a Console Variable binding without a variable (and, as a warning, one that does not exist) and a Sound Class Volume binding without a sound class (warning). For the controls it reports a Key Mappings setting that is Shared (error) or has no Key Mappings binding (warning: a Reset would leave the keys alone); an Enhanced Input Key binding on another kind than Key Binding, on a Shared setting or without a mapping name (errors), on a Requires Restart setting (error: Enhanced Input saves keys at once) or next to a Default Key or Platform Defaults it does not use (warning); and a Controller Prompts binding on another kind than Choice or on a Shared setting (errors) or without Options From Binding (warning).

While the game runs, setup mistakes (an unknown tag passed to a node, a Get or Set node of the wrong kind, a collection that failed to load) are reported once per session: in the Output Log, in the Message Log under the Rolly Settings Core listing (with a link to the object), and on screen in development builds. The console variable rollysettingscore.setuperrors.onscreen 0 turns the on-screen lines off. Each Play In Editor session reports afresh.

Saving a Rolly Settings Core UI Theme checks it (see Themes). While the game runs, a theme, a dialog class or a screen class named in Project Settings that cannot be loaded is reported the same way and the built-in one is used, and a setting of a kind the settings screen has no row for (a C++ setting class of your own) is reported and left out of the screen.

The controls add these runtime reports: a player input that is not an Enhanced Input one, and a mapping context in Project Settings that cannot be loaded (errors); Enhanced Input’s user settings turned off while the collection has key settings; no registered mapping context, or no player-mappable key in them; a key without a Display Name; several keys of one kind under one name (a move action’s W, A, S and D); one name with different default keys in two contexts; an Enhanced Input Key setting hidden because its column does not exist or cannot change; local players that share one key file; and a modifier whose Setting Tag names no setting of its kind (warnings). The reports about the key rows come when the list is first built (Get Control Rows) in development builds, because a game may register contexts after the first controller.

Cooking

The collection named in Project Settings is always cooked: the editor module adds it to every cook, and the cook log names it. The assets its bindings load by path (the sound classes of the volume settings) are added too, also for the built-in library, which uses the engine’s Music, SFX and Voice classes, and so are the mapping contexts of Project Settings > Mapping Contexts, which nothing else may reference. If the collection is missing when the game starts (deleted, renamed, not cooked, not a collection), the game uses the built-in library and reports a setup error, so players never get an empty settings screen. Other ways to cook a collection that is only loaded by path: Project Settings > Packaging > Additional Asset Directories to Cook, or a Primary Asset Label.

The same holds for the screens: the theme and the dialog class of Project Settings > Rolly Settings Core UI and the screen classes of Project Settings > Rolly Settings Screen are added to every cook (a built-in C++ class needs nothing), and a name that does not exist is reported at cook time with its fix. A theme or screen class that cannot be loaded in the game falls back to the built-in one with a setup error.

Multiplayer

Settings are local: nothing replicates, and a dedicated server creates no Rolly Settings subsystems. On a listen server and on clients each machine has its own values.

The screens are local too, one stack per local player; they never send anything over the network. Screens pause only a standalone game (see The screen stack), so in the default Play In Editor setup (a listen server and a client) the settings screen opens without pausing.

In Play In Editor every window has its own game instance and values, but some engine state is shared by the whole editor process (console variables, scalability, GameUserSettings), and all windows write the same RollySettings.ini with platform user index 0 for their first player. A shared change made in one window can therefore show in another. The same holds for keys: the first player of every window uses the same Enhanced Input key file, and input in any editor window can switch the prompts of every Play In Editor window. These are Play In Editor artifacts, not problems in packaged games.

Play In Editor

  • The engine values the built-in bindings change belong to the whole editor process: its scalability, frame cap, display gamma, subtitles, interface scale, colour correction and console variables. The editor module records them when Play In Editor starts and puts them back when it ends, and the log says so. When a game ends, its sound mix is removed from the audio device, and the device gets back the main volume that was in effect before that game changed it: another game’s on a device several games share, else full volume.
  • Window mode, resolution and monitor changes take effect in Standalone Game and in packaged games, not in Play In Editor, where the editor keeps its own windows (one log line says so). VSync shows only in Standalone Game and packaged games, because the editor presents without it.
  • The editor always has a GameUserSettings.ini, so the first-start defaults (see Values and flows) never apply in Play In Editor. Test them in a packaged build with the file deleted.

Localization

Every player-facing text is an FText (LOCTEXT namespaces start with RollySettings, with RollySettingsCoreUI for the texts of the shared widgets and dialogs, and with RollySettingsCoreKeyNames for the names of keys), the screen’s labels, facts, prompts and questions included; an automated test shows the screen, its dialogs and key capture in the LEET test language and fails on any text that did not come through localization. To translate the plugin’s own texts with your game, add the plugin’s Source folder to your Game localization target’s Gather from Text Files search directories. Texts in your collection are gathered with your content. Numbers follow the player’s culture (0,5 in German).

Extending

  • A new binding target: a C++ subclass of URollySettingBinding, or a Blueprint child class of Rolly Setting Custom Binding.
  • Another save system: a subclass of URollySettingsStorage, picked in Project Settings.
  • A project subclass of URollySettingsSubsystem or URollySettingsSharedSubsystem replaces the plugin’s own.
  • C++ code can use the plain classes directly: FRollySettingsModel (values and flows of one scope), FRollySettingsPlayerView (one player’s view of both scopes), FRollySettingsValidator, FRollySettingsDefaultLibrary::Create (the built-in library as a new collection), FRollySettingsControls (one player’s key rows, checks, rebinds and resets; URollySettingsSubsystem::GetControls) and the player’s input device subsystem (URollySettingsCoreInputDeviceSubsystem, from URollySettingsSubsystem::GetInputDevices: the input method and gamepad family, with a native change event).
  • The screen: see Themes, Layouts of your own, The screen stack and C++. A project subclass of URollySettingsUISubsystem, URollySettingsCoreUIStackSubsystem or URollySettingsCoreUISharedSubsystem replaces the plugin’s own.
  • Rolly Settings uses Enhanced Input’s user settings and key profile classes through their public calls and never replaces them (the key file stores their class paths). A project that sets classes of its own in Project Settings > Engine > Enhanced Input should keep working as long as they keep the stock rows and slots, since Rolly Settings passes each mapping’s slot and device back unchanged; the automated tests cover only the stock classes.

C++

Add the modules you use to your module’s Build.cs:

PrivateDependencyModuleNames.AddRange(new string[]
{
	"RollySettings",   // values, flows, controls
	"RollySettingsUI", // the settings screen
	"RollySettingsCoreUI",     // themes, Rolly widgets, the screen stack
});
C#

Headers sit in feature folders and are included by path from the module’s Public folder (Screens/RollySettingsScreen.h); Docs/ARCHITECTURE.md lists the folders and what each holds.

Open the settings screen from a menu of your own:

#include "Screens/RollySettingsUISubsystem.h"

void UMyPauseMenu::HandleSettingsClicked()
{
	if (URollySettingsUISubsystem* SettingsUI = URollySettingsUISubsystem::Get(GetOwningLocalPlayer()))
	{
		SettingsUI->OpenSettings();
	}
}
C++

Read a value where the game uses it (bind OnSettingChanged to follow its changes):

#include "RollySettingsTags.h"
#include "Subsystems/RollySettingsSubsystem.h"

void AMyPlayerCameraManager::ApplyFieldOfView(const ULocalPlayer& Player)
{
	if (const URollySettingsSubsystem* Settings = Player.GetSubsystem<URollySettingsSubsystem>())
	{
		SetFOV(Settings->GetFloatValue(RollySettingsTags::Gameplay_FieldOfView));
	}
}
C++

Switch the theme, preset, layout, high contrast or reduced motion for every player; open screens restyle in place and a screen switching layout keeps its category, focused row and waiting changes:

#include "Templates/RollySettingsCoreUILayouts.h"
#include "Theme/RollySettingsCoreUIPresets.h"
#include "Theme/RollySettingsCoreUIThemeSubsystem.h"

void UMyOptions::UseCouchLook(bool bHighContrast)
{
	if (URollySettingsCoreUIThemeSubsystem* Themes = URollySettingsCoreUIThemeSubsystem::Get())
	{
		Themes->SetPreset(FRollySettingsCoreUIPresets::Neon); // or SetTheme(MyThemeAsset); null goes back to Project Settings
		Themes->SetLayout(FRollySettingsCoreUILayouts::Hub);  // Large density comes with the hub unless one is chosen
		Themes->SetHighContrast(bHighContrast);
	}
}
C++

The look every installed Rolly product shares lives in three console variables (see Themes); set them from C++ at the players’ priority, which the console and ConsoleVariables.ini still beat:

#include "Shared/RollySettingsCoreSharedChannel.h"

void UMyAccessibilityMenu::ApplyChoices(bool bHighContrast, bool bStill, const FString& ThemeId)
{
	FRollySettingsCoreSharedChannel::SetHighContrast(bHighContrast);    // rolly.ui.contrast
	FRollySettingsCoreSharedChannel::SetMotionScale(bStill ? 0.0f : 1.0f); // rolly.ui.motion
	FRollySettingsCoreSharedChannel::SetThemeValue(ThemeId);            // rolly.ui.theme: "Preset:Paper", an asset path, or empty
}
C++

Place the screens in a panel of your HUD instead of the game viewport (Blueprint: Set Host Panel on the player’s Rolly Settings Core UI Stack Subsystem); every Rolly product can share that panel:

if (URollySettingsCoreUIStackSubsystem* Stack = URollySettingsCoreUIStackSubsystem::Get(LocalPlayer))
{
	Stack->SetHostPanel(MyHud->ScreensOverlay); // null goes back to the game viewport
}
C++

A screen of your own gets focus, the player’s input, Back and the pause from the stack, and its Rolly widgets follow the theme:

#include "Screens/RollySettingsCoreUIScreen.h"
#include "Widgets/RollySettingsCoreUIText.h"
#include "MyCreditsScreen.generated.h"

UCLASS()
class UMyCreditsScreen : public URollySettingsCoreUIScreen
{
	GENERATED_BODY()

protected:
	// Runs only when no Blueprint layout replaces the tree.
	virtual void BuildDefaultTree() override
	{
		URollySettingsCoreUIText* Title = MakePart<URollySettingsCoreUIText>(TEXT("TitleText"));
		Title->SetRoles(ERollySettingsCoreUITextRole::Display, ERollySettingsCoreUIColorRole::Text);
		Title->SetText(NSLOCTEXT("MyGame", "CreditsTitle", "Credits"));
		WidgetTree->RootWidget = Title;
	}
};

// Opening it for a player (#include "Stack/RollySettingsCoreUIStackSubsystem.h"):
if (URollySettingsCoreUIStackSubsystem* Stack = URollySettingsCoreUIStackSubsystem::Get(LocalPlayer))
{
	Stack->PushScreen(UMyCreditsScreen::StaticClass());
}
C++

A setting kind of your own shows with a row of your own once Row Classes names it, with no change to the plugin:

// A kind (in your runtime module): a line of text the player types elsewhere.
UCLASS(meta = (DisplayName = "Note"))
class UMyNoteSetting : public URollySetting
{
	GENERATED_BODY()
public:
	virtual bool NormalizeValue(const FString& InValue, TConstArrayView<FRollySettingOption> Options, FString& OutValue) const override { OutValue = InValue; return true; }
	virtual FText GetDisplayText(const FString& Value, TConstArrayView<FRollySettingOption> Options) const override { return FText::FromString(Value); }
	virtual FText GetKindName() const override { return NSLOCTEXT("MyGame", "NoteKind", "Note"); }
};

// Its row (in your UI module): BuildValueWidget makes the value's part, RefreshValue shows GetValueText().
UCLASS()
class UMyNoteRow : public URollySettingsSettingRow
{
	GENERATED_BODY()
};

// Then in Project Settings > Plugins > Rolly Settings Screen > Row Classes: My Note Setting -> My Note Row.
C++

A widget with parts that are not Rolly widgets overrides ApplyStyle(const FRollySettingsCoreUIStyle& Style) and sets them from roles, for example Style.Color(ERollySettingsCoreUIColorRole::Surface) and Style.Font(ERollySettingsCoreUITextRole::Title): it runs before the widget shows and again on every theme change. The classes to start from: URollySettingsCoreUIScreen (screens), URollySettingsCoreUIDialog (dialog layouts), URollySettingsRow and the rows of each kind (rows of the settings screen), URollySettingsCoreUIUserWidget (any widget that follows the theme), and IRollySettingsCoreUIPresenter and IRollySettingsCoreUIInputHandler (hosting and input policies of your own). Their headers document every function.

Testing

Automation tests: Rolly.Settings.* (the settings screen: Rolly.Settings.UI.*), and RollySettingsCore.* for the shared foundation and the design system (RollySettingsCore.UI.*). Run them in the editor from Tools > Session Frontend > Automation (filter Rolly), or headless with UnrealEditor-Cmd.exe <YourProject>.uproject -ExecCmds="Automation RunTests Rolly; Quit" -unattended -nullrhi. They build their collections in code, use test tags under Rolly.Settings.Test, run two local players without Play In Editor, write files only under Saved/Automation/Tmp (and a test key file, below), and restore Project Settings and the theme afterwards. Tests that apply built-in bindings record the engine values first and put them back at the end (FRollySettingsScopedEngineState), and they never save GameUserSettings.ini. Headless runs have no display, audio device or HDR, so they check the values the bindings hand to the engine; how a mode, a volume or a colour correction looks is checked in a packaged build. The controls tests build their input actions and mapping contexts in code, give each player a controller, and save keys only to the test slot RollySettingsAutomationKeys (and _1 to _3) in Saved/SaveGames, which they delete before and after; the device tests use a fake device lookup and, for one simulated pad, the engine’s simulated device descriptors (development builds only), and never register a real device. The screen tests show each player’s screen host in a virtual window and press keys through a virtual Slate user, as a player would; they never open a window or touch the editor’s own focus. Rolly.Settings.UI.Screenshots.Screens renders the settings screen (every tab, a pad’s prompts, high contrast, split screen), its dialogs and key capture to PNG files when the run can render, .Templates every layout at 1920 x 1080, at 1280 x 800, 2560 x 1080 and 3840 x 1080 and in a 2- and 4-player split, .Presets every theme preset with its contrast measured in the picture (names, focus, an inactive chevron and a dimmed prompt’s words), and .Matrix every layout at the design’s reference sizes R1 to R9, checking in every run that Back and Apply show inside the area, that exactly one thing shows focus and shows whole (not cut by a list too short for it), and that the header, navigation, list, detail and footer stay apart and inside the area (its pictures, 50_*, come in runs that render); RollySettingsCore.UI.Screenshots.StateSheet renders every row and button state with a greyscale copy. rolly test Rolly.Settings.UI.Screenshots rhi in the repository (or -RenderOffScreen instead of -nullrhi) writes them to the report folder’s Screenshots folder; a -nullrhi run skips them. Key caps must sit level with their words (the footer prompts, the tab keys, the key capture’s prompt), row names with their values, and dialog buttons must centre their labels: Rolly.Settings.UI.Look.Alignment checks this from the layout in every run, and the screenshot run checks the prompts and tab keys again in the rendered pictures.

Dependencies (Fab Technical Information)

Engine modules: Core, CoreUObject, Engine, ApplicationCore, DeveloperSettings, EnhancedInput, GameplayTags, InputCore, RenderCore, RHI, Slate, SlateCore, UMG (and in the editor: UnrealEd, AssetDefinition, AssetRegistry, AssetTools, ContentBrowser, EditorSubsystem, ImageCore, MessageLog, Projects, PropertyEditor, ToolMenus, UMGEditor). Engine plugins: Enhanced Input (enabled by default; the plugin descriptor enables it). With the Data Validation plugin enabled (the default), saving a collection or a theme runs its checks. No other user-made plugin is required: the shared foundation code, the Rolly UI design system included, ships inside the plugin.

Known limits of this version

  • Screens: the theme preview window is driven by the keyboard and mouse; gamepad input in editor windows was not verified. Interface Theme is a recipe, not a built-in setting. Screens of several Rolly products share the game’s input and pause, but each product keeps its own screen stack: Back reaches the top screen of the product whose screen has focus. Layouts are laid out for left-to-right languages; right-to-left languages were not checked. Touch is covered by the automated tests with simulated fingers; the layouts were not yet tried on a phone or tablet, where the platform’s DPI scale decides the area a layout gets. High Contrast Interface and Reduce Motion follow the system’s preferences on Windows only; elsewhere they start off.
  • Common UI: the screens do not use Common UI’s bound actions or activatable widgets; a presenter (C++) puts them into a Common UI layer (see Common UI or your own layers).
  • On desktop, a player’s saved values follow the controller slot, not the person.
  • Keys: buttons and keys only (no stick, trigger or mouse axis as a new key); a key cannot be removed, only replaced; rows with an axis or with several keys under one name are read-only; only the active key profile is shown (no profile switching); keys the game adds per platform through Enhanced Input’s platform settings do not appear in the rows. Changes made in the key list take effect and are saved at once, outside Apply, Discard Pending Changes and Revert.
  • Split-screen on PC needs Rolly Settings Player Input (see Controls), or players share one key file.
  • Prompts: on Windows, with the engine’s default plugins, only XInput pads are identified (as Xbox): a PlayStation pad through Steam Input looks like an Xbox pad, and one without Steam Input needs the engine’s Windows DualShock plugin with Sony’s library. The Controller Prompts setting lets the player choose. Moving a stick less than Gamepad Analog Switch Threshold does not switch the prompts, and neither does connecting a pad.
  • Not yet checked on real hardware or in a packaged build: device switching with real pads (stick drift, a pad connected at start, Steam Input), split-screen with two pads, and the look modifiers in a running game. The automated tests cover the rules with simulated input.
  • Brightness follows the default Filmic tonemapper: it has no effect on scenes whose post process uses the Standard ACES tonemapper, and in SDR it brightens the interface as well. In HDR use HDR Brightness instead (the library hides Brightness while HDR is on).
  • Colour vision correction is not available on iOS and Android (the engine skips it there), so the library hides it.
  • VSync has no visible effect in Play In Editor; Frame Rate Limit is offered on desktop platforms only; HDR needs Project Settings > Rendering > Allow HDR Display Output (or -hdr) and an HDR display; Monitor needs two monitors or more.
  • Music, Effects and Voice change the engine’s Music, SFX and Voice sound classes, which affect only sounds that use them (or a child class). Pick your project’s classes in the bindings if its sounds use others. Master Volume affects everything.
  • Master Volume sets the main output volume of the audio device, which the engine does not let anyone read back. When a game ends, the device gets back the volume Rolly Settings knew before it (see Play In Editor); a main volume your own code set through the engine directly is not known, and full volume comes back instead.
  • The built-in library does not put its defaults into engine-saved values on a fresh install; a collection of your own does (see Values and flows).
  • A project GameUserSettings subclass that turns scalability settings off (bEnableScalabilitySettings) makes the engine ignore the quality levels.
  • Auto-Detect runs the engine’s hardware test on the game thread, a short pause: offer it in a menu, not during play.
  • Resolution in exclusive fullscreen offers the modes the graphics card reports for the chosen monitor. On Windows, for a monitor driven by another graphics card, the engine reports only its desktop size.
  • Not yet checked in a packaged build: the window itself after a quit or a crash during a display confirmation. The automated tests cover the saved values and their recovery.