From 7280b2a0fb6e834cae7f4d042b5ee0f6f6f450cc Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 21 Aug 2023 18:24:07 +0200 Subject: [PATCH] Fix for SPE-1845 Incorrectly imported filament profiles from 3MF or configuration ini. + Fix for SPE-1848 Crash on switch from MM printer to SM, when non-first filament is modified --- src/libslic3r/Preset.cpp | 4 +++ src/libslic3r/PresetBundle.cpp | 36 ++++++++++++++++-------- src/slic3r/GUI/GUI_App.cpp | 3 ++ src/slic3r/GUI/Tab.cpp | 50 +++++++++++++++++++++++++++++++--- src/slic3r/GUI/Tab.hpp | 1 + 5 files changed, 79 insertions(+), 15 deletions(-) diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index d6ecb782e1..438668ea40 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -1376,6 +1376,10 @@ Preset& PresetCollection::select_preset(size_t idx) if (idx >= m_presets.size()) idx = first_visible_idx(); m_idx_selected = idx; + if (!m_presets[idx].is_visible) + // The newly selected preset can be activated -> make it visible. + m_presets[idx].is_visible = true; + m_edited_preset = m_presets[idx]; bool default_visible = ! m_default_suppressed || m_idx_selected < m_num_default_presets; for (size_t i = 0; i < m_num_default_presets; ++i) diff --git a/src/libslic3r/PresetBundle.cpp b/src/libslic3r/PresetBundle.cpp index af57c9314d..13153dd923 100644 --- a/src/libslic3r/PresetBundle.cpp +++ b/src/libslic3r/PresetBundle.cpp @@ -1046,11 +1046,8 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool } // Load the configs into this->filaments and make them active. std::vector extr_names = std::vector(configs.size()); - // To avoid incorrect selection of the first filament preset (means a value of Preset->m_idx_selected) - // in a case when next added preset take a place of previosly selected preset, - // we should add presets from last to first bool any_modified = false; - for (int i = (int)configs.size()-1; i >= 0; i--) { + for (int i = 0; i < (int)configs.size(); i++) { DynamicPrintConfig &cfg = configs[i]; // Split the "compatible_printers_condition" and "inherits" from the cummulative vectors to separate filament presets. cfg.opt_string("compatible_printers_condition", true) = compatible_printers_condition_values[i + 1]; @@ -1059,15 +1056,18 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool // Load all filament presets, but only select the first one in the preset dialog. auto [loaded, modified] = this->filaments.load_external_preset(name_or_path, name, (i < int(old_filament_profile_names->values.size())) ? old_filament_profile_names->values[i] : "", - std::move(cfg), - i == 0 ? - PresetCollection::LoadAndSelect::Always : - any_modified ? - PresetCollection::LoadAndSelect::Never : - PresetCollection::LoadAndSelect::OnlyIfModified); + std::move(cfg), + any_modified ? PresetCollection::LoadAndSelect::Never : + PresetCollection::LoadAndSelect::OnlyIfModified); any_modified |= modified; extr_names[i] = loaded->name; } + + // Check if some preset was selected after loading from config file. + // ! Selected preset name is always the same as name of edited preset, if selection was applied + if (this->filaments.get_selected_preset_name() != this->filaments.get_edited_preset().name) + this->filaments.select_preset_by_name(extr_names[0], true); + // create extruders_filaments only when all filaments are loaded for (size_t id = 0; id < extr_names.size(); ++id) this->extruders_filaments.emplace_back(ExtruderFilaments(&filaments, id, extr_names[id])); @@ -1806,7 +1806,21 @@ void PresetBundle::update_filaments_compatible(PresetSelectCompatibleType select else update_filament_compatible(extruder_idx); - if (this->filaments.get_idx_selected() == size_t(-1)) + // validate selection in filaments + bool invalid_selection = this->filaments.get_idx_selected() == size_t(-1); + if (!invalid_selection) { + invalid_selection = true; + const std::string selected_filament_name = this->filaments.get_selected_preset_name(); + for (const auto& extruder : extruders_filaments) + if (const std::string& selected_extr_filament_name = extruder.get_selected_preset_name(); + selected_extr_filament_name == selected_filament_name) { + invalid_selection = false; + break; + } + } + + // select valid filament from first extruder + if (invalid_selection) this->filaments.select_preset(extruders_filaments[0].get_selected_idx()); } diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index e8c7605473..b5321ba567 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -2864,6 +2864,9 @@ void GUI_App::load_current_presets(bool check_printer_presets_ /*= true*/) // Mark the plater to update print bed by tab->load_current_preset() from Plater::on_config_change(). this->plater()->force_print_bed_update(); } + else if (tab->type() == Preset::TYPE_FILAMENT) + // active extruder can be changed in a respect to the new loaded configurations, if some filament preset will be modified + static_cast(tab)->invalidate_active_extruder(); tab->load_current_preset(); } } diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index dc922f971b..abec782ceb 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1986,8 +1986,16 @@ void TabFilament::update_extruder_combobox() m_extruders_cb->Append(format_wxstr("%1% %2%", _L("Extruder"), id), *get_bmp_bundle("funnel")); } - if (m_active_extruder >= int(extruder_cnt)) + if (m_active_extruder >= int(extruder_cnt)) { m_active_extruder = 0; + // update selected and, as a result, editing preset + const std::string& preset_name = m_preset_bundle->extruders_filaments[0].get_selected_preset_name(); + m_presets->select_preset_by_name(preset_name, true); + + // To avoid inconsistance between value of active_extruder in FilamentTab and TabPresetComboBox, + // which can causes a crash on switch preset from MM printer to SM printer + m_presets_choice->set_active_extruder(m_active_extruder); + } m_extruders_cb->SetSelection(m_active_extruder); } @@ -2317,12 +2325,37 @@ void TabFilament::sys_color_changed() void TabFilament::load_current_preset() { + const std::string& selected_filament_name = m_presets->get_selected_preset_name(); + if (m_active_extruder < 0) { + // active extruder was invalidated before load new project file or configuration, + // so we have to update active extruder selection from selected filament + const std::string& edited_filament_name = m_presets->get_edited_preset().name; + assert(!selected_filament_name.empty() && selected_filament_name == edited_filament_name); + + for (int i = 0; i < int(m_preset_bundle->extruders_filaments.size()); i++) { + const std::string& selected_extr_filament_name = m_preset_bundle->extruders_filaments[i].get_selected_preset_name(); + if (selected_extr_filament_name == edited_filament_name) { + m_active_extruder = i; + break; + } + } + assert(m_active_extruder >= 0); + + m_presets_choice->set_active_extruder(m_active_extruder); + if (m_active_extruder != m_extruders_cb->GetSelection()) + m_extruders_cb->Select(m_active_extruder); + } + assert(m_active_extruder >= 0 && m_active_extruder < m_preset_bundle->extruders_filaments.size()); const std::string& selected_extr_filament_name = m_preset_bundle->extruders_filaments[m_active_extruder].get_selected_preset_name(); - const std::string& selected_filament_name = m_presets->get_selected_preset_name(); - if (selected_extr_filament_name != selected_filament_name) + if (selected_extr_filament_name != selected_filament_name) { m_presets->select_preset_by_name(selected_extr_filament_name, false); + // To avoid inconsistance between value of active_extruder in FilamentTab and TabPresetComboBox, + // which can causes a crash on switch preset from MM printer to SM printer + m_presets_choice->set_active_extruder(m_active_extruder); + } + Tab::load_current_preset(); } @@ -3639,8 +3672,17 @@ bool Tab::select_preset(std::string preset_name, bool delete_current /*=false*/, for (PresetUpdate &pu : updates) { pu.old_preset_dirty = (old_printer_technology == pu.technology) && pu.presets->current_is_dirty(); pu.new_preset_compatible = (new_printer_technology == pu.technology) && is_compatible_with_printer(pu.presets->get_edited_preset_with_vendor_profile(), new_printer_preset_with_vendor_profile); + bool force_update_edited_preset = false; + if (pu.tab_type == Preset::TYPE_FILAMENT && pu.new_preset_compatible) { + // check if edited preset will be still correct after selection new printer + const int active_extruder = dynamic_cast(wxGetApp().get_tab(Preset::TYPE_FILAMENT))->get_active_extruder(); + const int extruder_count_new = int(dynamic_cast(new_printer_preset.config.option("nozzle_diameter"))->size()); + // if active_extruder is bigger than extruders_count, + // then it means that edited filament preset will be changed and we have to check this changes + force_update_edited_preset = active_extruder >= extruder_count_new; + } if (!canceled) - canceled = pu.old_preset_dirty && !pu.new_preset_compatible && !may_discard_current_dirty_preset(pu.presets, preset_name); + canceled = pu.old_preset_dirty && (!pu.new_preset_compatible || force_update_edited_preset) && !may_discard_current_dirty_preset(pu.presets, preset_name); } if (!canceled) { for (PresetUpdate &pu : updates) { diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index f0be456a5a..da005b2180 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -469,6 +469,7 @@ public: // set actiev extruder and update preset combobox if needed // return false, if new preset wasn't selected bool set_active_extruder(int new_selected_extruder); + void invalidate_active_extruder() { m_active_extruder = -1; } void update_extruder_combobox(); int get_active_extruder() const { return m_active_extruder; }