Skip to content

Addon presets#1951

Open
MichalLabuda wants to merge 3 commits into
Return-To-The-Roots:masterfrom
MichalLabuda:addon-presets
Open

Addon presets#1951
MichalLabuda wants to merge 3 commits into
Return-To-The-Roots:masterfrom
MichalLabuda:addon-presets

Conversation

@MichalLabuda

@MichalLabuda MichalLabuda commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements addon preset save/load functionality, as requested in issue #665.
Closes #665
Players can now save their current addon configuration to a named .ini file and reload it later, instead of manually re-configuring addons each time.

Changes

  • New iwAddonPresets.h/.cpp - Two new dialog windows (iwSaveAddonPresetiwLoadAddonPreset) built on a shared base class (iwAddonPresetsBase). The dialogs show a sortable list of saved presets, a name edit field, and buttons for the primary action and deletion (with confirmation). Double-clicking a row triggers the action directly.
  • iwAddons - Added Save and Load buttons in a new button row above the existing Apply/Abort row. Window height increased from 500 to 530 px to accommodate the extra row. New applyAddonStates() method applies a loaded preset back into the GUI, respecting read-only addons and falling back to defaults for unknown/out-of-range values.
  • files.h - New folder constant addonPresets pointing to <RTTR_USERDATA>/PRESETS.
  • const_gui_ids.h - New CGI_ADDON_PRESETS GUI ID for the preset dialogs.

Presets are stored as .ini files (using libsiedler2) in <RTTR_USERDATA>/PRESETS/. The save dialog validates the name (strips path components, rejects Windows reserved device names, prompts before overwrite). Load validates the file format and falls back to addon defaults for any missing entries.


This PR probably also allows to solve issue #587, which reports that addon configurations configured while hosting a game are not preserved - players can now explicitly save a preset before a session and reload it next time.

Edit: Resolves #587


image

@Flamefire Flamefire left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thanks!
Just some questions

Comment thread libs/s25main/ingameWindows/iwAddonPresets.cpp Outdated
bfs::path iwSaveAddonPreset::GetSaveFilePath() const
{
std::string name = GetCtrl<ctrlEdit>(ID_edtName)->GetText();
name = bfs::path(name).filename().string();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the edit supposed to contain a name only? Then why the "detour" over a filepath?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intention is to disallow saving/loading from different paths. Now, it rejects slash and backslash with error message.

static constexpr std::array reservedNames{"con", "prn", "aux", "nul", "com1", "com2", "com3", "com4",
"com5", "com6", "com7", "com8", "com9", "lpt1", "lpt2", "lpt3",
"lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9"};
if(helpers::contains(reservedNames, s25util::toLower(filePath.stem().string())))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would makePortableName work?

@MichalLabuda MichalLabuda Jun 18, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea for handling file names was different from what makePortableName (makePortableFileName) does.
However, I could change this to use makePortableFileName and adjust the rest of the code accordingly - let me know.

We could (or more precisely you could ;-) ) also decide if makePortableName would benefit from adding those restrictions which I could implement.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, move it there, I'd say any of those names is not a portable name so should be handled there.

@MichalLabuda MichalLabuda requested a review from Flamefire June 22, 2026 14:07

void iwSaveAddonPreset::DoAction()
{
const std::string rawName = GetCtrl<ctrlEdit>(ID_edtName)->GetText();

@Flamefire Flamefire Jun 23, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this check not in GetSaveFilePath? Looks incomplete to get the name twice from (seemingly) different sources.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[wish] Add Addon presets Saving of addons/game settings

2 participants