diff --git a/src/libslic3r/PrintBase.hpp b/src/libslic3r/PrintBase.hpp index 154fa3649..e70edd20d 100644 --- a/src/libslic3r/PrintBase.hpp +++ b/src/libslic3r/PrintBase.hpp @@ -254,8 +254,13 @@ public: // If non-negative, stop processing at the successive print step. int to_print_step; }; - + // After calling the apply() function, call set_task() to limit the task to be processed by process(). + virtual void set_task(const TaskParams ¶ms) {} + // Perform the calculation. This is the only method that is to be called at a worker thread. virtual void process() = 0; + // 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() {} 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.cpp b/src/libslic3r/SLAPrint.cpp index 0c486e95a..213437612 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -402,13 +402,14 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf return static_cast(apply_status); } +// After calling the apply() function, set_task() may be called to limit the task to be processed by process(). void SLAPrint::set_task(const TaskParams ¶ms) { // Grab the lock for the Print / PrintObject milestones. tbb::mutex::scoped_lock lock(this->state_mutex()); - int n_object_steps = params.to_object_step + 1; - if (n_object_steps = 0) + int n_object_steps = int(params.to_object_step) + 1; + if (n_object_steps == 0) n_object_steps = (int)slaposCount; if (params.single_model_object.valid()) { @@ -442,7 +443,7 @@ void SLAPrint::set_task(const TaskParams ¶ms) // Suppress all the steps of other instances. for (SLAPrintObject *po : m_objects) for (int istep = 0; istep < (int)slaposCount; ++istep) - print_object->m_stepmask[istep] = false; + po->m_stepmask[istep] = false; } else if (!running) { // Swap the print objects, so that the selected print_object is first in the row. @@ -452,9 +453,27 @@ void SLAPrint::set_task(const TaskParams ¶ms) } for (int istep = 0; istep < n_object_steps; ++ istep) print_object->m_stepmask[istep] = true; - for (int istep = 0; istep < (int)slaposCount; ++ istep) + for (int istep = n_object_steps; istep < (int)slaposCount; ++istep) print_object->m_stepmask[istep] = false; } + + if (params.to_object_step != -1 || params.to_print_step != -1) { + // Limit the print steps. + size_t istep = (params.to_object_step != -1) ? 0 : size_t(params.to_print_step) + 1; + for (; istep < m_stepmask.size(); ++ istep) + m_stepmask[istep] = false; + } +} + +// Clean up after process() finished, either with success, error or if canceled. +// The adjustments on the SLAPrint / SLAPrintObject data due to set_task() are to be reverted here. +void SLAPrint::finalize() +{ + for (SLAPrintObject *po : m_objects) + for (int istep = 0; istep < (int)slaposCount; ++ istep) + po->m_stepmask[istep] = true; + for (int istep = 0; istep < (int)slapsCount; ++ istep) + m_stepmask[istep] = true; } namespace { diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index be862095c..68a0d34aa 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -195,8 +195,9 @@ public: void clear() override; bool empty() const override { return m_objects.empty(); } ApplyStatus apply(const Model &model, const DynamicPrintConfig &config) override; - void set_task(const TaskParams ¶ms); + void set_task(const TaskParams ¶ms) override; void process() override; + void finalize() 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 463be8397..7c8164f6b 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.cpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.cpp @@ -196,6 +196,7 @@ void BackgroundSlicingProcess::thread_proc() } catch (...) { error = "Unknown C++ exception."; } + m_print->finalize(); lck.lock(); m_state = m_print->canceled() ? STATE_CANCELED : STATE_FINISHED; if (m_print->cancel_status() != Print::CANCELED_INTERNAL) { @@ -362,6 +363,12 @@ Print::ApplyStatus BackgroundSlicingProcess::apply(const Model &model, const Dyn return invalidated; } +void BackgroundSlicingProcess::set_task(const PrintBase::TaskParams ¶ms) +{ + assert(m_print != nullptr); + m_print->set_task(params); +} + // Set the output path of the G-code. void BackgroundSlicingProcess::schedule_export(const std::string &path) { diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.hpp b/src/slic3r/GUI/BackgroundSlicingProcess.hpp index 5911c8a02..a2299e7bf 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.hpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.hpp @@ -78,6 +78,9 @@ public: // Apply config over the print. Returns false, if the new config values caused any of the already // processed steps to be invalidated, therefore the task will need to be restarted. Print::ApplyStatus apply(const Model &model, const DynamicPrintConfig &config); + // After calling the apply() function, set_task() may be called to limit the task to be processed by process(). + // This is useful for calculating SLA supports for a single object only. + void set_task(const PrintBase::TaskParams ¶ms); // After calling apply, the empty() call will report whether there is anything to slice. bool empty() const; // Validate the print. Returns an empty string if valid, returns an error message if invalid. @@ -94,6 +97,7 @@ public: void reset_export(); // Once the G-code export is scheduled, the apply() methods will do nothing. bool is_export_scheduled() const { return ! m_export_path.empty(); } + bool is_upload_scheduled() const { return ! m_upload_job.empty(); } enum State { // m_thread is not running yet, or it did not reach the STATE_IDLE yet (it does not wait on the condition yet). diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index a59ea8dad..5056fe72e 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2032,6 +2032,13 @@ unsigned int Plater::priv::update_background_process(bool force_validation) wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, evt.Clone()); } + //FIXME update "Slice Now / Schedule background process" + //background_process.is_export_scheduled() - byl zavolan "Export G-code", background processing ma jmeno export souboru + //background_process.is_upload_scheduled() - byl zavolan "Send to OctoPrint", jeste nebylo doslajsovano (pak se preda upload fronte a background process zapomene) + //background_process.empty() - prazdna plocha + // pokud (invalidated != Print::APPLY_STATUS_UNCHANGED) a ! background_process.empty() -> je neco ke slajsovani (povol tlacitko) + // pokud (return_state & UPDATE_BACKGROUND_PROCESS_INVALID) != 0 -> doslo k chybe (gray out "Slice now") + return return_state; } @@ -2999,6 +3006,32 @@ void Plater::reslice() this->p->restart_background_process(state | priv::UPDATE_BACKGROUND_PROCESS_FORCE_RESTART); } +void Plater::reslice_SLA_supports(const ModelObject &object) +{ + //FIXME Don't reslice if export of G-code or sending to OctoPrint is running. + // bitmask of UpdateBackgroundProcessReturnState + unsigned int state = this->p->update_background_process(true); + if (state & priv::UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE) + this->p->view3D->reload_scene(false); + + if (this->p->background_process.empty() || (state & priv::UPDATE_BACKGROUND_PROCESS_INVALID)) + // Nothing to do on empty input or invalid configuration. + return; + + // Limit calculation to the single object only. + PrintBase::TaskParams task; + task.single_model_object = object.id(); + // If the background processing is not enabled, calculate supports just for the single instance. + // Otherwise calculate everything, but start with the provided object. + if (!this->p->background_processing_enabled()) { + task.single_model_instance_only = true; + task.to_object_step = slaposBasePool; + } + this->p->background_process.set_task(task); + // and let the background processing start. + this->p->restart_background_process(state | priv::UPDATE_BACKGROUND_PROCESS_FORCE_RESTART); +} + void Plater::send_gcode() { if (p->model.objects.empty()) { return; } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 5dfe5528d..ddd8cd5bd 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -19,6 +19,7 @@ class wxString; namespace Slic3r { class Model; +class ModelObject; class Print; class SLAPrint; @@ -145,6 +146,7 @@ public: void export_amf(); void export_3mf(const boost::filesystem::path& output_path = boost::filesystem::path()); void reslice(); + void reslice_SLA_supports(const ModelObject &object); void changed_object(int obj_idx); void fix_through_netfabb(const int obj_idx, const int vol_idx = -1); void send_gcode();