diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index a8d0473b7b..ef3dc32c81 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -1677,6 +1677,7 @@ public: case coPercent: { auto opt = new ConfigOptionPercent(); archive(*opt); return opt; } case coPercents: { auto opt = new ConfigOptionPercents(); archive(*opt); return opt; } case coFloatOrPercent: { auto opt = new ConfigOptionFloatOrPercent(); archive(*opt); return opt; } + case coFloatsOrPercents:{ auto opt = new ConfigOptionFloatsOrPercents();archive(*opt); return opt; } case coPoint: { auto opt = new ConfigOptionPoint(); archive(*opt); return opt; } case coPoints: { auto opt = new ConfigOptionPoints(); archive(*opt); return opt; } case coPoint3: { auto opt = new ConfigOptionPoint3(); archive(*opt); return opt; } @@ -1708,6 +1709,7 @@ public: case coPercent: archive(*static_cast(opt)); break; case coPercents: archive(*static_cast(opt)); break; case coFloatOrPercent: archive(*static_cast(opt)); break; + case coFloatsOrPercents:archive(*static_cast(opt));break; case coPoint: archive(*static_cast(opt)); break; case coPoints: archive(*static_cast(opt)); break; case coPoint3: archive(*static_cast(opt)); break; diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 7d61a138e0..8d781f35cb 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -1253,6 +1253,7 @@ inline t_config_option_keys deep_diff(const ConfigBase &config_this, const Confi case coStrings: add_correct_opts_to_diff(opt_key, diff, config_other, config_this); break; case coPercents:add_correct_opts_to_diff(opt_key, diff, config_other, config_this); break; case coPoints: add_correct_opts_to_diff(opt_key, diff, config_other, config_this); break; + case coFloatsOrPercents: add_correct_opts_to_diff(opt_key, diff, config_other, config_this); break; default: diff.emplace_back(opt_key); break; } } diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index df3302ca3e..7a19a0a424 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -536,7 +536,7 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionBool(true)); def = this->add("overhang_overlaps", coPercents); - def->label = L("Overhang overlap percentage"); + def->full_label = L("Overhang overlap percentage"); def->category = L("Speed"); def->tooltip = L("Controls percentage of overhang extrusion overlap with the previous layer." "Each overlap size then corresponds with the overhang speed set below."); @@ -547,7 +547,7 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionPercents({60, 40, 20, 0})); def = this->add("dynamic_overhang_speeds", coFloatsOrPercents); - def->label = L("Dynamic speed on overhangs"); + def->full_label = L("Dynamic speed on overhangs"); def->category = L("Speed"); def->tooltip = L("This setting controls the speed of the overhangs for overlap values set above." "The final speed is calculated as an interpolation of the set speed values." diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 800bd9bf38..5692c880f4 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -290,6 +290,7 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true break; } case coString: case coStrings: + case coFloatsOrPercents: case coFloatOrPercent: { if (m_opt.type == coFloatOrPercent && m_opt.opt_key == "first_layer_height" && !str.IsEmpty() && str.Last() == '%') { // Workaroud to avoid of using of the % for first layer height @@ -301,7 +302,7 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true m_value = into_u8(stVal);; break; } - if (m_opt.type == coFloatOrPercent && !str.IsEmpty() && str.Last() != '%') + if ((m_opt.type == coFloatOrPercent || m_opt.type == coFloatsOrPercents) && !str.IsEmpty() && str.Last() != '%') { double val = 0.; const char dec_sep = is_decimal_separator_point() ? '.' : ','; @@ -443,6 +444,13 @@ void TextCtrl::BUILD() { text_value += "%"; break; } + case coFloatsOrPercents: { + const auto val = m_opt.get_default_value()->get_at(m_opt_idx); + text_value = double_to_string(val.value); + if (val.percent) + text_value += "%"; + break; + } case coPercent: { text_value = wxString::Format(_T("%i"), int(m_opt.default_value->getFloat())); @@ -574,6 +582,7 @@ bool TextCtrl::value_was_changed() case coString: case coStrings: case coFloatOrPercent: + case coFloatsOrPercents: return boost::any_cast(m_value) != boost::any_cast(val); default: return true; diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index 5886be0284..d4df48d508 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -130,6 +130,18 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt val = boost::any_cast(value); break; } + case coFloatsOrPercents:{ + std::string str = boost::any_cast(value); + bool percent = false; + if (str.back() == '%') { + str.pop_back(); + percent = true; + } + double val = std::stod(str); // locale-dependent (on purpose - the input is the actual content of the field) + ConfigOptionFloatsOrPercents* vec_new = new ConfigOptionFloatsOrPercents({ {val, percent} }); + config.option(opt_key)->set_at(vec_new, opt_index, opt_index); + break; + } case coPercents:{ ConfigOptionPercents* vec_new = new ConfigOptionPercents{ boost::any_cast(value) }; config.option(opt_key)->set_at(vec_new, opt_index, opt_index); diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index 0534446f01..3e99d0cf1b 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -54,6 +54,7 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co default: switch (opt.type) { case coFloatOrPercent: + case coFloatsOrPercents: case coFloat: case coFloats: case coPercent: @@ -867,6 +868,14 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config ret = text_value; break; } + case coFloatsOrPercents:{ + const auto& val = config.option(opt_key)->get_at(idx); + text_value = double_to_string(val.value); + if (val.percent) + text_value += "%"; + ret = text_value; + break; + } case coPercent:{ double val = config.option(opt_key)->value; text_value = wxString::Format(_T("%i"), int(val)); diff --git a/src/slic3r/GUI/Search.cpp b/src/slic3r/GUI/Search.cpp index 88d3e13763..594632a226 100644 --- a/src/slic3r/GUI/Search.cpp +++ b/src/slic3r/GUI/Search.cpp @@ -80,8 +80,12 @@ static std::string get_key(const std::string& opt_key, Preset::Type type) void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type type) { - auto emplace = [this, type](const std::string key, const wxString& label) + auto emplace = [this, type](std::string key, const wxString& label, int id = -1) { + if (id >= 0) + // ! It's very important to use "#". opt_key#n is a real option key used in GroupAndCategory + key += "#" + std::to_string(id); + const GroupAndCategory& gc = groups_and_categories[key]; if (gc.group.IsEmpty() || gc.category.IsEmpty()) return; @@ -89,10 +93,14 @@ void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type ty wxString suffix; wxString suffix_local; if (gc.category == "Machine limits") { - suffix = key.back()=='1' ? L("Stealth") : L("Normal"); + suffix = id == 1 ? L("Stealth") : L("Normal"); suffix_local = " " + _(suffix); suffix = " " + suffix; } + else if (gc.group == "Dynamic overhang speed" && id >= 0) { + suffix = " " + std::to_string(id+1); + suffix_local = suffix; + } if (!label.IsEmpty()) options.emplace_back(Option{ boost::nowide::widen(key), type, @@ -109,7 +117,7 @@ void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type ty int cnt = 0; - if ( (type == Preset::TYPE_SLA_MATERIAL || type == Preset::TYPE_PRINTER) && opt_key != "bed_shape" && opt_key != "thumbnails") + if ( (type == Preset::TYPE_SLA_MATERIAL || type == Preset::TYPE_PRINTER || type == Preset::TYPE_PRINT) && opt_key != "bed_shape" && opt_key != "thumbnails") switch (config->option(opt_key)->type()) { case coInts: change_opt_key(opt_key, config, cnt); break; @@ -118,6 +126,7 @@ void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type ty case coStrings: change_opt_key(opt_key, config, cnt); break; case coPercents:change_opt_key(opt_key, config, cnt); break; case coPoints: change_opt_key(opt_key, config, cnt); break; + case coFloatsOrPercents: change_opt_key(opt_key, config, cnt); break; default: break; } @@ -128,8 +137,7 @@ void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type ty emplace(key, label); else for (int i = 0; i < cnt; ++i) - // ! It's very important to use "#". opt_key#n is a real option key used in GroupAndCategory - emplace(key + "#" + std::to_string(i), label); + emplace(key, label, i); } } diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 6cf2509f5a..30c48420f3 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -603,7 +603,7 @@ void Tab::update_changed_ui() if (m_postpone_update_ui) return; - const bool deep_compare = (m_type == Slic3r::Preset::TYPE_PRINTER || m_type == Slic3r::Preset::TYPE_SLA_MATERIAL); + const bool deep_compare = m_type != Preset::TYPE_FILAMENT; auto dirty_options = m_presets->current_dirty_options(deep_compare); auto nonsys_options = m_presets->current_different_from_parent_options(deep_compare); if (m_type == Preset::TYPE_PRINTER) { @@ -644,11 +644,10 @@ void Tab::update_changed_ui() void Tab::init_options_list() { - if (!m_options_list.empty()) - m_options_list.clear(); + m_options_list.clear(); for (const std::string& opt_key : m_config->keys()) - m_options_list.emplace(opt_key, m_opt_status_value); + emplace_option(opt_key); } template @@ -659,10 +658,36 @@ void add_correct_opts_to_options_list(const std::string &opt_key, std::mapoption(opt_key)->type()) + { + case coInts: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; + case coBools: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; + case coFloats: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; + case coStrings: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; + case coPercents:add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; + case coPoints: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; + case coFloatsOrPercents: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; + default: m_options_list.emplace(opt_key, m_opt_status_value); break; + } + } + else + m_options_list.emplace(opt_key, m_opt_status_value); +} + +void TabPrint::init_options_list() +{ + m_options_list.clear(); + + for (const std::string& opt_key : m_config->keys()) + emplace_option(opt_key, true); +} + void TabPrinter::init_options_list() { - if (!m_options_list.empty()) - m_options_list.clear(); + m_options_list.clear(); for (const std::string& opt_key : m_config->keys()) { @@ -670,16 +695,7 @@ void TabPrinter::init_options_list() m_options_list.emplace(opt_key, m_opt_status_value); continue; } - switch (m_config->option(opt_key)->type()) - { - case coInts: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; - case coBools: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; - case coFloats: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; - case coStrings: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; - case coPercents:add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; - case coPoints: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; - default: m_options_list.emplace(opt_key, m_opt_status_value); break; - } + emplace_option(opt_key, true); } if (m_printer_technology == ptFFF) m_options_list.emplace("extruders_count", m_opt_status_value); @@ -687,8 +703,7 @@ void TabPrinter::init_options_list() void TabSLAMaterial::init_options_list() { - if (!m_options_list.empty()) - m_options_list.clear(); + m_options_list.clear(); for (const std::string& opt_key : m_config->keys()) { @@ -696,16 +711,7 @@ void TabSLAMaterial::init_options_list() m_options_list.emplace(opt_key, m_opt_status_value); continue; } - switch (m_config->option(opt_key)->type()) - { - case coInts: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; - case coBools: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; - case coFloats: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; - case coStrings: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; - case coPercents:add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; - case coPoints: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; - default: m_options_list.emplace(opt_key, m_opt_status_value); break; - } + emplace_option(opt_key, true); } } diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 83ece74e8c..70c16a0235 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -348,6 +348,7 @@ public: virtual void update() = 0; virtual void toggle_options() = 0; virtual void init_options_list(); + void emplace_option(const std::string &opt_key, bool respect_vec_values = false); void load_initial_data(); void update_dirty(); void update_tab_ui(); @@ -416,6 +417,7 @@ public: void toggle_options() override; void update() override; void clear_pages() override; + void init_options_list() override; bool supports_printer_technology(const PrinterTechnology tech) const override { return tech == ptFFF; } wxSizer* create_manage_substitution_widget(wxWindow* parent); wxSizer* create_substitutions_widget(wxWindow* parent); diff --git a/src/slic3r/GUI/UnsavedChangesDialog.cpp b/src/slic3r/GUI/UnsavedChangesDialog.cpp index 73d4b767ad..158579c70e 100644 --- a/src/slic3r/GUI/UnsavedChangesDialog.cpp +++ b/src/slic3r/GUI/UnsavedChangesDialog.cpp @@ -1205,6 +1205,14 @@ static wxString get_string_value(std::string opt_key, const DynamicPrintConfig& out = double_to_string(opt->value) + (opt->percent ? "%" : ""); return out; } + case coFloatsOrPercents: { + const ConfigOptionFloatsOrPercents* opt = config.opt(opt_key); + if (opt) { + const auto val = opt->get_at(opt_idx); + out = double_to_string(val.value) + (val.percent ? "%" : ""); + } + return out; + } case coEnum: { return get_string_from_enum(opt_key, config, opt_key == "top_fill_pattern" || @@ -1303,7 +1311,7 @@ void UnsavedChangesDialog::update_tree(Preset::Type type, PresetCollection* pres m_tree->model->AddPreset(type, from_u8(presets->get_edited_preset().name), old_pt, from_u8(new_selected_preset)); // Collect dirty options. - const bool deep_compare = (type == Preset::TYPE_PRINTER || type == Preset::TYPE_SLA_MATERIAL); + const bool deep_compare = type != Preset::TYPE_FILAMENT; auto dirty_options = presets->current_dirty_options(deep_compare); // process changes of extruders count @@ -1833,7 +1841,7 @@ void DiffPresetDialog::update_tree() } // Collect dirty options. - const bool deep_compare = (type == Preset::TYPE_PRINTER || type == Preset::TYPE_SLA_MATERIAL); + const bool deep_compare = type != Preset::TYPE_FILAMENT; auto dirty_options = type == Preset::TYPE_PRINTER && left_pt == ptFFF && left_config.opt("extruder_colour")->values.size() < right_congig.opt("extruder_colour")->values.size() ? presets->dirty_options(right_preset, left_preset, deep_compare) :