Skip to content

Menu Creation

UrFriendKen edited this page Sep 27, 2025 · 12 revisions

Creating The Menu

Setup

Instantiate and cache a static instance of PreferenceSystemManager in void PostActivate(KitchenMods.Mod mod), passing MOD_GUID and MOD_NAME in the constructor.

static PreferenceSystemManager PrefManager;

public void PostActivate(KitchenMods.Mod mod)
{
    PrefManager = new PreferenceSystemManager(MOD_GUID, MOD_NAME);
}

If using KitchenLib, you can do it in Mod.OnPostActivate(KitchenMods.Mod mod) instead.

static PreferenceSystemManager PrefManager;

protected override void OnPostActivate(KitchenMods.Mod mod)
{
    PrefManager = new PreferenceSystemManager(MOD_GUID, MOD_NAME);
}

Available Elements

Simple Elements

PreferenceSystemManager contains standard elements including:

public PreferenceSystemManager AddLabel(string text);
public PreferenceSystemManager AddInfo(string text);
public PreferenceSystemManager AddSelect(List<string> options, Action<int> on_activate, int index = 0);
public PreferenceSystemManager AddButton(string button_text, Action<int> on_activate, int arg = 0, float scale = 1f, float padding = 0.2f);
public PreferenceSystemManager AddPlayerRow(string username, PlayerInfo player, Action<int> on_kick, Action<int> on_remove, int arg = 0, float scale = 1f, float padding = 0.2f);
public PreferenceSystemManager AddActionButton(string button_text, MenuAction action, ElementStyle style = ElementStyle.Default);
public PreferenceSystemManager AddSpacer();

Preference Option

To add a preference option:

public PreferenceSystemManager AddOption<T>(string key, T initialValue, T[] values, string[] strings);

Alternatively, you can create properties instead of options if you do not want the preference to be modified by the user.

public PreferenceSystemManager AddProperty<T>(string key, T initialValue, bool doLoad = false);

Optional parameter doLoad needs to be set to true if and only if you are doing AddProperty after running RegisterMenu. Otherwise, leave it as default. If you fail to do so, properties you have registered will not be properly loaded after the game is restarted.

Currently supported preference types are

  • bool
  • int
  • float
  • string

Preference Profiles

Profiles are now supported after KitchenLib Beta v0.5.2. To add a profile selector:

public PreferenceSystemManager AddProfileSelector();

Submenu

To start a new submenu:

public PreferenceSystemManager AddSubmenu(string button_text, string submenu_key, bool skip_stack = false);

When done with the submenu call:

public PreferenceSystemManager SubmenuDone();

If you want to point the submenu button to a custom menu you have declared separately instead:

public PreferenceSystemManager AddSelfRegisteredSubmenu<TMain, TPause>(string button_text, bool skip_stack = false) where TMain : Menu<MainMenuAction> where TPause : Menu<PauseMenuAction>

You will need to register the menus instances into GameData yourself, perhaps with KitchenLib.Event Events

Conditionally Hide Menu Elements

Begin a conditional block with:

public PreferenceSystemManager AddConditionalBlocker(Func<bool> shouldBlock);

End the block with:

public PreferenceSystemManager ConditionalBlockerDone();

All elements within the block will be hidden or visible depending on the return value of the shouldBlock function you define. Conditional blocks can be nested if desired.

Showing different preferences to host and client

To simplify conditional blocking based on host status:

public PreferenceSystemManager AddHostStatusConditionalBlocker(bool block_if_host = false, bool block_if_client = true)

By default, all elements within the block will be hidden for clients and visible for the host. You can change the default parameters to alter this behavior. Then similarly, end the block with:

public PreferenceSystemManager ConditionalBlockerDone();

Adding Pagination

Only one page selector is allowed in each submenu. The page selector must be the first selectable element that is added.

public PreferenceSystemManager AddPageSelector(int maxItemsPerPage);

Before adding each item, start with:

public PreferenceSystemManager StartPagedItem();

End the paged item with:

public PreferenceSystemManager PagedItemDone();

You must end the previous paged item before starting another. Paged items are helpful when there are many items, or when used in a loop where the number of items is unknown at compile time.

For example:

PrefManager
    .Label("Title") // Non-selectable elements before is fine 
    .AddPageSelector(3);    // 3 items per page

    for (int i = 0; i < itemCount; i++)     // Loop for each item
    {
        PrefManager
            .StartPagedItem()   // A paged item can contain more than 1 element
                .AddLabel($"Item{i}")
                .AddInfo("This is a paged item description")
                .AddOption<int>($"PreferenceID{i}", intOptions, displayStrings)
            .PagedItemDone()
    }

You may use conditional hiding within paged items, if and only if, the entire conditional block is contained within the paged item.

Structure

The exact order depends on the how you want your menu to look. Here is an example.

PrefManager
    .AddLabel("Label")
    .AddInfo("Info")
    .AddSubmenu("Submenu 1", "Submenu1")
        .AddSubmenu("Nested Submenu", "NestedSubmenu")
        .AddOption<bool>("boolPreference", true, new bool[] { false, true }, new string[] { "Disabled", "Enabled" })
    .SubmenuDone()
    .AddSubmenu("Submenu 2", "Submenu2")
        .AddProfileSelector()
        .AddOption<int>("intPreference", 0, new int[] { 0, 1, 2 }, new string[] { "Option 0", "Option 1", "Option 2" })
    .SubmenuDone();

Registering the menu

For your menu to appear, you must register it. Depending on where you want your menu to appear, use the appropriate MenuType (MenuType.MainMenu or MenuType.PauseMenu).

public void RegisterMenu(MenuType menuType);

Call RegisterMenu twice, one for each MenuType if you want it to appear in both menus.

Full Menu Creation Example

The full code for mod creation should look something like this.

static PreferenceSystemManager PrefManager;

protected override void OnPostActivate(KitchenMods.Mod mod)
{
    PrefManager = new PreferenceSystemManager(MOD_GUID, MOD_NAME);
    PrefManager
        .AddLabel("Label")
        .AddInfo("Info")
        .AddSubmenu("Submenu 1", "Submenu1")
            .AddSubmenu("Nested Submenu", "NestedSubmenu")
            .AddOption<bool>("boolPreference", true, new bool[] { false, true }, new string[] { "Disabled", "Enabled" })
        .SubmenuDone()
        .AddSubmenu("Submenu 2", "Submenu2")
            .AddProfileSelector()
            .AddOption<int>("intPreference", 0, new int[] { 0, 1, 2 }, new string[] { "Option 0", "Option 1", "Option 2" })
        .SubmenuDone();

    PrefManager.RegisterMenu(PreferenceSystemManager.MenuType.MainMenu);
    PrefManager.RegisterMenu(PreferenceSystemManager.MenuType.PauseMenu);
}