diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 4e8eaa63b..2f5c4e96b 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -517,6 +517,7 @@ public: void set_task(const TaskParams ¶ms) override { PrintBaseWithState::set_task_impl(params, m_objects); } void process() override; void finalize() override { PrintBaseWithState::finalize_impl(m_objects); } + void cleanup() override; // Exports G-code into a file name based on the path_template, returns the file path of the generated G-code file. // If preview_data is not null, the preview_data is filled in for the G-code visualization (not used by the command line Slic3r). @@ -609,6 +610,12 @@ private: // Return 4 wipe tower corners in the world coordinates (shifted and rotated), including the wipe tower brim. std::vector first_layer_wipe_tower_corners() const; + // Returns true if any of the print_objects has print_object_step valid. + // That means data shared by all print objects of the print_objects span may still use the shared data. + // Otherwise the shared data shall be released. + // Unguarded variant, thus it shall only be called from main thread with background processing stopped. + static bool is_shared_print_object_step_valid_unguarded(SpanOfConstPtrs print_objects, PrintObjectStep print_object_step); + PrintConfig m_config; PrintObjectConfig m_default_object_config; PrintRegionConfig m_default_region_config; diff --git a/src/libslic3r/PrintApply.cpp b/src/libslic3r/PrintApply.cpp index 330ad533c..5f95edefa 100644 --- a/src/libslic3r/PrintApply.cpp +++ b/src/libslic3r/PrintApply.cpp @@ -1451,6 +1451,9 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ for (PrintObject *object : m_objects) object->update_slicing_parameters(); + if (apply_status == APPLY_STATUS_CHANGED || apply_status == APPLY_STATUS_INVALIDATED) + this->cleanup(); + #ifdef _DEBUG check_model_ids_equal(m_model, model); #endif /* _DEBUG */ @@ -1458,4 +1461,25 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ return static_cast(apply_status); } +void Print::cleanup() +{ + // Invalidate data of a single ModelObject shared by multiple PrintObjects. + // Find spans of PrintObjects sharing the same PrintObjectRegions. + std::vector all_objects(m_objects); + std::sort(all_objects.begin(), all_objects.end(), [](const PrintObject *l, const PrintObject *r){ return l->shared_regions() < r->shared_regions(); } ); + for (auto it = all_objects.begin(); it != all_objects.end();) { + PrintObjectRegions *shared_regions = (*it)->m_shared_regions; + auto it_begin = it; + for (++ it; it != all_objects.end() && shared_regions == (*it)->shared_regions(); ++ it); + auto this_objects = SpanOfConstPtrs(const_cast(&(*it_begin)), it - it_begin); + if (Print::is_shared_print_object_step_valid_unguarded(this_objects, posSupportSpotsSearch)) + shared_regions->generated_support_points.reset(); + } +} + +bool Print::is_shared_print_object_step_valid_unguarded(SpanOfConstPtrs print_objects, PrintObjectStep print_object_step) +{ + return std::any_of(print_objects.begin(), print_objects.end(), [print_object_step](auto po){ return po->is_step_done_unguarded(print_object_step); }); +} + } // namespace Slic3r diff --git a/src/libslic3r/PrintBase.hpp b/src/libslic3r/PrintBase.hpp index 13796abba..6aac560a3 100644 --- a/src/libslic3r/PrintBase.hpp +++ b/src/libslic3r/PrintBase.hpp @@ -408,6 +408,10 @@ public: // Clean up after process() finished, either with success, error or if canceled. // The adjustments on the Print / PrintObject data due to set_task() are to be reverted here. virtual void finalize() = 0; + // Clean up print step / print object step data after + // 1) some print step / print object step was invalidated inside PrintBase::apply() while holding the milestone mutex locked. + // 2) background thread finished being canceled. + virtual void cleanup() = 0; struct SlicingStatus { SlicingStatus(int percent, const std::string &text, unsigned int flags = 0) : percent(percent), text(text), flags(flags) {} diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index 528d3c28b..2ebb7cc2f 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -412,6 +412,7 @@ public: void set_task(const TaskParams ¶ms) override { PrintBaseWithState::set_task_impl(params, m_objects); } void process() override; void finalize() override { PrintBaseWithState::finalize_impl(m_objects); } + void cleanup() override {} // Returns true if an object step is done on all objects and there's at least one object. bool is_step_done(SLAPrintObjectStep step) const; // Returns true if the last step was finished with success. diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.cpp b/src/slic3r/GUI/BackgroundSlicingProcess.cpp index 275fcdc98..678761924 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.cpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.cpp @@ -251,6 +251,9 @@ void BackgroundSlicingProcess::thread_proc() (m_state == STATE_CANCELED) ? SlicingProcessCompletedEvent::Cancelled : exception ? SlicingProcessCompletedEvent::Error : SlicingProcessCompletedEvent::Finished, exception); wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, evt.Clone()); + // Cancelled by the user, not internally, thus cleanup() was not called yet. + // Otherwise cleanup() is called from Print::apply() + m_print->cleanup(); } m_print->restart(); lck.unlock(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index b55f6299a..6e65371ed 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -983,20 +983,24 @@ Sidebar::Sidebar(Plater *parent) Sidebar::~Sidebar() {} -void Sidebar::init_filament_combo(PlaterPresetComboBox **combo, const int extr_idx) { +void Sidebar::init_filament_combo(PlaterPresetComboBox** combo, const int extr_idx) +{ *combo = new PlaterPresetComboBox(p->presets_panel, Slic3r::Preset::TYPE_FILAMENT); -// # copy icons from first choice -// $choice->SetItemBitmap($_, $choices->[0]->GetItemBitmap($_)) for 0..$#presets; - (*combo)->set_extruder_idx(extr_idx); +#ifdef __WXMSW__ + // When project is loading and progress dialog is processing + // In this case mainframe is marked as a disabled, that is why new created filament preset comboboxes are disabled + if (wxWindow* mf = wxGetApp().mainframe; mf && !mf->IsThisEnabled()) + mf->Enable(); +#endif //__WXMSW__ + auto combo_and_btn_sizer = new wxBoxSizer(wxHORIZONTAL); combo_and_btn_sizer->Add(*combo, 1, wxEXPAND); combo_and_btn_sizer->Add((*combo)->edit_btn, 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, int(0.3*wxGetApp().em_unit())); - auto /***/sizer_filaments = this->p->sizer_filaments; - sizer_filaments->Add(combo_and_btn_sizer, 1, wxEXPAND | + this->p->sizer_filaments->Add(combo_and_btn_sizer, 1, wxEXPAND | #ifdef __WXGTK3__ wxRIGHT, int(0.5 * wxGetApp().em_unit())); #else