diff --git a/src/igl/EPS.h b/src/igl/EPS.h index 17f3b8c25..d65007a64 100644 --- a/src/igl/EPS.h +++ b/src/igl/EPS.h @@ -13,8 +13,8 @@ namespace igl // Define a standard value for double epsilon const double DOUBLE_EPS = 1.0e-14; const double DOUBLE_EPS_SQ = 1.0e-28; - const float FLOAT_EPS = 1.0e-7; - const float FLOAT_EPS_SQ = 1.0e-14; + const float FLOAT_EPS = 1.0e-7f; + const float FLOAT_EPS_SQ = 1.0e-14f; // Function returning EPS for corresponding type template IGL_INLINE S_type EPS(); template IGL_INLINE S_type EPS_SQ(); diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 97eb03662..0ac5c9771 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -760,7 +760,8 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co update_apply_status(this->invalidate_all_steps()); for (PrintObject *object : m_objects) { model_object_status.emplace(object->model_object()->id(), ModelObjectStatus::Deleted); - delete object; + update_apply_status(object->invalidate_all_steps()); + delete object; } m_objects.clear(); for (PrintRegion *region : m_regions) @@ -990,12 +991,9 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co const_cast(*it_old)->status = PrintObjectStatus::Deleted; } else { // The PrintObject already exists and the copies differ. - if ((*it_old)->print_object->copies().size() != new_instances.copies.size()) - update_apply_status(this->invalidate_step(psWipeTower)); - if ((*it_old)->print_object->set_copies(new_instances.copies)) { - // Invalidated - update_apply_status(this->invalidate_steps({ psSkirt, psBrim, psGCodeExport })); - } + PrintBase::ApplyStatus status = (*it_old)->print_object->set_copies(new_instances.copies); + if (status != PrintBase::APPLY_STATUS_UNCHANGED) + update_apply_status(status == PrintBase::APPLY_STATUS_INVALIDATED); print_objects_new.emplace_back((*it_old)->print_object); const_cast(*it_old)->status = PrintObjectStatus::Reused; } @@ -1009,13 +1007,14 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co bool deleted_objects = false; for (auto &pos : print_object_status) if (pos.status == PrintObjectStatus::Unknown || pos.status == PrintObjectStatus::Deleted) { - // update_apply_status(pos.print_object->invalidate_all_steps()); + update_apply_status(pos.print_object->invalidate_all_steps()); delete pos.print_object; deleted_objects = true; } if (new_objects || deleted_objects) update_apply_status(this->invalidate_steps({ psSkirt, psBrim, psWipeTower, psGCodeExport })); - update_apply_status(new_objects); + if (new_objects) + update_apply_status(false); } print_object_status.clear(); } @@ -1629,7 +1628,9 @@ void Print::_make_skirt() { Polygons loops = offset(convex_hull, distance, ClipperLib::jtRound, scale_(0.1)); Geometry::simplify_polygons(loops, scale_(0.05), &loops); - loop = loops.front(); + if (loops.empty()) + break; + loop = loops.front(); } // Extrude the skirt loop. ExtrusionLoop eloop(elrSkirt); diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index e5060cb76..eaad767ea 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -164,7 +164,7 @@ protected: void config_apply(const ConfigBase &other, bool ignore_nonexistent = false) { this->m_config.apply(other, ignore_nonexistent); } void config_apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false) { this->m_config.apply_only(other, keys, ignore_nonexistent); } void set_trafo(const Transform3d& trafo) { m_trafo = trafo; } - bool set_copies(const Points &points); + PrintBase::ApplyStatus set_copies(const Points &points); // Invalidates the step, and its depending steps in PrintObject and Print. bool invalidate_step(PrintObjectStep step); // Invalidates all PrintObject and Print steps. diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 877c77b0c..3019233d1 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -69,7 +69,7 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, bool add_insta this->layer_height_profile = model_object->layer_height_profile; } -bool PrintObject::set_copies(const Points &points) +PrintBase::ApplyStatus PrintObject::set_copies(const Points &points) { // Order copies with a nearest-neighbor search. std::vector copies; @@ -81,14 +81,15 @@ bool PrintObject::set_copies(const Points &points) copies.emplace_back(points[point_idx] + m_copies_shift); } // Invalidate and set copies. - bool invalidated = false; + PrintBase::ApplyStatus status = PrintBase::APPLY_STATUS_UNCHANGED; if (copies != m_copies) { - invalidated = m_print->invalidate_steps({ psSkirt, psBrim, psGCodeExport }); - if (copies.size() != m_copies.size()) - invalidated |= m_print->invalidate_step(psWipeTower); + status = PrintBase::APPLY_STATUS_CHANGED; + if (m_print->invalidate_steps({ psSkirt, psBrim, psGCodeExport }) || + (copies.size() != m_copies.size() && m_print->invalidate_step(psWipeTower))) + status = PrintBase::APPLY_STATUS_INVALIDATED; m_copies = copies; } - return invalidated; + return status; } // 1) Decides Z positions of the layers, diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 9d177a5e9..afb9c6f87 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -184,6 +184,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf update_apply_status(this->invalidate_all_steps()); for (SLAPrintObject *object : m_objects) { model_object_status.emplace(object->model_object()->id(), ModelObjectStatus::Deleted); + update_apply_status(object->invalidate_all_steps()); delete object; } m_objects.clear(); @@ -376,11 +377,12 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf bool deleted_objects = false; for (auto &pos : print_object_status) if (pos.status == PrintObjectStatus::Unknown || pos.status == PrintObjectStatus::Deleted) { - // update_apply_status(pos.print_object->invalidate_all_steps()); + update_apply_status(pos.print_object->invalidate_all_steps()); delete pos.print_object; deleted_objects = true; } - update_apply_status(new_objects); + if (new_objects) + update_apply_status(false); } this->update_object_placeholders(); diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index 3a4dd846e..9fab4d550 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -190,7 +190,7 @@ public: // 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. - bool finished() const override { return this->is_step_done(slaposIndexSlices); } + bool finished() const override { return this->is_step_done(slaposIndexSlices) && this->Inherited::is_step_done(slapsRasterize); } template void export_raster(const std::string& fname) { if(m_printer) m_printer->save(fname); diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index b801b6679..d0ae03e26 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -2218,7 +2218,7 @@ bool GLCurvedArrow::on_init(bool useVBOs) } // side face - for (unsigned int i = 0; i < 4 + 2 * (int)m_resolution; ++i) + for (unsigned int i = 0; i < 4 + 2 * (unsigned int)m_resolution; ++i) { triangles.emplace_back(i, vertices_per_level + 2 + i, i + 1); triangles.emplace_back(i, vertices_per_level + 1 + i, vertices_per_level + 2 + i); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index bcf66b603..6d5053bfa 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -987,11 +987,17 @@ struct Plater::priv // update_background_process() reports, that the Print / SLAPrint is invalid, and the error message // was sent to the status line. UPDATE_BACKGROUND_PROCESS_INVALID = 4, + // Restart even if the background processing is disabled. + UPDATE_BACKGROUND_PROCESS_FORCE_RESTART = 8, + // Restart for G-code (or SLA zip) export or upload. + UPDATE_BACKGROUND_PROCESS_FORCE_EXPORT = 16, }; // returns bit mask of UpdateBackgroundProcessReturnState unsigned int update_background_process(); + // Restart background processing thread based on a bitmask of UpdateBackgroundProcessReturnState. + bool restart_background_process(unsigned int state); + void update_restart_background_process(bool force_scene_update, bool force_preview_update); void export_gcode(fs::path output_path, PrintHostJob upload_job); - void async_apply_config(); void reload_from_disk(); void fix_through_netfabb(const int obj_idx); @@ -1141,7 +1147,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) #endif // ENABLE_REMOVE_TABS_FROM_PLATER this->background_process_timer.SetOwner(this->q, 0); - this->q->Bind(wxEVT_TIMER, [this](wxTimerEvent &evt) { this->async_apply_config(); }); + this->q->Bind(wxEVT_TIMER, [this](wxTimerEvent &evt) { this->update_restart_background_process(false, false); }); auto *bed_shape = config->opt("bed_shape"); #if ENABLE_REMOVE_TABS_FROM_PLATER @@ -1239,6 +1245,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) // Preview events: preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_VIEWPORT_CHANGED, &priv::on_viewport_changed, this); + preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_QUESTION_MARK, [this](SimpleEvent&) { wxGetApp().keyboard_shortcuts(); }); #if ENABLE_REMOVE_TABS_FROM_PLATER view3D_canvas->Bind(EVT_GLCANVAS_INIT, [this](SimpleEvent&) { init_view_toolbar(); }); #endif // ENABLE_REMOVE_TABS_FROM_PLATER @@ -1272,19 +1279,21 @@ void Plater::priv::update(bool force_full_scene_refresh) model.center_instances_around_point(bed_center); } - if (this->printer_technology == ptSLA) { + unsigned int update_status = 0; + if (this->printer_technology == ptSLA) // Update the SLAPrint from the current Model, so that the reload_scene() // pulls the correct data. - this->update_background_process(); - } + update_status = this->update_background_process(); #if ENABLE_REMOVE_TABS_FROM_PLATER - view3D->reload_scene(false, force_full_scene_refresh); + this->view3D->reload_scene(false, force_full_scene_refresh); #else this->canvas3D->reload_scene(false, force_full_scene_refresh); #endif // ENABLE_REMOVE_TABS_FROM_PLATER - preview->reload_print(); - - this->schedule_background_process(); + this->preview->reload_print(); + if (this->printer_technology == ptSLA) + this->restart_background_process(update_status); + else + this->schedule_background_process(); } #if ENABLE_REMOVE_TABS_FROM_PLATER @@ -1999,12 +2008,13 @@ unsigned int Plater::priv::update_background_process() // bitmap of enum UpdateBackgroundProcessReturnState unsigned int return_state = 0; - // If the update_background_process() was not called by the timer, kill the timer, so the async_apply_config() - // will not be called again in vain. + // If the update_background_process() was not called by the timer, kill the timer, + // so the update_restart_background_process() will not be called again in vain. this->background_process_timer.Stop(); // Update the "out of print bed" state of ModelInstances. this->update_print_volume_state(); // Apply new config to the possibly running background task. + bool was_running = this->background_process.running(); Print::ApplyStatus invalidated = this->background_process.apply(this->q->model(), wxGetApp().preset_bundle->full_config()); // Just redraw the 3D canvas without reloading the scene to consume the update of the layer height profile. @@ -2038,18 +2048,10 @@ unsigned int Plater::priv::update_background_process() } } - if (this->background_process.empty()) { - if (invalidated != Print::APPLY_STATUS_UNCHANGED) { - // The background processing will not be restarted, because the Print / SLAPrint is empty. - // Simulate a "canceled" callback message. - wxCommandEvent evt; - evt.SetInt(-1); // canceled - this->on_process_completed(evt); - } - } else { + if (! this->background_process.empty()) { std::string err = this->background_process.validate(); if (err.empty()) { - if (invalidated != Print::APPLY_STATUS_UNCHANGED) + if (invalidated != Print::APPLY_STATUS_UNCHANGED && this->background_processing_enabled()) return_state |= UPDATE_BACKGROUND_PROCESS_RESTART; } else { // The print is not valid. @@ -2057,9 +2059,39 @@ unsigned int Plater::priv::update_background_process() return_state |= UPDATE_BACKGROUND_PROCESS_INVALID; } } + + if (invalidated != Print::APPLY_STATUS_UNCHANGED && was_running && ! this->background_process.running() && + (return_state & UPDATE_BACKGROUND_PROCESS_RESTART) == 0) { + // The background processing was killed and it will not be restarted. + wxCommandEvent evt(EVT_PROCESS_COMPLETED); + evt.SetInt(-1); + // Post the "canceled" callback message, so that it will be processed after any possible pending status bar update messages. + wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, evt.Clone()); + } + return return_state; } +// Restart background processing thread based on a bitmask of UpdateBackgroundProcessReturnState. +bool Plater::priv::restart_background_process(unsigned int state) +{ + if ( ! this->background_process.empty() && + (state & priv::UPDATE_BACKGROUND_PROCESS_INVALID) == 0 && + ( ((state & UPDATE_BACKGROUND_PROCESS_FORCE_RESTART) != 0 && ! this->background_process.finished()) || + (state & UPDATE_BACKGROUND_PROCESS_FORCE_EXPORT) != 0 || + (state & UPDATE_BACKGROUND_PROCESS_RESTART) != 0 ) ) { + // The print is valid and it can be started. + if (this->background_process.start()) { + this->statusbar()->set_cancel_callback([this]() { + this->statusbar()->set_status_text(L("Cancelling")); + this->background_process.stop(); + }); + return true; + } + } + return false; +} + void Plater::priv::export_gcode(fs::path output_path, PrintHostJob upload_job) { wxCHECK_RET(!(output_path.empty() && upload_job.empty()), "export_gcode: output_path and upload_job empty"); @@ -2089,34 +2121,22 @@ void Plater::priv::export_gcode(fs::path output_path, PrintHostJob upload_job) background_process.schedule_upload(std::move(upload_job)); } - if (! background_process.running()) { - // The print is valid and it should be started. - if (background_process.start()) - statusbar()->set_cancel_callback([this]() { - statusbar()->set_status_text(L("Cancelling")); - background_process.stop(); - }); - } + this->restart_background_process(priv::UPDATE_BACKGROUND_PROCESS_FORCE_EXPORT); } -void Plater::priv::async_apply_config() +void Plater::priv::update_restart_background_process(bool force_update_scene, bool force_update_preview) { // bitmask of UpdateBackgroundProcessReturnState unsigned int state = this->update_background_process(); - if (state & UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE) + if (force_update_scene || (state & UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE) != 0) #if ENABLE_REMOVE_TABS_FROM_PLATER view3D->reload_scene(false); #else this->canvas3D->reload_scene(false); #endif // ENABLE_REMOVE_TABS_FROM_PLATER - if ((state & UPDATE_BACKGROUND_PROCESS_RESTART) != 0 && this->background_processing_enabled()) { - // The print is valid and it can be started. - if (this->background_process.start()) - this->statusbar()->set_cancel_callback([this]() { - this->statusbar()->set_status_text(L("Cancelling")); - this->background_process.stop(); - }); - } + if (force_update_preview) + this->preview->reload_print(); + this->restart_background_process(state); } void Plater::priv::update_fff_scene() @@ -2135,15 +2155,8 @@ void Plater::priv::update_sla_scene() { // Update the SLAPrint from the current Model, so that the reload_scene() // pulls the correct data. - if (this->update_background_process() & UPDATE_BACKGROUND_PROCESS_RESTART) - this->schedule_background_process(); -#if ENABLE_REMOVE_TABS_FROM_PLATER - view3D->reload_scene(true); -#else - this->canvas3D->reload_scene(true); -#endif // ENABLE_REMOVE_TABS_FROM_PLATER delayed_scene_refresh = false; - this->preview->reload_print(); + this->update_restart_background_process(true, true); } void Plater::priv::reload_from_disk() @@ -2242,10 +2255,9 @@ void Plater::priv::set_current_panel(wxPanel* panel) { // Update the SLAPrint from the current Model, so that the reload_scene() // pulls the correct data. - if (this->update_background_process() & UPDATE_BACKGROUND_PROCESS_RESTART) - this->schedule_background_process(); - } - view3D->reload_scene(true); + this->update_restart_background_process(true, false); + } else + view3D->reload_scene(true); } // sets the canvas as dirty to force a render at the 1st idle event (wxWidgets IsShownOnScreen() is buggy and cannot be used reliably) view3D->set_as_dirty(); @@ -2277,10 +2289,9 @@ void Plater::priv::on_notebook_changed(wxBookCtrlEvent&) if (this->printer_technology == ptSLA) { // Update the SLAPrint from the current Model, so that the reload_scene() // pulls the correct data. - if (this->update_background_process() & UPDATE_BACKGROUND_PROCESS_RESTART) - this->schedule_background_process(); - } - this->canvas3D->reload_scene(true); + this->update_restart_background_process(true, false); + } else + this->canvas3D->reload_scene(true); } // sets the canvas as dirty to force a render at the 1st idle event (wxWidgets IsShownOnScreen() is buggy and cannot be used reliably) this->canvas3D->set_as_dirty(); @@ -3143,14 +3154,8 @@ void Plater::reslice() #else this->p->canvas3D->reload_scene(false); #endif // ENABLE_REMOVE_TABS_FROM_PLATER - if ((state & priv::UPDATE_BACKGROUND_PROCESS_INVALID) == 0 && !this->p->background_process.running() && !this->p->background_process.finished()) { - // The print is valid and it can be started. - if (this->p->background_process.start()) - this->p->statusbar()->set_cancel_callback([this]() { - this->p->statusbar()->set_status_text(L("Cancelling")); - this->p->background_process.stop(); - }); - } + // Only restarts if the state is valid. + this->p->restart_background_process(state | priv::UPDATE_BACKGROUND_PROCESS_FORCE_RESTART); } void Plater::send_gcode() @@ -3341,13 +3346,13 @@ void Plater::changed_object(int obj_idx) model_object->ensure_on_bed(); if (this->p->printer_technology == ptSLA) { // Update the SLAPrint from the current Model, so that the reload_scene() - // pulls the correct data. - this->p->update_background_process(); - } + // pulls the correct data, update the 3D scene. + this->p->update_restart_background_process(true, false); + } else #if ENABLE_REMOVE_TABS_FROM_PLATER - p->view3D->reload_scene(false); + p->view3D->reload_scene(false); #else - p->canvas3D->reload_scene(false); + p->canvas3D->reload_scene(false); #endif // ENABLE_REMOVE_TABS_FROM_PLATER } diff --git a/src/slic3r/Utils/PresetUpdater.cpp b/src/slic3r/Utils/PresetUpdater.cpp index be2a17d66..bfa3af3e6 100644 --- a/src/slic3r/Utils/PresetUpdater.cpp +++ b/src/slic3r/Utils/PresetUpdater.cpp @@ -256,7 +256,7 @@ void PresetUpdater::priv::sync_config(const std::set vendors) Index new_index; try { new_index.load(idx_path_temp); - } catch (const std::exception &err) { + } catch (const std::exception & /* err */) { BOOST_LOG_TRIVIAL(error) << boost::format("Failed loading a downloaded index %1% for vendor %2%: invalid index?") % idx_path_temp % vendor.name; continue; }