From 4b0fe7cba4140444d45ba5a5256f9dca36fecc7b Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 15 Oct 2019 15:42:30 +0200 Subject: [PATCH] Implemented custom extruder(tool) change from DoubleSlider --- src/libslic3r/Model.cpp | 15 +++++ src/libslic3r/Model.hpp | 3 + src/libslic3r/Print.cpp | 74 ++++++++++++++++++--- src/libslic3r/Print.hpp | 6 ++ src/slic3r/GUI/BackgroundSlicingProcess.hpp | 5 ++ src/slic3r/GUI/Plater.cpp | 1 + 6 files changed, 95 insertions(+), 9 deletions(-) diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 061c5bd50..6123be037 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -586,6 +586,21 @@ std::string Model::propose_export_file_name_and_path(const std::string &new_exte return boost::filesystem::path(this->propose_export_file_name_and_path()).replace_extension(new_extension).string(); } +std::vector> Model:: get_custom_tool_changes(double default_layer_height) const +{ + std::vector> custom_tool_changes; + if (!custom_gcode_per_height.empty()) { + for (const CustomGCode& custom_gcode : custom_gcode_per_height) + if (custom_gcode.gcode == "tool_change") { + DynamicPrintConfig config; + config.set_key_value("extruder", new ConfigOptionInt(custom_gcode.extruder)); + // For correct extruders(tools) changing, we should decrease custom_gcode.height value by one default layer height + custom_tool_changes.push_back({ custom_gcode.height - default_layer_height, config }); + } + } + return custom_tool_changes; +} + ModelObject::~ModelObject() { this->clear_volumes(); diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 05147f9dd..d78dbdfa6 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -836,6 +836,9 @@ public: // Propose an output path, replace extension. The new_extension shall contain the initial dot. std::string propose_export_file_name_and_path(const std::string &new_extension) const; + // from custom_gcode_per_height get just tool_change codes + std::vector> get_custom_tool_changes(double default_layer_height) const; + private: explicit Model(int) : ObjectBase(-1) { assert(this->id().invalid()); }; void assign_new_unique_ids_recursive(); diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 3212082a3..d3451265e 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -636,11 +636,59 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ else m_ranges.emplace_back(t_layer_height_range(m_ranges.back().first.second, DBL_MAX), nullptr); } + + // Convert input config ranges into continuous non-overlapping sorted vector of intervals and their configs, + // considering custom_tool_change values + void assign(const t_layer_config_ranges &in, const std::vector> &custom_tool_changes) { + m_ranges.clear(); + m_ranges.reserve(in.size()); + // Input ranges are sorted lexicographically. First range trims the other ranges. + coordf_t last_z = 0; + for (const std::pair &range : in) + if (range.first.second > last_z) { + coordf_t min_z = std::max(range.first.first, 0.); + if (min_z > last_z + EPSILON) { + m_ranges.emplace_back(t_layer_height_range(last_z, min_z), nullptr); + last_z = min_z; + } + if (range.first.second > last_z + EPSILON) { + const DynamicPrintConfig* cfg = &range.second; + m_ranges.emplace_back(t_layer_height_range(last_z, range.first.second), cfg); + last_z = range.first.second; + } + } + + // add ranges for extruder changes from custom_tool_changes + for (size_t i = 0; i < custom_tool_changes.size(); i++) { + const DynamicPrintConfig* cfg = &custom_tool_changes[i].second; + coordf_t cur_Z = custom_tool_changes[i].first; + coordf_t next_Z = i == custom_tool_changes.size()-1 ? DBL_MAX : custom_tool_changes[i+1].first; + if (cur_Z > last_z + EPSILON) { + if (i==0) + m_ranges.emplace_back(t_layer_height_range(last_z, cur_Z), nullptr); + m_ranges.emplace_back(t_layer_height_range(cur_Z, next_Z), cfg); + } + else if (next_Z > last_z + EPSILON) + m_ranges.emplace_back(t_layer_height_range(last_z, next_Z), cfg); + } + + if (m_ranges.empty()) + m_ranges.emplace_back(t_layer_height_range(0, DBL_MAX), nullptr); + else if (m_ranges.back().second == nullptr) + m_ranges.back().first.second = DBL_MAX; + else if (m_ranges.back().first.second != DBL_MAX) + m_ranges.emplace_back(t_layer_height_range(m_ranges.back().first.second, DBL_MAX), nullptr); + } const DynamicPrintConfig* config(const t_layer_height_range &range) const { auto it = std::lower_bound(m_ranges.begin(), m_ranges.end(), std::make_pair< t_layer_height_range, const DynamicPrintConfig*>(t_layer_height_range(range.first - EPSILON, range.second - EPSILON), nullptr)); - assert(it != m_ranges.end()); - assert(it == m_ranges.end() || std::abs(it->first.first - range.first ) < EPSILON); - assert(it == m_ranges.end() || std::abs(it->first.second - range.second) < EPSILON); + // #ys_FIXME_COLOR + // assert(it != m_ranges.end()); + // assert(it == m_ranges.end() || std::abs(it->first.first - range.first ) < EPSILON); + // assert(it == m_ranges.end() || std::abs(it->first.second - range.second) < EPSILON); + if (it == m_ranges.end() || + std::abs(it->first.first - range.first) > EPSILON || + std::abs(it->first.second - range.second) > EPSILON ) + return nullptr; // desired range doesn't found return (it == m_ranges.end()) ? nullptr : it->second; } std::vector>::const_iterator begin() const { return m_ranges.cbegin(); } @@ -688,6 +736,13 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ // The object list did not change. for (const ModelObject *model_object : m_model.objects) model_object_status.emplace(model_object->id(), ModelObjectStatus::Old); + + // But if custom gcode per layer height was changed + if (m_model.custom_gcode_per_height != model.custom_gcode_per_height) { + // we should stop background processing + update_apply_status(this->invalidate_step(psGCodeExport)); + m_model.custom_gcode_per_height = model.custom_gcode_per_height; + } } else if (model_object_list_extended(m_model, model)) { // Add new objects. Their volumes and configs will be synchronized later. update_apply_status(this->invalidate_step(psGCodeExport)); @@ -749,11 +804,6 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ delete model_object; } } - if (model.custom_gcode_per_height != m_model.custom_gcode_per_height) - { - update_apply_status(this->invalidate_step(psGCodeExport)); - m_model.custom_gcode_per_height = model.custom_gcode_per_height; - } } // 2) Map print objects including their transformation matrices. @@ -784,6 +834,8 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ for (PrintObject *print_object : m_objects) print_object_status.emplace(PrintObjectStatus(print_object)); + std::vector> custom_tool_changes = m_model.get_custom_tool_changes(m_default_object_config.layer_height); + // 3) Synchronize ModelObjects & PrintObjects. for (size_t idx_model_object = 0; idx_model_object < model.objects.size(); ++ idx_model_object) { ModelObject &model_object = *m_model.objects[idx_model_object]; @@ -791,7 +843,9 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ assert(it_status != model_object_status.end()); assert(it_status->status != ModelObjectStatus::Deleted); const ModelObject& model_object_new = *model.objects[idx_model_object]; - const_cast(*it_status).layer_ranges.assign(model_object_new.layer_config_ranges); + // ys_FIXME_COLOR + // const_cast(*it_status).layer_ranges.assign(model_object_new.layer_config_ranges); + const_cast(*it_status).layer_ranges.assign(model_object_new.layer_config_ranges, custom_tool_changes); if (it_status->status == ModelObjectStatus::New) // PrintObject instances will be added in the next loop. continue; @@ -959,6 +1013,8 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ PrintRegionConfig this_region_config; bool this_region_config_set = false; for (PrintObject *print_object : m_objects) { + if(m_force_update_print_regions && !custom_tool_changes.empty()) + goto print_object_end; const LayerRanges *layer_ranges; { auto it_status = model_object_status.find(ModelObjectStatus(print_object->model_object()->id())); diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 6d94a515f..d5810f057 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -361,6 +361,9 @@ public: // Accessed by SupportMaterial const PrintRegion* get_region(size_t idx) const { return m_regions[idx]; } + // force update of PrintRegions, when custom_tool_change is not empty and (Re)Slicing is started + void set_force_update_print_regions(bool force_update_print_regions) { m_force_update_print_regions = force_update_print_regions; } + protected: // methods for handling regions PrintRegion* get_region(size_t idx) { return m_regions[idx]; } @@ -403,6 +406,9 @@ private: // Estimated print time, filament consumed. PrintStatistics m_print_statistics; + // flag used + bool m_force_update_print_regions = false; + // To allow GCode to set the Print's GCodeExport step status. friend class GCode; // Allow PrintObject to access m_mutex and m_cancel_callback. diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.hpp b/src/slic3r/GUI/BackgroundSlicingProcess.hpp index cf5edd55f..e389c1e86 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.hpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.hpp @@ -128,6 +128,11 @@ public: // This "finished" flag does not account for the final export of the output file (.gcode or zipped PNGs), // and it does not account for the OctoPrint scheduling. bool finished() const { return m_print->finished(); } + + void set_force_update_print_regions(bool force_update_print_regions) { + if (m_fff_print) + m_fff_print->set_force_update_print_regions(force_update_print_regions); + } private: void thread_proc(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index fc80cb306..96af17999 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2922,6 +2922,7 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool this->update_print_volume_state(); // Apply new config to the possibly running background task. bool was_running = this->background_process.running(); + this->background_process.set_force_update_print_regions(force_validation); 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.