From fb5cba2c113c381c7ac6de4b5bff4eddf5072f08 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 17 Apr 2024 21:29:23 +0200 Subject: [PATCH 01/13] Remove dead code --- include/PrimeTower.h | 1 - src/PrimeTower.cpp | 16 ---------------- 2 files changed, 17 deletions(-) diff --git a/include/PrimeTower.h b/include/PrimeTower.h index b11522643d..3be44656b7 100644 --- a/include/PrimeTower.h +++ b/include/PrimeTower.h @@ -60,7 +60,6 @@ class PrimeTower public: bool enabled_; //!< Whether the prime tower is enabled. bool would_have_actual_tower_; //!< Whether there is an actual tower. - bool multiple_extruders_on_first_layer_; //!< Whether multiple extruders are allowed on the first layer of the prime tower (e.g. when a raft is there) /* * In which order, from outside to inside, will we be printing the prime diff --git a/src/PrimeTower.cpp b/src/PrimeTower.cpp index f9ebcb4f4c..b6cff0db10 100644 --- a/src/PrimeTower.cpp +++ b/src/PrimeTower.cpp @@ -32,22 +32,6 @@ PrimeTower::PrimeTower() const Scene& scene = Application::getInstance().current_slice_->scene; PrimeTowerMethod method = scene.current_mesh_group->settings.get("prime_tower_mode"); - { - EPlatformAdhesion adhesion_type = scene.current_mesh_group->settings.get("adhesion_type"); - - // When we have multiple extruders sharing the same heater/nozzle, we expect that all the extruders have been - //'primed' by the print-start gcode script, but we don't know which one has been left at the tip of the nozzle - // and whether it needs 'purging' (before extruding a pure material) or not, so we need to prime (actually purge) - // each extruder before it is used for the model. This can done by the (per-extruder) brim lines or (per-extruder) - // skirt lines when they are used, but we need to do that inside the first prime-tower layer when they are not - // used (sacrifying for this purpose the usual single-extruder first layer, that would be better for prime-tower - // adhesion). - - multiple_extruders_on_first_layer_ = (method == PrimeTowerMethod::INTERLEAVED) || (method == PrimeTowerMethod::NORMAL) - || (scene.current_mesh_group->settings.get("machine_extruders_share_nozzle") - && ((adhesion_type != EPlatformAdhesion::SKIRT) && (adhesion_type != EPlatformAdhesion::BRIM))); - } - enabled_ = scene.current_mesh_group->settings.get("prime_tower_enable") && scene.current_mesh_group->settings.get("prime_tower_min_volume") > 10 && scene.current_mesh_group->settings.get("prime_tower_size") > 10; From 1a533d95941095cf6219553a3015e5a29fa33bda Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 18 Apr 2024 09:06:38 +0200 Subject: [PATCH 02/13] Code simplification --- include/PrimeTower.h | 1 - src/PrimeTower.cpp | 12 +++++------- src/raft.cpp | 14 -------------- 3 files changed, 5 insertions(+), 22 deletions(-) diff --git a/include/PrimeTower.h b/include/PrimeTower.h index 3be44656b7..e6d7f0f011 100644 --- a/include/PrimeTower.h +++ b/include/PrimeTower.h @@ -59,7 +59,6 @@ class PrimeTower public: bool enabled_; //!< Whether the prime tower is enabled. - bool would_have_actual_tower_; //!< Whether there is an actual tower. /* * In which order, from outside to inside, will we be printing the prime diff --git a/src/PrimeTower.cpp b/src/PrimeTower.cpp index b6cff0db10..45db27f6a1 100644 --- a/src/PrimeTower.cpp +++ b/src/PrimeTower.cpp @@ -30,12 +30,9 @@ PrimeTower::PrimeTower() : wipe_from_middle_(false) { const Scene& scene = Application::getInstance().current_slice_->scene; - PrimeTowerMethod method = scene.current_mesh_group->settings.get("prime_tower_mode"); enabled_ = scene.current_mesh_group->settings.get("prime_tower_enable") && scene.current_mesh_group->settings.get("prime_tower_min_volume") > 10 && scene.current_mesh_group->settings.get("prime_tower_size") > 10; - - would_have_actual_tower_ = enabled_; // Assume so for now. } void PrimeTower::initializeExtruders(const std::vector& used_extruders) @@ -96,10 +93,11 @@ void PrimeTower::generatePaths(const SliceDataStorage& storage) { checkUsed(); + // Maybe it turns out that we don't need a prime tower after all because there are no layer switches. const int raft_total_extra_layers = Raft::getTotalExtraLayers(); - would_have_actual_tower_ = storage.max_print_height_second_to_last_extruder - >= -raft_total_extra_layers; // Maybe it turns out that we don't need a prime tower after all because there are no layer switches. - if (would_have_actual_tower_ && enabled_) + enabled_ &= storage.max_print_height_second_to_last_extruder >= -raft_total_extra_layers; + + if (enabled_) { generateGroundpoly(); @@ -312,7 +310,7 @@ void PrimeTower::addToGcode( const size_t prev_extruder_nr, const size_t new_extruder_nr) const { - if (! (enabled_ && would_have_actual_tower_)) + if (! enabled_) { return; } diff --git a/src/raft.cpp b/src/raft.cpp index 4b27f0911f..c24ce0d691 100644 --- a/src/raft.cpp +++ b/src/raft.cpp @@ -125,20 +125,6 @@ void Raft::generate(SliceDataStorage& storage) settings.get("raft_surface_remove_inside_corners"), settings.get("raft_surface_smoothing"), nominal_raft_line_width); - - if (storage.primeTower.enabled_ && ! storage.primeTower.would_have_actual_tower_) - { - // Find out if the prime-tower part of the raft still needs to be printed, even if there is no actual tower. - // This will only happen if the different raft layers are printed by different extruders. - const Settings& mesh_group_settings = Application::getInstance().current_slice_->scene.current_mesh_group->settings; - const size_t base_extruder_nr = mesh_group_settings.get("raft_base_extruder_nr").extruder_nr_; - const size_t interface_extruder_nr = mesh_group_settings.get("raft_interface_extruder_nr").extruder_nr_; - const size_t surface_extruder_nr = mesh_group_settings.get("raft_surface_extruder_nr").extruder_nr_; - if (base_extruder_nr == interface_extruder_nr && base_extruder_nr == surface_extruder_nr) - { - return; - } - } } coord_t Raft::getTotalThickness() From ec881b0b8a51fdf0b3f0beac94e9f79fe576a9d9 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 18 Apr 2024 21:26:51 +0200 Subject: [PATCH 03/13] Fixed missing interleaved prime tower raft layer --- include/raft.h | 15 +++++++++++++++ src/FffGcodeWriter.cpp | 21 +++------------------ src/raft.cpp | 35 +++++++++++++++++++++++++++++------ src/sliceDataStorage.cpp | 6 +++--- 4 files changed, 50 insertions(+), 27 deletions(-) diff --git a/include/raft.h b/include/raft.h index b6f837f53e..67eb7145c5 100644 --- a/include/raft.h +++ b/include/raft.h @@ -55,6 +55,18 @@ class Raft */ static size_t getTotalExtraLayers(); + /*! + * \brief Get the amount of bottom for the raft interface. + * \note This is currently hard-coded to 1 because we have yet no setting for the bottom + */ + static size_t getBottomLayers(); + + /*! \brief Get the amount of layers for the raft interface. */ + static size_t getInterfaceLayers(); + + /*! \brief Get the amount of layers for the raft top. */ + static size_t getSurfaceLayers(); + enum LayerType { RaftBase, @@ -70,6 +82,9 @@ class Raft * \return The type of layer at the given layer index. */ static LayerType getLayerType(LayerIndex layer_index); + +private: + static size_t getLayersAmount(const std::string& extruder_nr, const std::string& layers_nr); }; } // namespace cura diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index e055d99a9c..626be418d7 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -570,7 +570,6 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) const size_t base_extruder_nr = mesh_group_settings.get("raft_base_extruder_nr").extruder_nr_; const size_t interface_extruder_nr = mesh_group_settings.get("raft_interface_extruder_nr").extruder_nr_; const size_t surface_extruder_nr = mesh_group_settings.get("raft_surface_extruder_nr").extruder_nr_; - const size_t prime_tower_extruder_nr = storage.primeTower.extruder_order_.front(); coord_t z = 0; const LayerIndex initial_raft_layer_nr = -Raft::getTotalExtraLayers(); @@ -782,12 +781,6 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) interface_line_width, interface_avoid_distance); - if (! prime_tower_added_on_this_layer && current_extruder_nr == prime_tower_extruder_nr) - { - addPrimeTower(storage, gcode_layer, current_extruder_nr); - prime_tower_added_on_this_layer = true; - } - gcode_layer.setIsInside(true); if (interface_extruder_nr != current_extruder_nr) { @@ -908,8 +901,7 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) if (! prime_tower_added_on_this_layer) { - setExtruder_addPrime(storage, gcode_layer, prime_tower_extruder_nr); - current_extruder_nr = prime_tower_extruder_nr; + addPrimeTower(storage, gcode_layer, current_extruder_nr); } layer_plan_buffer.handle(gcode_layer, gcode); @@ -952,12 +944,6 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) surface_line_width, surface_avoid_distance); - if (! prime_tower_added_on_this_layer && current_extruder_nr == prime_tower_extruder_nr) - { - addPrimeTower(storage, gcode_layer, current_extruder_nr); - prime_tower_added_on_this_layer = true; - } - gcode_layer.setIsInside(true); // make sure that we are using the correct extruder to print raft @@ -1098,8 +1084,7 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) if (! prime_tower_added_on_this_layer) { - setExtruder_addPrime(storage, gcode_layer, prime_tower_extruder_nr); - current_extruder_nr = prime_tower_extruder_nr; + addPrimeTower(storage, gcode_layer, current_extruder_nr); } layer_plan_buffer.handle(gcode_layer, gcode); @@ -1620,7 +1605,7 @@ std::vector FffGcodeWriter::getUsedExtrudersOnLayer( } } - // Now check whether extuders should really used, and how + // Now check whether extuders should really be used, and how size_t last_extruder = start_extruder; for (size_t extruder_nr : ordered_extruders) { diff --git a/src/raft.cpp b/src/raft.cpp index c24ce0d691..c708271ac4 100644 --- a/src/raft.cpp +++ b/src/raft.cpp @@ -168,18 +168,29 @@ coord_t Raft::getFillerLayerHeight() return round_divide(getZdiffBetweenRaftAndLayer0(), getFillerLayerCount()); } - size_t Raft::getTotalExtraLayers() +{ + return getBottomLayers() + getInterfaceLayers() + getSurfaceLayers() + getFillerLayerCount(); +} + +size_t Raft::getBottomLayers() { const Settings& mesh_group_settings = Application::getInstance().current_slice_->scene.current_mesh_group->settings; - const ExtruderTrain& base_train = mesh_group_settings.get("raft_base_extruder_nr"); - const ExtruderTrain& interface_train = mesh_group_settings.get("raft_interface_extruder_nr"); - const ExtruderTrain& surface_train = mesh_group_settings.get("raft_surface_extruder_nr"); - if (base_train.settings_.get("adhesion_type") != EPlatformAdhesion::RAFT) + if (mesh_group_settings.get("adhesion_type") != EPlatformAdhesion::RAFT) { return 0; } - return 1 + interface_train.settings_.get("raft_interface_layers") + surface_train.settings_.get("raft_surface_layers") + getFillerLayerCount(); + return 1; +} + +size_t Raft::getInterfaceLayers() +{ + return getLayersAmount("raft_interface_extruder_nr", "raft_interface_layers"); +} + +size_t Raft::getSurfaceLayers() +{ + return getLayersAmount("raft_surface_extruder_nr", "raft_surface_layers"); } Raft::LayerType Raft::getLayerType(LayerIndex layer_index) @@ -214,5 +225,17 @@ Raft::LayerType Raft::getLayerType(LayerIndex layer_index) } } +size_t Raft::getLayersAmount(const std::string& extruder_nr, const std::string& layers_nr) +{ + const Settings& mesh_group_settings = Application::getInstance().current_slice_->scene.current_mesh_group->settings; + if (mesh_group_settings.get("adhesion_type") != EPlatformAdhesion::RAFT) + { + return 0; + } + + const ExtruderTrain& train = mesh_group_settings.get(extruder_nr); + return train.settings_.get(layers_nr); +} + } // namespace cura diff --git a/src/sliceDataStorage.cpp b/src/sliceDataStorage.cpp index cfc4d32c08..48d7b532ec 100644 --- a/src/sliceDataStorage.cpp +++ b/src/sliceDataStorage.cpp @@ -482,8 +482,8 @@ std::vector SliceDataStorage::getExtrudersUsed(const LayerIndex layer_nr) } if (adhesion_type == EPlatformAdhesion::RAFT) { - const LayerIndex raft_layers = Raft::getTotalExtraLayers(); - if (layer_nr == -raft_layers) // Base layer. + const LayerIndex raft_base_layer_index = -Raft::getTotalExtraLayers(); + if (layer_nr < raft_base_layer_index + Raft::getBottomLayers()) // Base layer. { ret[mesh_group_settings.get("raft_base_extruder_nr").extruder_nr_] = true; // When using a raft, all prime blobs need to be on the lowest layer (the build plate). @@ -495,7 +495,7 @@ std::vector SliceDataStorage::getExtrudersUsed(const LayerIndex layer_nr) } } } - else if (layer_nr == -raft_layers + 1) // Interface layer. + else if (layer_nr < raft_base_layer_index + Raft::getBottomLayers() + Raft::getInterfaceLayers()) // Interface layer. { ret[mesh_group_settings.get("raft_interface_extruder_nr").extruder_nr_] = true; } From 01a4de6e0869d1930dce26d877a66c0a83630ab0 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Fri, 19 Apr 2024 15:27:42 +0200 Subject: [PATCH 04/13] Fixed missing prime tower layers when using raft --- include/FffGcodeWriter.h | 4 ++ src/FffGcodeWriter.cpp | 109 +++++++++++++++++++++++---------------- 2 files changed, 69 insertions(+), 44 deletions(-) diff --git a/include/FffGcodeWriter.h b/include/FffGcodeWriter.h index 251712c8fc..d599207e35 100644 --- a/include/FffGcodeWriter.h +++ b/include/FffGcodeWriter.h @@ -207,6 +207,10 @@ class FffGcodeWriter : public NoCopy */ void processRaft(const SliceDataStorage& storage); + void startRaftLayer(const SliceDataStorage& storage, LayerPlan& gcode_layer, const LayerIndex layer_nr, size_t layer_extruder, size_t& current_extruder); + + void endRaftLayer(const SliceDataStorage& storage, LayerPlan& gcode_layer, const LayerIndex layer_nr, size_t& current_extruder); + /*! * Convert the polygon data of a layer into a layer plan on the FffGcodeWriter::layer_plan_buffer * diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index 626be418d7..207054b8f0 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -589,7 +589,7 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) Polygons raft_polygons; std::optional last_planned_position = std::optional(); - unsigned int current_extruder_nr = base_extruder_nr; + size_t current_extruder_nr = base_extruder_nr; { // raft base layer const Settings& base_settings = mesh_group_settings.get("raft_base_extruder_nr").settings_; @@ -756,7 +756,6 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) for (LayerIndex raft_interface_layer = 1; static_cast(raft_interface_layer) <= num_interface_layers; ++raft_interface_layer) { // raft interface layer - bool prime_tower_added_on_this_layer = ! storage.primeTower.enabled_; const LayerIndex layer_nr = initial_raft_layer_nr + raft_interface_layer; z += interface_layer_height; @@ -782,11 +781,8 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) interface_avoid_distance); gcode_layer.setIsInside(true); - if (interface_extruder_nr != current_extruder_nr) - { - setExtruder_addPrime(storage, gcode_layer, interface_extruder_nr); - current_extruder_nr = interface_extruder_nr; - } + + startRaftLayer(storage, gcode_layer, layer_nr, interface_extruder_nr, current_extruder_nr); Application::getInstance().communication_->sendLayerComplete(layer_nr, z, interface_layer_height); @@ -899,10 +895,7 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) raft_polygons.clear(); raft_lines.clear(); - if (! prime_tower_added_on_this_layer) - { - addPrimeTower(storage, gcode_layer, current_extruder_nr); - } + endRaftLayer(storage, gcode_layer, layer_nr, current_extruder_nr); layer_plan_buffer.handle(gcode_layer, gcode); last_planned_position = gcode_layer.getLastPlannedPositionOrStartingPosition(); @@ -919,7 +912,6 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) for (LayerIndex raft_surface_layer = 1; static_cast(raft_surface_layer) <= num_surface_layers; raft_surface_layer++) { // raft surface layers - bool prime_tower_added_on_this_layer = ! storage.primeTower.enabled_; const LayerIndex layer_nr = initial_raft_layer_nr + 1 + num_interface_layers + raft_surface_layer - 1; // +1: 1 base layer z += surface_layer_height; @@ -947,11 +939,8 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) gcode_layer.setIsInside(true); // make sure that we are using the correct extruder to print raft - if (current_extruder_nr != surface_extruder_nr) - { - setExtruder_addPrime(storage, gcode_layer, surface_extruder_nr); - current_extruder_nr = surface_extruder_nr; - } + startRaftLayer(storage, gcode_layer, layer_nr, surface_extruder_nr, current_extruder_nr); + Application::getInstance().communication_->sendLayerComplete(layer_nr, z, surface_layer_height); Polygons raft_outline_path; @@ -1082,15 +1071,41 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) raft_lines.clear(); } - if (! prime_tower_added_on_this_layer) - { - addPrimeTower(storage, gcode_layer, current_extruder_nr); - } + endRaftLayer(storage, gcode_layer, layer_nr, current_extruder_nr); layer_plan_buffer.handle(gcode_layer, gcode); } } +void FffGcodeWriter::startRaftLayer(const SliceDataStorage& storage, LayerPlan& gcode_layer, const LayerIndex layer_nr, size_t layer_extruder, size_t& current_extruder) +{ + // If required, fill prime tower with previous extruder + setExtruder_addPrime(storage, gcode_layer, current_extruder); + + if (current_extruder != layer_extruder) + { + // Switch to new extruder and prime + setExtruder_addPrime(storage, gcode_layer, layer_extruder); + current_extruder = layer_extruder; + } +} + +void FffGcodeWriter::endRaftLayer(const SliceDataStorage& storage, LayerPlan& gcode_layer, const LayerIndex layer_nr, size_t& current_extruder) +{ + // If required, fill prime tower with current extruder + setExtruder_addPrime(storage, gcode_layer, current_extruder); + + // If required, fill prime tower for other extruders + for (const ExtruderUse& extruder_use : getExtruderUse(layer_nr)) + { + if (! gcode_layer.getPrimeTowerIsPlanned(extruder_use.extruder_nr) && extruder_use.prime != ExtruderPrime::None) + { + setExtruder_addPrime(storage, gcode_layer, extruder_use.extruder_nr); + current_extruder = extruder_use.extruder_nr; + } + } +} + FffGcodeWriter::ProcessLayerResult FffGcodeWriter::processLayer(const SliceDataStorage& storage, LayerIndex layer_nr, const size_t total_layers) const { spdlog::debug("GcodeWriter processing layer {} of {}", layer_nr, total_layers); @@ -1210,19 +1225,11 @@ FffGcodeWriter::ProcessLayerResult FffGcodeWriter::processLayer(const SliceDataS for (const ExtruderUse& extruder_use : extruder_order) { size_t extruder_nr = extruder_use.extruder_nr; - // Everytime you start with a new extruder you want to add a prime tower, unless: - // - prime tower is disabled (setExtruder_addPrime takes care of this) - // - this is the first (and not the only!) extruder in this layer. Since the previous - // layer always ends with this extruder. If the first extruder is the only extruder, - // the prime tower needs to be added anyways, in order to support the prime tower if - // later in the print a prime tower is needed. - // - prime tower is already printed this layer (only applicable for more than 2 extruders). - // The setExtruder_addPrime takes care of this. - if (extruder_nr != extruder_order.front().extruder_nr || (extruder_order.size() == 1 && layer_nr >= 0) || extruder_nr == 0) - { - setExtruder_addPrime(storage, gcode_layer, extruder_nr); - time_keeper.registerTime("Prime tower pre"); - } + + // Set extruder (if needed) and prime (if needed) + setExtruder_addPrime(storage, gcode_layer, extruder_nr); + time_keeper.registerTime("Prime tower"); + if (include_helper_parts && (extruder_nr == support_infill_extruder_nr || extruder_nr == support_roof_extruder_nr || extruder_nr == support_bottom_extruder_nr)) { addSupportToGCode(storage, gcode_layer, extruder_nr); @@ -1249,14 +1256,6 @@ FffGcodeWriter::ProcessLayerResult FffGcodeWriter::processLayer(const SliceDataS time_keeper.registerTime(fmt::format("Mesh {}", mesh_idx)); } } - // Always print a prime tower before switching extruder. Unless: - // - The prime tower is already printed this layer (setExtruder_addPrime takes care of this). - // - this is the last extruder of the layer, since the next layer will start with the same extruder. - if (extruder_nr != extruder_order.back().extruder_nr && layer_nr >= 0) - { - setExtruder_addPrime(storage, gcode_layer, extruder_nr); - time_keeper.registerTime("Prime tower post"); - } } gcode_layer.applyModifyPlugin(); @@ -1580,9 +1579,31 @@ std::vector FffGcodeWriter::getUsedExtrudersOnLayer( std::vector extruder_is_used_on_this_layer = storage.getExtrudersUsed(layer_nr); const auto method = mesh_group_settings.get("prime_tower_mode"); const auto prime_tower_enable = mesh_group_settings.get("prime_tower_enable"); + const LayerIndex raft_base_layer_nr = -Raft::getTotalExtraLayers(); + + if (layer_nr < 0 && layer_nr < raft_base_layer_nr + Raft::getBottomLayers()) + { + // Raft base layers area treated apart because they don't have a proper prime tower + const size_t raft_base_extruder_nr = mesh_group_settings.get("raft_base_extruder_nr").extruder_nr_; + ret.push_back(ExtruderUse{ raft_base_extruder_nr, ExtruderPrime::None }); + + // check if we need prime blob on the first layer + if (layer_nr == raft_base_layer_nr) + { + for (size_t extruder_nr = 0; extruder_nr < extruder_is_used_on_this_layer.size(); extruder_nr++) + { + if (extruder_nr != raft_base_extruder_nr && getExtruderNeedPrimeBlobDuringFirstLayer(storage, extruder_nr)) + { + ret.push_back(ExtruderUse{ extruder_nr, ExtruderPrime::None }); + } + } + } + + return ret; + } // check if we are on the first layer - if (layer_nr == -static_cast(Raft::getTotalExtraLayers())) + if (layer_nr == raft_base_layer_nr) { // check if we need prime blob on the first layer for (size_t used_idx = 0; used_idx < extruder_is_used_on_this_layer.size(); used_idx++) @@ -1605,7 +1626,7 @@ std::vector FffGcodeWriter::getUsedExtrudersOnLayer( } } - // Now check whether extuders should really be used, and how + // Now check whether extruders should really be used, and how size_t last_extruder = start_extruder; for (size_t extruder_nr : ordered_extruders) { From a0f0636c1a416e24ebbaafd50a2149b12f951549 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Fri, 10 May 2024 16:37:57 +0200 Subject: [PATCH 05/13] Properly handle material_print_temp_prepend with Griffin flavor Previously the material_print_temp_prepend setting was taken care of only for non-Griffin flavor. This logic is now also applied for Griffin, and the setting is properly applied. CURA-11868 --- src/gcodeExport.cpp | 102 +++++++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 48 deletions(-) diff --git a/src/gcodeExport.cpp b/src/gcodeExport.cpp index 8a3cc11538..b8af0451db 100644 --- a/src/gcodeExport.cpp +++ b/src/gcodeExport.cpp @@ -766,69 +766,75 @@ void GCodeExport::processInitialLayerTemperature(const SliceDataStorage& storage { Scene& scene = Application::getInstance().current_slice_->scene; const size_t num_extruders = scene.extruders.size(); + bool wait_start_extruder = false; - if (getFlavor() == EGCodeFlavor::GRIFFIN) - { - processInitialLayerBedTemperature(); - - ExtruderTrain& train = scene.extruders[start_extruder_nr]; - constexpr bool wait = true; - const Temperature print_temp_0 = train.settings_.get("material_print_temperature_layer_0"); - const Temperature print_temp_here = (print_temp_0 != 0) ? print_temp_0 : train.settings_.get("material_print_temperature"); - writeTemperatureCommand(start_extruder_nr, print_temp_here, wait); - } - else if (getFlavor() != EGCodeFlavor::ULTIGCODE) + switch (getFlavor()) { + case EGCodeFlavor::ULTIGCODE: + return; + case EGCodeFlavor::GRIFFIN: + wait_start_extruder = true; + break; + default: if (num_extruders > 1 || getFlavor() == EGCodeFlavor::REPRAP) { std::ostringstream tmp; tmp << "T" << start_extruder_nr; writeLine(tmp.str().c_str()); } + break; + } - processInitialLayerBedTemperature(); + processInitialLayerBedTemperature(); - if (scene.current_mesh_group->settings.get("material_print_temp_prepend") || (scene.current_mesh_group != scene.mesh_groups.begin())) + std::vector extruders_to_process; + extruders_to_process.push_back(start_extruder_nr); + if (scene.current_mesh_group->settings.get("material_print_temp_prepend") || (scene.current_mesh_group != scene.mesh_groups.begin())) + { + std::vector extruders_used = storage.getExtrudersUsed(); + for (size_t extruder_nr = 0; extruder_nr < extruders_used.size(); ++extruder_nr) { - for (unsigned extruder_nr = 0; extruder_nr < num_extruders; extruder_nr++) + if (extruder_nr != start_extruder_nr && extruders_used[extruder_nr]) { - if (storage.getExtrudersUsed()[extruder_nr]) - { - const ExtruderTrain& train = scene.extruders[extruder_nr]; - Temperature extruder_temp; - if (extruder_nr == start_extruder_nr) - { - const Temperature print_temp_0 = train.settings_.get("material_print_temperature_layer_0"); - extruder_temp = (print_temp_0 != 0) ? print_temp_0 : train.settings_.get("material_print_temperature"); - } - else - { - extruder_temp = train.settings_.get("material_standby_temperature"); - } - writeTemperatureCommand(extruder_nr, extruder_temp); - } + extruders_to_process.push_back(extruder_nr); } - if (scene.current_mesh_group->settings.get("material_print_temp_wait")) + } + } + + for (size_t extruder_nr : extruders_to_process) + { + const ExtruderTrain& train = scene.extruders[extruder_nr]; + Temperature extruder_temp; + bool wait = false; + if (extruder_nr == start_extruder_nr) + { + const Temperature print_temp_0 = train.settings_.get("material_print_temperature_layer_0"); + extruder_temp = (print_temp_0 != 0) ? print_temp_0 : train.settings_.get("material_print_temperature"); + wait = wait_start_extruder; + } + else + { + extruder_temp = train.settings_.get("material_standby_temperature"); + } + writeTemperatureCommand(extruder_nr, extruder_temp, wait); + } + + if (scene.current_mesh_group->settings.get("material_print_temp_wait")) + { + for (size_t extruder_nr : extruders_to_process) + { + const ExtruderTrain& train = scene.extruders[extruder_nr]; + Temperature extruder_temp; + if (extruder_nr == start_extruder_nr) { - for (unsigned extruder_nr = 0; extruder_nr < num_extruders; extruder_nr++) - { - if (storage.getExtrudersUsed()[extruder_nr]) - { - const ExtruderTrain& train = scene.extruders[extruder_nr]; - Temperature extruder_temp; - if (extruder_nr == start_extruder_nr) - { - const Temperature print_temp_0 = train.settings_.get("material_print_temperature_layer_0"); - extruder_temp = (print_temp_0 != 0) ? print_temp_0 : train.settings_.get("material_print_temperature"); - } - else - { - extruder_temp = train.settings_.get("material_standby_temperature"); - } - writeTemperatureCommand(extruder_nr, extruder_temp, true); - } - } + const Temperature print_temp_0 = train.settings_.get("material_print_temperature_layer_0"); + extruder_temp = (print_temp_0 != 0) ? print_temp_0 : train.settings_.get("material_print_temperature"); + } + else + { + extruder_temp = train.settings_.get("material_standby_temperature"); } + writeTemperatureCommand(extruder_nr, extruder_temp, true); } } } From db39086e14f23db7951b836333841f12129c20d9 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 13 May 2024 14:50:43 +0200 Subject: [PATCH 06/13] All printing prime blobs for all extruders when using a raft Previously we would calculate the most appropriate layer to do the priming of an extruder, but when using a prime blob the extruder needs to be primed at first layer, which won't happen when using a raft. We now then for priming at first layer when having a prime blob, and process priming after the raft base layer has been printed. CURA-11868 --- include/FffGcodeWriter.h | 7 +++++-- src/FffGcodeWriter.cpp | 30 ++++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/include/FffGcodeWriter.h b/include/FffGcodeWriter.h index d599207e35..6491d8dbb2 100644 --- a/include/FffGcodeWriter.h +++ b/include/FffGcodeWriter.h @@ -209,7 +209,7 @@ class FffGcodeWriter : public NoCopy void startRaftLayer(const SliceDataStorage& storage, LayerPlan& gcode_layer, const LayerIndex layer_nr, size_t layer_extruder, size_t& current_extruder); - void endRaftLayer(const SliceDataStorage& storage, LayerPlan& gcode_layer, const LayerIndex layer_nr, size_t& current_extruder); + void endRaftLayer(const SliceDataStorage& storage, LayerPlan& gcode_layer, const LayerIndex layer_nr, size_t& current_extruder, const bool append_to_prime_tower = true); /*! * Convert the polygon data of a layer into a layer plan on the FffGcodeWriter::layer_plan_buffer @@ -665,8 +665,11 @@ class FffGcodeWriter : public NoCopy * \param[in] storage where the slice data is stored. * \param gcode_layer The initial planning of the gcode of the layer. * \param extruder_nr The extruder to switch to. + * \param append_to_prime_tower Indicates whether we should actually prime the extruder on the prime tower (normal + * case before actually using the extruder) or just do the basic priming (i.e. on first + * layer before starting the print */ - void setExtruder_addPrime(const SliceDataStorage& storage, LayerPlan& gcode_layer, const size_t extruder_nr) const; + void setExtruder_addPrime(const SliceDataStorage& storage, LayerPlan& gcode_layer, const size_t extruder_nr, const bool append_to_prime_tower = true) const; /*! * Add the prime tower gcode for the current layer. diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index 207054b8f0..9419aa06ff 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -150,7 +150,6 @@ void FffGcodeWriter::writeGCode(SliceDataStorage& storage, TimeKeeper& time_keep gcode.writeTravel(p, extruder_settings.get("speed_travel")); } - calculateExtruderOrderPerLayer(storage); calculatePrimeLayerPerExtruder(storage); @@ -743,6 +742,8 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) last_planned_position = gcode_layer.getLastPlannedPositionOrStartingPosition(); } + endRaftLayer(storage, gcode_layer, layer_nr, current_extruder_nr, false); + layer_plan_buffer.handle(gcode_layer, gcode); } @@ -1090,17 +1091,17 @@ void FffGcodeWriter::startRaftLayer(const SliceDataStorage& storage, LayerPlan& } } -void FffGcodeWriter::endRaftLayer(const SliceDataStorage& storage, LayerPlan& gcode_layer, const LayerIndex layer_nr, size_t& current_extruder) +void FffGcodeWriter::endRaftLayer(const SliceDataStorage& storage, LayerPlan& gcode_layer, const LayerIndex layer_nr, size_t& current_extruder, const bool append_to_prime_tower) { // If required, fill prime tower with current extruder - setExtruder_addPrime(storage, gcode_layer, current_extruder); + setExtruder_addPrime(storage, gcode_layer, current_extruder, append_to_prime_tower); // If required, fill prime tower for other extruders for (const ExtruderUse& extruder_use : getExtruderUse(layer_nr)) { - if (! gcode_layer.getPrimeTowerIsPlanned(extruder_use.extruder_nr) && extruder_use.prime != ExtruderPrime::None) + if (! append_to_prime_tower || (! gcode_layer.getPrimeTowerIsPlanned(extruder_use.extruder_nr) && extruder_use.prime != ExtruderPrime::None)) { - setExtruder_addPrime(storage, gcode_layer, extruder_use.extruder_nr); + setExtruder_addPrime(storage, gcode_layer, extruder_use.extruder_nr, append_to_prime_tower); current_extruder = extruder_use.extruder_nr; } } @@ -1553,7 +1554,17 @@ void FffGcodeWriter::calculateExtruderOrderPerLayer(const SliceDataStorage& stor void FffGcodeWriter::calculatePrimeLayerPerExtruder(const SliceDataStorage& storage) { - for (LayerIndex layer_nr = -Raft::getTotalExtraLayers(); layer_nr < static_cast(storage.print_layer_count); ++layer_nr) + LayerIndex first_print_layer = -Raft::getTotalExtraLayers(); + for (size_t extruder_nr = 0; extruder_nr < MAX_EXTRUDERS; ++extruder_nr) + { + if (getExtruderNeedPrimeBlobDuringFirstLayer(storage, extruder_nr)) + { + // Extruders requiring a prime blob have to be primed at first layer + extruder_prime_layer_nr[extruder_nr] = std::min(extruder_prime_layer_nr[extruder_nr], first_print_layer); + } + } + + for (LayerIndex layer_nr = first_print_layer; layer_nr < static_cast(storage.print_layer_count); ++layer_nr) { const std::vector used_extruders = storage.getExtrudersUsed(layer_nr); for (size_t extruder_nr = 0; extruder_nr < used_extruders.size(); ++extruder_nr) @@ -3920,7 +3931,7 @@ bool FffGcodeWriter::addSupportBottomsToGCode(const SliceDataStorage& storage, L return true; } -void FffGcodeWriter::setExtruder_addPrime(const SliceDataStorage& storage, LayerPlan& gcode_layer, const size_t extruder_nr) const +void FffGcodeWriter::setExtruder_addPrime(const SliceDataStorage& storage, LayerPlan& gcode_layer, const size_t extruder_nr, const bool append_to_prime_tower) const { const size_t previous_extruder = gcode_layer.getExtruder(); const bool extruder_changed = gcode_layer.setExtruder(extruder_nr); @@ -3953,7 +3964,10 @@ void FffGcodeWriter::setExtruder_addPrime(const SliceDataStorage& storage, Layer } } - addPrimeTower(storage, gcode_layer, previous_extruder); + if (append_to_prime_tower) + { + addPrimeTower(storage, gcode_layer, previous_extruder); + } } void FffGcodeWriter::addPrimeTower(const SliceDataStorage& storage, LayerPlan& gcode_layer, const size_t prev_extruder) const From ded635220ff86b99be6653a11385416b289a2f4d Mon Sep 17 00:00:00 2001 From: Saumya Jain Date: Fri, 26 Apr 2024 16:52:49 +0200 Subject: [PATCH 07/13] removing debug code as its executing in production Also this code contains svg generation, which is majorly used in debugging application --- src/utils/polygonUtils.cpp | 46 -------------------------------------- 1 file changed, 46 deletions(-) diff --git a/src/utils/polygonUtils.cpp b/src/utils/polygonUtils.cpp index 7f7bc2466a..6266b73ce1 100644 --- a/src/utils/polygonUtils.cpp +++ b/src/utils/polygonUtils.cpp @@ -16,9 +16,7 @@ #ifdef DEBUG #include - #include "utils/AABB.h" -#include "utils/SVG.h" #endif namespace cura @@ -689,50 +687,6 @@ ClosestPolygonPoint PolygonUtils::ensureInsideOrOutside( bool overall_is_inside = polygons.inside(overall_inside.location_); if (overall_is_inside != (preferred_dist_inside > 0)) { -#ifdef DEBUG - static bool has_run = false; - if (! has_run) - { - try - { - int offset_performed = offset / 2; - AABB aabb(polygons); - aabb.expand(std::abs(preferred_dist_inside) * 2); - SVG svg("debug.html", aabb); - svg.writeComment("Original polygon in black"); - svg.writePolygons(polygons, SVG::Color::BLACK); - for (auto poly : polygons) - { - for (auto point : poly) - { - svg.writePoint(point, true, 2); - } - } - std::stringstream ss; - svg.writeComment("Reference polygon in yellow"); - svg.writePolygon(closest_poly, SVG::Color::YELLOW); - ss << "Offsetted polygon in blue with offset " << offset_performed; - svg.writeComment(ss.str()); - svg.writePolygons(insetted, SVG::Color::BLUE); - for (auto poly : insetted) - { - for (auto point : poly) - { - svg.writePoint(point, true, 2); - } - } - svg.writeComment("From location"); - svg.writePoint(from, true, 5, SVG::Color::GREEN); - svg.writeComment("Location computed to be inside the black polygon"); - svg.writePoint(inside.location_, true, 5, SVG::Color::RED); - } - catch (...) - { - } - spdlog::error("Clipper::offset failed. See generated debug.html! Black is original Blue is offsetted polygon"); - has_run = true; - } -#endif return ClosestPolygonPoint(); } inside = overall_inside; From dac3de6a306330ce78b2fa79e33b2f6662097bb3 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 15 May 2024 09:57:05 +0200 Subject: [PATCH 08/13] Reuse existing code to calcule raft layer types --- src/FffGcodeWriter.cpp | 3 ++- src/raft.cpp | 12 ++++-------- src/sliceDataStorage.cpp | 8 ++++---- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index 207054b8f0..77c52f8f0e 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -1580,8 +1580,9 @@ std::vector FffGcodeWriter::getUsedExtrudersOnLayer( const auto method = mesh_group_settings.get("prime_tower_mode"); const auto prime_tower_enable = mesh_group_settings.get("prime_tower_enable"); const LayerIndex raft_base_layer_nr = -Raft::getTotalExtraLayers(); + Raft::LayerType layer_type = Raft::getLayerType(layer_nr); - if (layer_nr < 0 && layer_nr < raft_base_layer_nr + Raft::getBottomLayers()) + if (layer_type == Raft::RaftBase) { // Raft base layers area treated apart because they don't have a proper prime tower const size_t raft_base_extruder_nr = mesh_group_settings.get("raft_base_extruder_nr").extruder_nr_; diff --git a/src/raft.cpp b/src/raft.cpp index c708271ac4..6f455b12c1 100644 --- a/src/raft.cpp +++ b/src/raft.cpp @@ -195,23 +195,19 @@ size_t Raft::getSurfaceLayers() Raft::LayerType Raft::getLayerType(LayerIndex layer_index) { - const Settings& mesh_group_settings = Application::getInstance().current_slice_->scene.current_mesh_group->settings; - const ExtruderTrain& base_train = mesh_group_settings.get("raft_base_extruder_nr"); - const ExtruderTrain& interface_train = mesh_group_settings.get("raft_interface_extruder_nr"); - const ExtruderTrain& surface_train = mesh_group_settings.get("raft_surface_extruder_nr"); const auto airgap = Raft::getFillerLayerCount(); - const auto interface_layers = interface_train.settings_.get("raft_interface_layers"); - const auto surface_layers = surface_train.settings_.get("raft_surface_layers"); + const auto interface_layers = Raft::getInterfaceLayers(); + const auto surface_layers = Raft::getSurfaceLayers(); if (layer_index < -airgap - surface_layers - interface_layers) { return LayerType::RaftBase; } - if (layer_index < -airgap - surface_layers) + else if (layer_index < -airgap - surface_layers) { return LayerType::RaftInterface; } - if (layer_index < -airgap) + else if (layer_index < -airgap) { return LayerType::RaftSurface; } diff --git a/src/sliceDataStorage.cpp b/src/sliceDataStorage.cpp index 48d7b532ec..618cced427 100644 --- a/src/sliceDataStorage.cpp +++ b/src/sliceDataStorage.cpp @@ -482,8 +482,8 @@ std::vector SliceDataStorage::getExtrudersUsed(const LayerIndex layer_nr) } if (adhesion_type == EPlatformAdhesion::RAFT) { - const LayerIndex raft_base_layer_index = -Raft::getTotalExtraLayers(); - if (layer_nr < raft_base_layer_index + Raft::getBottomLayers()) // Base layer. + const Raft::LayerType layer_type = Raft::getLayerType(layer_nr); + if (layer_type == Raft::RaftBase) { ret[mesh_group_settings.get("raft_base_extruder_nr").extruder_nr_] = true; // When using a raft, all prime blobs need to be on the lowest layer (the build plate). @@ -495,11 +495,11 @@ std::vector SliceDataStorage::getExtrudersUsed(const LayerIndex layer_nr) } } } - else if (layer_nr < raft_base_layer_index + Raft::getBottomLayers() + Raft::getInterfaceLayers()) // Interface layer. + else if (layer_type == Raft::RaftInterface) { ret[mesh_group_settings.get("raft_interface_extruder_nr").extruder_nr_] = true; } - else if (layer_nr < -static_cast(Raft::getFillerLayerCount())) // Any of the surface layers. + else if (layer_type == Raft::RaftSurface) { ret[mesh_group_settings.get("raft_surface_extruder_nr").extruder_nr_] = true; } From 52728ae0b0af57acab24b2ba58fe865e27e05206 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 15 May 2024 12:02:31 +0200 Subject: [PATCH 09/13] Make Raft::getLayersAmount more readable and document it CURA-11873 --- include/raft.h | 8 +++++++- src/raft.cpp | 6 +++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/include/raft.h b/include/raft.h index 67eb7145c5..01110490cf 100644 --- a/include/raft.h +++ b/include/raft.h @@ -84,7 +84,13 @@ class Raft static LayerType getLayerType(LayerIndex layer_index); private: - static size_t getLayersAmount(const std::string& extruder_nr, const std::string& layers_nr); + /*! + * \brief Get the amount of layers to be printed for the given raft section + * \param extruder_nr_setting_name The name of the setting to be fetched to get the proper extruder number + * \param target_raft_section The name of the setting to be fetched to get the number of layers + * \return The number of layers for the given raft section, or 0 if raft is disabled + */ + static size_t getLayersAmount(const std::string& extruder_nr_setting_name, const std::string& target_raft_section); }; } // namespace cura diff --git a/src/raft.cpp b/src/raft.cpp index 6f455b12c1..f93d59ed1c 100644 --- a/src/raft.cpp +++ b/src/raft.cpp @@ -221,7 +221,7 @@ Raft::LayerType Raft::getLayerType(LayerIndex layer_index) } } -size_t Raft::getLayersAmount(const std::string& extruder_nr, const std::string& layers_nr) +size_t Raft::getLayersAmount(const std::string& extruder_nr_setting_name, const std::string& target_raft_section) { const Settings& mesh_group_settings = Application::getInstance().current_slice_->scene.current_mesh_group->settings; if (mesh_group_settings.get("adhesion_type") != EPlatformAdhesion::RAFT) @@ -229,8 +229,8 @@ size_t Raft::getLayersAmount(const std::string& extruder_nr, const std::string& return 0; } - const ExtruderTrain& train = mesh_group_settings.get(extruder_nr); - return train.settings_.get(layers_nr); + const ExtruderTrain& train = mesh_group_settings.get(extruder_nr_setting_name); + return train.settings_.get(target_raft_section); } From f62285ebc415f0dba66b6e19592c1f4844bf2da7 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 15 May 2024 12:06:08 +0200 Subject: [PATCH 10/13] Rename Raft:getBottomLayers for more consistency CURA-11873 --- include/raft.h | 6 +++--- src/raft.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/raft.h b/include/raft.h index 01110490cf..a4493f0622 100644 --- a/include/raft.h +++ b/include/raft.h @@ -56,10 +56,10 @@ class Raft static size_t getTotalExtraLayers(); /*! - * \brief Get the amount of bottom for the raft interface. - * \note This is currently hard-coded to 1 because we have yet no setting for the bottom + * \brief Get the amount of layers for the raft base. + * \note This is currently hard-coded to 1 because we have yet no setting for the base */ - static size_t getBottomLayers(); + static size_t getBaseLayers(); /*! \brief Get the amount of layers for the raft interface. */ static size_t getInterfaceLayers(); diff --git a/src/raft.cpp b/src/raft.cpp index f93d59ed1c..55198e4205 100644 --- a/src/raft.cpp +++ b/src/raft.cpp @@ -170,10 +170,10 @@ coord_t Raft::getFillerLayerHeight() size_t Raft::getTotalExtraLayers() { - return getBottomLayers() + getInterfaceLayers() + getSurfaceLayers() + getFillerLayerCount(); + return getBaseLayers() + getInterfaceLayers() + getSurfaceLayers() + getFillerLayerCount(); } -size_t Raft::getBottomLayers() +size_t Raft::getBaseLayers() { const Settings& mesh_group_settings = Application::getInstance().current_slice_->scene.current_mesh_group->settings; if (mesh_group_settings.get("adhesion_type") != EPlatformAdhesion::RAFT) From 0672e61e9a0191eae35a025c401da7ed146e751e Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 23 May 2024 12:59:49 +0200 Subject: [PATCH 11/13] Set version 5.7.2 --- conandata.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conandata.yml b/conandata.yml index 25ea096dd3..4f95615585 100644 --- a/conandata.yml +++ b/conandata.yml @@ -1,4 +1,4 @@ -version: "5.7.1" +version: "5.7.2" requirements: - "scripta/0.1.0@ultimaker/testing" requirements_arcus: From 9f4621278d47431dbef1dfe04144dfe8c9aad92f Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 27 May 2024 14:57:30 +0200 Subject: [PATCH 12/13] Force adding temperatures commands when required Previously, the initial temperatures commands were ignored if the temperatures were already set in the header. This causes issues because we don't actually know in what state the printer will let the nozzles after its init sequence. So we now write non-wait and wait temperatures commands based only on the settings, so that one can set them properly according to the printer init sequence. CURA-11930 --- include/gcodeExport.h | 9 +++++- src/gcodeExport.cpp | 68 +++++++++++++++++++++---------------------- 2 files changed, 41 insertions(+), 36 deletions(-) diff --git a/include/gcodeExport.h b/include/gcodeExport.h index 5edd5dcdda..143504c710 100644 --- a/include/gcodeExport.h +++ b/include/gcodeExport.h @@ -541,7 +541,14 @@ class GCodeExport : public NoCopy void writeFanCommand(double speed); - void writeTemperatureCommand(const size_t extruder, const Temperature& temperature, const bool wait = false); + /*! + * \brief Write a GCode temperature command + * \param extruder The extruder number + * \param temperature The temperature to bo set + * \param wait Indicates whether we should just set the temperature and keep going, or wait for the temperature to be reach before going further + * \param force_same_temperature When true, we should set the temperature command even if the actual set temperature is the same + */ + void writeTemperatureCommand(const size_t extruder, const Temperature& temperature, const bool wait = false, const bool force_same_temperature = false); void writeBedTemperatureCommand(const Temperature& temperature, const bool wait = false); void writeBuildVolumeTemperatureCommand(const Temperature& temperature, const bool wait = false); diff --git a/src/gcodeExport.cpp b/src/gcodeExport.cpp index b8af0451db..1be31075ae 100644 --- a/src/gcodeExport.cpp +++ b/src/gcodeExport.cpp @@ -766,6 +766,8 @@ void GCodeExport::processInitialLayerTemperature(const SliceDataStorage& storage { Scene& scene = Application::getInstance().current_slice_->scene; const size_t num_extruders = scene.extruders.size(); + const bool material_print_temp_prepend = scene.current_mesh_group->settings.get("material_print_temp_prepend"); + const bool material_print_temp_wait = scene.current_mesh_group->settings.get("material_print_temp_wait"); bool wait_start_extruder = false; switch (getFlavor()) @@ -787,41 +789,17 @@ void GCodeExport::processInitialLayerTemperature(const SliceDataStorage& storage processInitialLayerBedTemperature(); - std::vector extruders_to_process; - extruders_to_process.push_back(start_extruder_nr); - if (scene.current_mesh_group->settings.get("material_print_temp_prepend") || (scene.current_mesh_group != scene.mesh_groups.begin())) + struct ExtruderInitialize { - std::vector extruders_used = storage.getExtrudersUsed(); - for (size_t extruder_nr = 0; extruder_nr < extruders_used.size(); ++extruder_nr) - { - if (extruder_nr != start_extruder_nr && extruders_used[extruder_nr]) - { - extruders_to_process.push_back(extruder_nr); - } - } - } + size_t nr; + Temperature temperature; + }; - for (size_t extruder_nr : extruders_to_process) + std::vector all_extruders; + std::vector extruders_used = storage.getExtrudersUsed(); + for (size_t extruder_nr = 0; extruder_nr < extruders_used.size(); ++extruder_nr) { - const ExtruderTrain& train = scene.extruders[extruder_nr]; - Temperature extruder_temp; - bool wait = false; - if (extruder_nr == start_extruder_nr) - { - const Temperature print_temp_0 = train.settings_.get("material_print_temperature_layer_0"); - extruder_temp = (print_temp_0 != 0) ? print_temp_0 : train.settings_.get("material_print_temperature"); - wait = wait_start_extruder; - } - else - { - extruder_temp = train.settings_.get("material_standby_temperature"); - } - writeTemperatureCommand(extruder_nr, extruder_temp, wait); - } - - if (scene.current_mesh_group->settings.get("material_print_temp_wait")) - { - for (size_t extruder_nr : extruders_to_process) + if (extruders_used[extruder_nr]) { const ExtruderTrain& train = scene.extruders[extruder_nr]; Temperature extruder_temp; @@ -834,7 +812,27 @@ void GCodeExport::processInitialLayerTemperature(const SliceDataStorage& storage { extruder_temp = train.settings_.get("material_standby_temperature"); } - writeTemperatureCommand(extruder_nr, extruder_temp, true); + + all_extruders.push_back({ extruder_nr, extruder_temp }); + } + } + + // First set all the required temperatures at once, but without waiting so that all heaters start heating right now + const bool prepend_all_temperatures = material_print_temp_prepend || (scene.current_mesh_group != scene.mesh_groups.begin()); + for (ExtruderInitialize& extruder : all_extruders) + { + if (extruder.nr == start_extruder_nr || prepend_all_temperatures) + { + writeTemperatureCommand(extruder.nr, extruder.temperature, false, true); + } + } + + // Now wait for all the required temperatures one after the other + for (ExtruderInitialize& extruder : all_extruders) + { + if (material_print_temp_wait || (extruder.nr == start_extruder_nr && wait_start_extruder)) + { + writeTemperatureCommand(extruder.nr, extruder.temperature, true, true); } } } @@ -1481,7 +1479,7 @@ void GCodeExport::writeFanCommand(double speed) current_fan_speed_ = speed; } -void GCodeExport::writeTemperatureCommand(const size_t extruder, const Temperature& temperature, const bool wait) +void GCodeExport::writeTemperatureCommand(const size_t extruder, const Temperature& temperature, const bool wait, const bool force_same_temperature) { const ExtruderTrain& extruder_train = Application::getInstance().current_slice_->scene.extruders[extruder]; @@ -1517,7 +1515,7 @@ void GCodeExport::writeTemperatureCommand(const size_t extruder, const Temperatu } } - if ((! wait || extruder_attr_[extruder].waited_for_temperature_) && extruder_attr_[extruder].current_temperature_ == temperature) + if ((! wait || extruder_attr_[extruder].waited_for_temperature_) && ! force_same_temperature && extruder_attr_[extruder].current_temperature_ == temperature) { return; } From 935b266a8d8a14b9ca25fc783b59ec054b19f868 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 29 May 2024 11:41:27 +0200 Subject: [PATCH 13/13] Rename variable as suggested CURA-11930 --- include/gcodeExport.h | 4 ++-- src/gcodeExport.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/gcodeExport.h b/include/gcodeExport.h index 143504c710..8f25a0fa32 100644 --- a/include/gcodeExport.h +++ b/include/gcodeExport.h @@ -546,9 +546,9 @@ class GCodeExport : public NoCopy * \param extruder The extruder number * \param temperature The temperature to bo set * \param wait Indicates whether we should just set the temperature and keep going, or wait for the temperature to be reach before going further - * \param force_same_temperature When true, we should set the temperature command even if the actual set temperature is the same + * \param force_write_on_equal When true, we should write the temperature command even if the actual set temperature is the same */ - void writeTemperatureCommand(const size_t extruder, const Temperature& temperature, const bool wait = false, const bool force_same_temperature = false); + void writeTemperatureCommand(const size_t extruder, const Temperature& temperature, const bool wait = false, const bool force_write_on_equal = false); void writeBedTemperatureCommand(const Temperature& temperature, const bool wait = false); void writeBuildVolumeTemperatureCommand(const Temperature& temperature, const bool wait = false); diff --git a/src/gcodeExport.cpp b/src/gcodeExport.cpp index 1be31075ae..6ce8588c6d 100644 --- a/src/gcodeExport.cpp +++ b/src/gcodeExport.cpp @@ -1479,7 +1479,7 @@ void GCodeExport::writeFanCommand(double speed) current_fan_speed_ = speed; } -void GCodeExport::writeTemperatureCommand(const size_t extruder, const Temperature& temperature, const bool wait, const bool force_same_temperature) +void GCodeExport::writeTemperatureCommand(const size_t extruder, const Temperature& temperature, const bool wait, const bool force_write_on_equal) { const ExtruderTrain& extruder_train = Application::getInstance().current_slice_->scene.extruders[extruder]; @@ -1515,7 +1515,7 @@ void GCodeExport::writeTemperatureCommand(const size_t extruder, const Temperatu } } - if ((! wait || extruder_attr_[extruder].waited_for_temperature_) && ! force_same_temperature && extruder_attr_[extruder].current_temperature_ == temperature) + if ((! wait || extruder_attr_[extruder].waited_for_temperature_) && ! force_write_on_equal && extruder_attr_[extruder].current_temperature_ == temperature) { return; }