UI Toolbox logoUI Toolbox

Custom settings panels (SettingsPanel)

GraphicsSettingsPanel, AudioSettingsPanel and InputSettingsPanel share the base SettingsPanel<T>. Use it for a settings screen of your game, for example difficulty or accessibility options.

The base has these members:

Member Description
Editing The options that the body edits.
Applied The options of the last Apply, or the saved options.
IsDirty True when Editing differs from Applied. Apply and Revert are enabled only then.
ApplyAsync() Sets Editing on the game and saves it. True when the edits stay.
Revert(), Defaults() Sets Editing to Applied, or to DefaultOptions().
PrefsKey (prefs-key) The PlayerPrefs key. The panel loads the saved options on the first attach. Empty: Apply does not save.
ShowButtons (show-buttons) False hides the buttons, for a larger settings screen with its own buttons that call the methods.

How to make a panel:

  1. Make a [Serializable] subclass of SettingsOptions with public fields. Use the PropertyGrid attributes: [Category], [Range], [Description], [InspectorName], [EnabledIf].
  2. Make a [UxmlElement] partial subclass of SettingsPanel<T>.
  3. Override Capture() (the values in effect now), DefaultOptions() and ApplyOptions(options).
  4. Call AddGrid() in the constructor for a PropertyGrid of Editing.
[Serializable]
public class GameplayOptions : SettingsOptions
{
    public static GameplayOptions Current = new();

    [Category("Gameplay"), Range(0, 2), Description("0: easy, 2: hard.")]
    public int Difficulty = 1;

    [Category("Gameplay"), InspectorName("Show hints")]
    public bool ShowHints = true;
}

[UxmlElement]
public partial class GameplaySettingsPanel : SettingsPanel<GameplayOptions>
{
    public GameplaySettingsPanel() : base("mygame.gameplay") => AddGrid();

    protected override GameplayOptions Capture() => (GameplayOptions)GameplayOptions.Current.Clone();
    protected override GameplayOptions DefaultOptions() => new();
    protected override void ApplyOptions(GameplayOptions options) => options.CopyTo(GameplayOptions.Current);
}

Tips:

Styling

Class Element
tb-settings-panel The panel, on every SettingsPanel. It grows to fill its parent.
tb-graphics-settings Also on a GraphicsSettingsPanel.
tb-audio-settings Also on an AudioSettingsPanel.
tb-input-settings Also on an InputSettingsPanel.
tb-input-settings__header The title row of an InputSettingsPanel: Action, Keyboard and mouse, Gamepad. Bold muted text and a bottom border.
tb-input-settings__rows The ScrollView of the action rows.
tb-input-settings__map The title of an action map, when the asset has more than one map. Bold, on --tb-color-surface-alt.
tb-input-settings__row The row of one action.
tb-input-settings__action The action name, 120 px wide. Also on the first header label.
tb-input-settings__key The cell of a KeyBindingField. The two cells share the width that is left. Also on the two column header labels.
tb-input-settings__key--none On a cell without a field: the action has no binding for that device.
tb-settings-panel__body The body with the PropertyGrid. Its flex basis is 0, so it scrolls in a short panel. Its minimum height is 120 px, so some rows show when the parent does not grow.
tb-settings-panel__buttons The row of the Defaults, Revert and Apply buttons, on the right. The buttons have the look of the MessageBox buttons.