Adding new Settings: Difference between revisions

From PMDOWiki
MistressNebula (talk | contribs)
m Added TOC limit + small introduction changes
MistressNebula (talk | contribs)
Remove references, add example
Line 1: Line 1:
Version 0.8.4 contained a heavy rework of the Settings menu. The new menu supports multiple pages of settings, and allows modders to add new pages at will thanks to the [[Service Callbacks#AddMenu|AddMenu]] service callback. Please refer to the [[Editing Menus#Prerequisites]] section to know how to interact with menus using this callback.
Version 0.8.4 contained a heavy rework of the Settings menu. The new menu supports multiple pages of settings, and allows modders to add new pages at will thanks to the [[Service Callbacks#AddMenu|AddMenu]] service callback. Please refer to the [[Editing Menus#Prerequisites]] section to know how to interact with menus using this callback.


The settings menu's label is literally just <code>"SETTINGS_MENU"</code>. Keep in mind that this retrieves the label of the settings menu's TITLE window. The actual settings pages have no label, and are supposed to be populated using the functions described in this page.
The label we need is literally just <code>"SETTINGS_MENU"</code>. Keep in mind that this is the label of the settings menu TITLE window. The actual settings pages have no label, and are supposed to be populated indirectly thanks to the functions described in this page.


Despite the menu being technically an InteractableMenu, using any function described in the Editing Menus page is highly discouraged, with the sole exception of the ILabeled functions.
Despite the menu being technically an InteractableMenu, using any function described in the Editing Menus page is highly discouraged, with the ILabeled functions being the only exception.


That said, adding new settings is very simple: just call <code>SettingsTitleMenu:NewPage</code> and then register new settings with <code>SettingsPage:AddSetting</code>.
Feel free to visit the [[Settings Menu Reference]] page for a more in-depth explanation of all of the functions and values provided by the settings engine specifically.


{|limit=2
== Making a new settings page ==
  |__TOC__
That said, adding new settings is very simple. Call <code>SettingsTitleMenu:NewPage</code>, and then register new settings with <code>SettingsPage:AddSetting</code>, like this:
  |}


== SettingsTitleMenu ==
<pre>
This is the menu included in the AddMenu callback as argument.
if menu:HasLabel() and menu.Label == labels.SETTINGS_MENU and menu.InGame then
    local page = menu:AddPage("my_namespace", "My Mod")


=== SettingsTitleMenu:HasPage(System.String) ===
    local options = {"Off", 1, 2, 3, 4, 5}
Returns <code>true</code> if a SettingsPage is already associated with the provided key, <code>false</code> otherwise.
    local saveFunction = function(setting) SV.MySetting = setting.CurrentChoice end
    local choiceChangedFunction = function(setting) PrintInfo("MySetting preview: "..setting.CurrentChoice) end
    page:AddSetting("My Setting", options, SV.MySetting or 0, saveFunction, choiceChangedFunction)


====Arguments====
    page.GlobalSaveAction = function() PrintInfo("SV.MySetting has been set to "..SV.MySetting) end
* <code>key</code> the unique id key to test for.
end
</pre>


Of course, the code has something more going on, so let's check that out in more detail:
The first thing we need to do is, of course, to make sure that we're editing the right menu. Then we check if we're in game or not. Making a setting work from the Top Menu requires a bit more work than what is shown here, so we're going avoid that entirely for now.


The first step now is to create a [[Settings Menu Reference#SettingsPage|SettingsPage]] and store it in a variable. Then we prepare the structures we need for our setting: a list of options and a function that saves our settings when the player presses the confirm button. Since this is a demonstration, we will also include a function that runs every time the setting's value change, even though it is both optional and not necessary here.


=== SettingsTitleMenu:AddPage(System.String, System.String) ===
Finally, we create our settings, giving it also a display name and using its previous value (or, in this case, 0 if there wasn't one yet) as the starting choice for the setting. This default value is a 0-based index, so, for this setting, valid values go from 0 to 5.
Creates and returns a new SettingsPage object, assigning it to a key and giving it a title.
Using a key that already exixts results in an error.
It is recommended to always use a mod's namespace as either the prefix of a page's key or the key itself. This will minimize conflicts and ensure that multiple pages for the same mod stay as close together as possible. Good examples are: <code>my_namespace</code>, <code>my_namespace_general</code>, <code>my_namespace_qol</code>.


====Arguments====
Finally, the last line registers a special function that is ran at the end of every other save actions in the page when the player confirms their changes. This is also optional, and it's included here simply for demonstration.
* <code>key</code> the unique id key of the newly created page.
* <code>title</code> the localized display title of the page.


Notice how the saveFunction and the choiceChangedFunction both accept an argument. This is because the engine always passes the [https://github.com/RogueCollab/RogueEssence/tree/master/RogueEssence/Menu/MenuElements/MenuSetting.cs MenuSetting] in question to our function. In almost all cases, all we are interested in doing is store its <code> CurrentChoice</code> value somewhere in our code, but it IS technically possible to tamper with any of the object's <code>public</code> properties and fields.


 
== Top Menu settings ==
== SettingsPage ==
WIP
This object is what gets returned by <code>SettingsTitleMenu:AddPage</code>. This is the object that actually allows the user to add new settings to the game.
 
=== SettingsPage.GlobalSaveAction ===
This property is an Action; a function that takes no parameters and returns nothing. If set, it is called after all of the settings' SaveActions have been ran. PMDO uses this in its original page to bring the player back to the top menu if the language setting has been edited.
 
 
 
=== SettingsPage.AddSetting(System.String, NLua.LuaTable, System.Int32, System.Action<RogueEssence.Menu.MenuSetting>, System.Action<RogueEssence.Menu.MenuSetting>) ===
This function registers a new setting, giving it a name, a list of state, a starting position and some special callbacks.
 
==== Arguments ====
* <code>name</code> the localized display name of the setting.
* <code>options</code> a table containing a list of strings. Each string is one of the possible displayed values of the setting.
* <code>defaultValue</code> the option this setting will show as its starting value. It must be a number between 0 and <code>#options-1</code>.
* <code>action</code> the function that will be called when the player presses the confirm button. It will have its corresponding [https://github.com/RogueCollab/RogueEssence/blob/master/RogueEssence/Menu/MenuElements/MenuSetting.cs MenuSetting] passed to it, so that you can access its CurrentChoice parameter and use it to actually update whatever value this setting represents.
* <code>settingChangedAction</code> the function that will be called whenever the player changes the value of this specific setting. Useful to display changes immediately. PMDO uses this in its original page to temporarily change the window borders without actually saving the setting. It will have its corresponding MenuSetting passed to it, so that you can access its CurrentChoice parameter and use it to actually update whatever temporary value this setting is tied to. Defaults to <code>nil</code>.

Revision as of 10:29, 27 August 2024

Version 0.8.4 contained a heavy rework of the Settings menu. The new menu supports multiple pages of settings, and allows modders to add new pages at will thanks to the AddMenu service callback. Please refer to the Editing Menus#Prerequisites section to know how to interact with menus using this callback.

The label we need is literally just "SETTINGS_MENU". Keep in mind that this is the label of the settings menu TITLE window. The actual settings pages have no label, and are supposed to be populated indirectly thanks to the functions described in this page.

Despite the menu being technically an InteractableMenu, using any function described in the Editing Menus page is highly discouraged, with the ILabeled functions being the only exception.

Feel free to visit the Settings Menu Reference page for a more in-depth explanation of all of the functions and values provided by the settings engine specifically.

Making a new settings page

That said, adding new settings is very simple. Call SettingsTitleMenu:NewPage, and then register new settings with SettingsPage:AddSetting, like this:

if menu:HasLabel() and menu.Label == labels.SETTINGS_MENU and menu.InGame then
    local page = menu:AddPage("my_namespace", "My Mod")

    local options = {"Off", 1, 2, 3, 4, 5}
    local saveFunction = function(setting) SV.MySetting = setting.CurrentChoice end
    local choiceChangedFunction = function(setting) PrintInfo("MySetting preview: "..setting.CurrentChoice) end
    page:AddSetting("My Setting", options, SV.MySetting or 0, saveFunction, choiceChangedFunction)

    page.GlobalSaveAction = function() PrintInfo("SV.MySetting has been set to "..SV.MySetting) end
end

Of course, the code has something more going on, so let's check that out in more detail: The first thing we need to do is, of course, to make sure that we're editing the right menu. Then we check if we're in game or not. Making a setting work from the Top Menu requires a bit more work than what is shown here, so we're going avoid that entirely for now.

The first step now is to create a SettingsPage and store it in a variable. Then we prepare the structures we need for our setting: a list of options and a function that saves our settings when the player presses the confirm button. Since this is a demonstration, we will also include a function that runs every time the setting's value change, even though it is both optional and not necessary here.

Finally, we create our settings, giving it also a display name and using its previous value (or, in this case, 0 if there wasn't one yet) as the starting choice for the setting. This default value is a 0-based index, so, for this setting, valid values go from 0 to 5.

Finally, the last line registers a special function that is ran at the end of every other save actions in the page when the player confirms their changes. This is also optional, and it's included here simply for demonstration.

Notice how the saveFunction and the choiceChangedFunction both accept an argument. This is because the engine always passes the MenuSetting in question to our function. In almost all cases, all we are interested in doing is store its CurrentChoice value somewhere in our code, but it IS technically possible to tamper with any of the object's public properties and fields.

Top Menu settings

WIP