diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 6416a709a..d47cdf99f 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -280,7 +280,7 @@ bool Print::is_step_done(PrintObjectStep step) const return false; tbb::mutex::scoped_lock lock(this->state_mutex()); for (const PrintObject *object : m_objects) - if (! object->m_state.is_done_unguarded(step)) + if (! object->is_step_done_unguarded(step)) return false; return true; } @@ -549,10 +549,14 @@ void Print::model_volume_list_update_supports(ModelObject &model_object_dst, con assert(! it->second); // not consumed yet it->second = true; ModelVolume *model_volume_dst = const_cast(it->first); - assert(model_volume_dst->type() == model_volume_src->type()); + // For support modifiers, the type may have been switched from blocker to enforcer and vice versa. + assert((model_volume_dst->is_support_modifier() && model_volume_src->is_support_modifier()) || model_volume_dst->type() == model_volume_src->type()); model_object_dst.volumes.emplace_back(model_volume_dst); - if (model_volume_dst->is_support_modifier()) - model_volume_dst->set_transformation(model_volume_src->get_transformation()); + if (model_volume_dst->is_support_modifier()) { + // For support modifiers, the type may have been switched from blocker to enforcer and vice versa. + model_volume_dst->set_type(model_volume_src->type()); + model_volume_dst->set_transformation(model_volume_src->get_transformation()); + } assert(model_volume_dst->get_matrix().isApprox(model_volume_src->get_matrix())); } else { // The volume was not found in the old list. Create a new copy. diff --git a/src/libslic3r/PrintBase.hpp b/src/libslic3r/PrintBase.hpp index f67ec4b72..154fa3649 100644 --- a/src/libslic3r/PrintBase.hpp +++ b/src/libslic3r/PrintBase.hpp @@ -62,6 +62,10 @@ public: return state; } + bool is_started(StepType step, tbb::mutex &mtx) const { + return this->state_with_timestamp(step, mtx).state == STARTED; + } + bool is_done(StepType step, tbb::mutex &mtx) const { return this->state_with_timestamp(step, mtx).state == DONE; } @@ -70,6 +74,10 @@ public: return m_state[step]; } + bool is_started_unguarded(StepType step) const { + return this->state_with_timestamp_unguarded(step).state == STARTED; + } + bool is_done_unguarded(StepType step) const { return this->state_with_timestamp_unguarded(step).state == DONE; } @@ -235,6 +243,18 @@ public: virtual ApplyStatus apply(const Model &model, const DynamicPrintConfig &config) = 0; const Model& model() const { return m_model; } + struct TaskParams { + TaskParams() : single_model_object(0), single_model_instance_only(false), to_object_step(-1), to_print_step(-1) {} + // If non-empty, limit the processing to this ModelObject. + ModelID single_model_object; + // If set, only process single_model_object. Otherwise process everything, but single_model_object first. + bool single_model_instance_only; + // If non-negative, stop processing at the successive object step. + int to_object_step; + // If non-negative, stop processing at the successive print step. + int to_print_step; + }; + virtual void process() = 0; struct SlicingStatus { @@ -350,6 +370,9 @@ protected: bool invalidate_all_steps() { return m_state.invalidate_all(this->cancel_callback()); } + bool is_step_started_unguarded(PrintStepEnum step) const { return m_state.is_started_unguarded(step); } + bool is_step_done_unguarded(PrintStepEnum step) const { return m_state.is_done_unguarded(step); } + private: PrintState m_state; }; @@ -383,6 +406,9 @@ protected: bool invalidate_all_steps() { return m_state.invalidate_all(PrintObjectBase::cancel_callback(m_print)); } + bool is_step_started_unguarded(PrintObjectStepEnum step) const { return m_state.is_started_unguarded(step); } + bool is_step_done_unguarded(PrintObjectStepEnum step) const { return m_state.is_done_unguarded(step); } + protected: // If the background processing stop was requested, throw CanceledException. // To be called by the worker thread and its sub-threads (mostly launched on the TBB thread pool) regularly. diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index f25087cbe..0c486e95a 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -51,7 +51,7 @@ const std::array OBJ_STEP_LABELS = L("Slicing model"), // slaposObjectSlice, L("Generating support points"), // slaposSupportPoints, L("Generating support tree"), // slaposSupportTree, - L("Generating base pool"), // slaposBasePool, + L("Generating pad"), // slaposBasePool, L("Slicing supports"), // slaposSliceSupports, L("Slicing supports") // slaposIndexSlices, }; @@ -402,6 +402,61 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf return static_cast(apply_status); } +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) + n_object_steps = (int)slaposCount; + + if (params.single_model_object.valid()) { + SLAPrintObject *print_object = nullptr; + size_t idx_print_object = 0; + for (; idx_print_object < m_objects.size(); ++idx_print_object) + if (m_objects[idx_print_object]->model_object()->id() == params.single_model_object) { + print_object = m_objects[idx_print_object]; + break; + } + assert(print_object != nullptr); + bool shall_cancel = false; + for (int istep = 0; istep < n_object_steps; ++istep) + if (! print_object->m_stepmask[istep]) { + shall_cancel = true; + break; + } + bool running = false; + if (!shall_cancel) { + for (int istep = 0; istep < n_object_steps; ++ istep) + if (print_object->is_step_started_unguarded(SLAPrintObjectStep(istep))) { + running = true; + break; + } + } + if (!running) + this->cancel_callback(); + + // Now the background process is either stopped, or it is inside one of the print object steps to be calculated anyway. + if (params.single_model_instance_only) { + // 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; + } + else if (!running) { + // Swap the print objects, so that the selected print_object is first in the row. + // At this point the background processing must be stopped, so it is safe to shuffle print objects. + if (idx_print_object != 0) + std::swap(m_objects.front(), m_objects[idx_print_object]); + } + for (int istep = 0; istep < n_object_steps; ++ istep) + print_object->m_stepmask[istep] = true; + for (int istep = 0; istep < (int)slaposCount; ++ istep) + print_object->m_stepmask[istep] = false; + } +} + namespace { // Compile the argument for support creation from the static print config. sla::SupportConfig make_support_cfg(const SLAPrintObjectConfig& c) { @@ -1035,7 +1090,7 @@ bool SLAPrint::is_step_done(SLAPrintObjectStep step) const return false; tbb::mutex::scoped_lock lock(this->state_mutex()); for (const SLAPrintObject *object : m_objects) - if (! object->m_state.is_done_unguarded(step)) + if (! object->is_step_done_unguarded(step)) return false; return true; } diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index 9aaba6a47..be862095c 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -139,6 +139,10 @@ protected: // Invalidate steps based on a set of parameters changed. bool invalidate_state_by_config_options(const std::vector &opt_keys); + // Which steps have to be performed. Implicitly: all + // to be accessible from SLAPrint + std::vector m_stepmask; + private: // Object specific configuration, pulled from the configuration layer. SLAPrintObjectConfig m_config; @@ -146,9 +150,6 @@ private: Transform3d m_trafo = Transform3d::Identity(); std::vector m_instances; - // Which steps have to be performed. Implicitly: all - std::vector m_stepmask; - // Individual 2d slice polygons from lower z to higher z levels std::vector m_model_slices; @@ -194,6 +195,7 @@ 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 process() 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;