mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-06-19 06:27:02 -04:00
add functionality for saving and loading presets
This commit is contained in:
@@ -490,6 +490,7 @@ window.modal.danger .modal-header icon {
|
||||
font-size: 20dp;
|
||||
color: #FFFFFF;
|
||||
font-weight: normal;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.modal-body span.tip {
|
||||
|
||||
@@ -86,6 +86,9 @@ namespace randomizer::seedgen::config
|
||||
}
|
||||
|
||||
auto& settings = this->_settingsList.front();
|
||||
settings.GetModifiableExcludedLocations().clear();
|
||||
settings.GetModifiableMixedEntrancePools().clear();
|
||||
settings.GetModifiableStartingInventory().clear();
|
||||
|
||||
// Load settings info
|
||||
auto settingInfoMap = settings::GetAllSettingsInfo();
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "modal.hpp"
|
||||
|
||||
#include "string_button.hpp"
|
||||
|
||||
namespace dusk::ui {
|
||||
|
||||
Modal::Modal(Props props) : WindowSmall("modal", "modal-dialog"), mProps(std::move(props)) {
|
||||
@@ -100,4 +102,35 @@ bool Modal::handle_nav_command(Rml::Event& event, NavCommand cmd) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TextInputModal::TextInputModal(Props props) : Modal(props) {
|
||||
auto modalBody = mDialog->QuerySelector(".modal-body");
|
||||
|
||||
mInput = std::make_unique<StringButton>(modalBody, StringButton::Props{
|
||||
.getValue = [this]{return mInputText;},
|
||||
.setValue = [this](Rml::String value) { mInputText = value; },
|
||||
});
|
||||
|
||||
mInput->start_editing();
|
||||
}
|
||||
|
||||
bool TextInputModal::handle_nav_command(Rml::Event& event, NavCommand cmd) {
|
||||
auto retVal = Modal::handle_nav_command(event, cmd);
|
||||
if (!retVal) {
|
||||
if (mInput->root()->IsPseudoClassSet("focus") && cmd == NavCommand::Down) {
|
||||
mButtons[0]->focus();
|
||||
retVal = true;
|
||||
} else if (!mInput->root()->IsPseudoClassSet("focus") && cmd == NavCommand::Up) {
|
||||
mInput->focus();
|
||||
retVal = true;
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void TextInputModal::update() {
|
||||
mInput->update();
|
||||
Document::update();
|
||||
}
|
||||
|
||||
} // namespace dusk::ui
|
||||
|
||||
+16
-2
@@ -31,12 +31,26 @@ public:
|
||||
|
||||
protected:
|
||||
bool handle_nav_command(Rml::Event& event, NavCommand cmd) override;
|
||||
|
||||
private:
|
||||
void dismiss();
|
||||
|
||||
Props mProps;
|
||||
std::vector<std::unique_ptr<Button> > mButtons;
|
||||
};
|
||||
|
||||
class StringButton;
|
||||
|
||||
class TextInputModal : public Modal {
|
||||
public:
|
||||
explicit TextInputModal(Props props);
|
||||
|
||||
Rml::String get_input_text() {return mInputText;}
|
||||
void update() override;
|
||||
|
||||
protected:
|
||||
bool handle_nav_command(Rml::Event& event, NavCommand cmd) override;
|
||||
private:
|
||||
std::unique_ptr<StringButton> mInput{};
|
||||
Rml::String mInputText{};
|
||||
};
|
||||
|
||||
} // namespace dusk::ui
|
||||
|
||||
@@ -652,14 +652,11 @@ void RandomizerWindow::rando_excluded_locations_update_left_pane(Pane& innerLeft
|
||||
|
||||
// Focus the closest child in the next Pane. Returns true if a child was found to focus
|
||||
bool focus_closest_child_on_next_pane(Pane& currentPane, Pane& nextPane) {
|
||||
|
||||
auto childToFocusY = currentPane.get_focused_child_y();
|
||||
return nextPane.focus_closest_child(childToFocusY);
|
||||
|
||||
}
|
||||
|
||||
void delete_seed_callback(Pane& pane) {
|
||||
|
||||
// Get the Y position to focus the child nearest to after we rebuild this pane
|
||||
auto childToFocusY = pane.get_focused_child_y();
|
||||
|
||||
@@ -688,7 +685,6 @@ void delete_seed_callback(Pane& pane) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: our ui lib doesnt have an easy way to either refresh or remove values from the right pane
|
||||
pane.add_button(
|
||||
{
|
||||
.text = hash,
|
||||
@@ -713,6 +709,9 @@ RandomizerWindow::RandomizerWindow(dFile_select_c* fileSelect /*= nullptr*/) : m
|
||||
if (!std::filesystem::exists(GetRandomizerSeedsPath())) {
|
||||
std::filesystem::create_directories(GetRandomizerSeedsPath());
|
||||
}
|
||||
if (!std::filesystem::exists(GetRandomizerPresetsPath())) {
|
||||
std::filesystem::create_directories(GetRandomizerPresetsPath());
|
||||
}
|
||||
|
||||
// If we're bringing this menu up during file selection
|
||||
if (mFileSelectMenu) {
|
||||
@@ -823,6 +822,58 @@ RandomizerWindow::RandomizerWindow(dFile_select_c* fileSelect /*= nullptr*/) : m
|
||||
leftPane.add_button("Delete Seeds"),
|
||||
rightPane, delete_seed_callback
|
||||
);
|
||||
|
||||
leftPane.add_section("Presets");
|
||||
leftPane.register_control(
|
||||
leftPane.add_button("Save Current Settings as Preset")
|
||||
.on_pressed([] {
|
||||
push_document(std::make_unique<TextInputModal>(Modal::Props{
|
||||
.title = "Preset Name",
|
||||
.bodyRml = "",
|
||||
.actions = {
|
||||
ModalAction{
|
||||
.label = "Save",
|
||||
.onPressed = [](Modal& modal) {
|
||||
auto textModal = dynamic_cast<TextInputModal*>(&modal);
|
||||
if (!textModal->get_input_text().empty()) {
|
||||
modal.pop();
|
||||
SaveNewRandomizerPreset(textModal->get_input_text());
|
||||
}
|
||||
},
|
||||
},
|
||||
ModalAction{
|
||||
.label = "Cancel",
|
||||
.onPressed = [](Modal& modal) {
|
||||
modal.pop();
|
||||
},
|
||||
},
|
||||
},
|
||||
.icon = "information"
|
||||
}));
|
||||
|
||||
}),
|
||||
rightPane, [](Pane& pane) {
|
||||
pane.clear();
|
||||
pane.add_text("Save the current settings to your list of presets.");
|
||||
});
|
||||
|
||||
leftPane.register_control(
|
||||
leftPane.add_button("Load Preset"),
|
||||
rightPane, [](Pane& pane) {
|
||||
pane.clear();
|
||||
pane.add_text("Choose an existing preset to load from.");
|
||||
|
||||
for (const auto& file : std::filesystem::directory_iterator{GetRandomizerPresetsPath()}) {
|
||||
const auto& filepath = file.path();
|
||||
auto presetName = file.path().stem().generic_string();
|
||||
pane.add_button(ControlledButton::Props{
|
||||
.text = presetName,
|
||||
})
|
||||
.on_pressed([filepath] {
|
||||
ApplyExistingRandomizerPreset(filepath);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
add_tab("Seed Options", [this](Rml::Element* content) {
|
||||
@@ -1168,6 +1219,90 @@ bool FileSelectRandomizerWindow::consume_close_request() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void SaveNewRandomizerPreset(const std::string& presetName, bool overwriteExisting /*= false*/) {
|
||||
auto presetFilepath = GetRandomizerPresetsPath() / (presetName + ".yaml");
|
||||
|
||||
// If the preset exists, ask the user if they want to overwrite it. If so, call this function
|
||||
// again but force overwrite the existing preset
|
||||
if (std::filesystem::exists(presetFilepath) && !overwriteExisting) {
|
||||
push_document(std::make_unique<Modal>(Modal::Props{
|
||||
.title = "Overwrite Existing Preset",
|
||||
.bodyRml = "A preset with the name " + presetName + " already exists. Do you wish to overwrite it?",
|
||||
.actions = {
|
||||
ModalAction{
|
||||
.label = "Yes",
|
||||
.onPressed = [presetName](Modal& modal) {
|
||||
modal.pop();
|
||||
SaveNewRandomizerPreset(presetName, true);
|
||||
}
|
||||
},
|
||||
ModalAction{
|
||||
.label = "No",
|
||||
.onPressed = [](Modal& modal) {
|
||||
modal.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
// If there was an error trying to save, let the user know
|
||||
try {
|
||||
GetRandomizerConfig().WriteSettingsToFile(presetFilepath);
|
||||
} catch (std::exception& e) {
|
||||
auto modal = dynamic_cast<Modal*>(&push_document(std::make_unique<Modal>(Modal::Props{
|
||||
.title = "Error Saving Preset",
|
||||
.bodyRml = fmt::format("Error: {}", e.what()),
|
||||
.actions = {
|
||||
ModalAction{
|
||||
.label = "Okay",
|
||||
.onPressed = [](Modal& modal) {
|
||||
modal.pop();
|
||||
}
|
||||
}
|
||||
},
|
||||
.icon = "error"
|
||||
})));
|
||||
return;
|
||||
}
|
||||
|
||||
push_toast(Toast{
|
||||
.title = "",
|
||||
.content = fmt::format("Saved preset {}", presetName),
|
||||
.duration = std::chrono::seconds(3)
|
||||
});
|
||||
}
|
||||
|
||||
void ApplyExistingRandomizerPreset(const std::filesystem::path& presetFilePath) {
|
||||
// Don't overwrite the seed with the one from the preset
|
||||
auto seed = GetRandomizerConfig().GetSeed();
|
||||
try {
|
||||
GetRandomizerConfig().LoadFromFile(presetFilePath, GetRandomizerPreferencesPath(), false, false);
|
||||
GetRandomizerConfig().SetSeed(seed);
|
||||
} catch (std::exception& e) {
|
||||
auto modal = dynamic_cast<Modal*>(&push_document(std::make_unique<Modal>(Modal::Props{
|
||||
.title = "Error Loading Preset",
|
||||
.bodyRml = fmt::format("Error: {}", e.what()),
|
||||
.actions = {
|
||||
ModalAction{
|
||||
.label = "Okay",
|
||||
.onPressed = [](Modal& modal) {
|
||||
modal.pop();
|
||||
}
|
||||
}
|
||||
},
|
||||
.icon = "error"
|
||||
})));
|
||||
return;
|
||||
}
|
||||
|
||||
push_toast(Toast{
|
||||
.title = "",
|
||||
.content = fmt::format("Loaded preset {}", presetFilePath.stem().generic_string()),
|
||||
.duration = std::chrono::seconds(3)
|
||||
});
|
||||
}
|
||||
|
||||
std::filesystem::path GetRandomizerPath() {
|
||||
return data::configured_data_path() / "randomizer";
|
||||
}
|
||||
@@ -1180,6 +1315,10 @@ std::filesystem::path GetRandomizerPreferencesPath() {
|
||||
return GetRandomizerPath() / "preferences.yaml";
|
||||
}
|
||||
|
||||
std::filesystem::path GetRandomizerPresetsPath() {
|
||||
return GetRandomizerPath() / "presets";
|
||||
}
|
||||
|
||||
std::filesystem::path GetRandomizerSeedsPath() {
|
||||
return GetRandomizerPath() / "seeds";
|
||||
}
|
||||
|
||||
@@ -10,10 +10,13 @@ class dFile_select_c;
|
||||
namespace dusk::ui {
|
||||
class Pane;
|
||||
|
||||
void SaveNewRandomizerPreset(const std::string& presetName, bool overwriteExisting = false);
|
||||
void ApplyExistingRandomizerPreset(const std::filesystem::path& presetFilePath);
|
||||
std::filesystem::path GetRandomizerPath();
|
||||
std::filesystem::path GetRandomizerSettingsPath();
|
||||
std::filesystem::path GetRandomizerPreferencesPath();
|
||||
std::filesystem::path GetRandomizerSeedsPath();
|
||||
std::filesystem::path GetRandomizerPresetsPath();
|
||||
randomizer::seedgen::config::Config& GetRandomizerConfig();
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user