diff --git a/include/FffGcodeWriter.h b/include/FffGcodeWriter.h index 9c2482a937..3767309b60 100644 --- a/include/FffGcodeWriter.h +++ b/include/FffGcodeWriter.h @@ -206,6 +206,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, const bool append_to_prime_tower = true); + /*! * Convert the polygon data of a layer into a layer plan on the FffGcodeWriter::layer_plan_buffer * @@ -660,8 +664,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/include/PrimeTower.h b/include/PrimeTower.h index c1f4927880..4de22dfa57 100644 --- a/include/PrimeTower.h +++ b/include/PrimeTower.h @@ -59,8 +59,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/include/gcodeExport.h b/include/gcodeExport.h index 9d91325d97..efcbebfac7 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_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_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/include/raft.h b/include/raft.h index b6f837f53e..a4493f0622 100644 --- a/include/raft.h +++ b/include/raft.h @@ -55,6 +55,18 @@ class Raft */ static size_t getTotalExtraLayers(); + /*! + * \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 getBaseLayers(); + + /*! \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,15 @@ class Raft * \return The type of layer at the given layer index. */ static LayerType getLayerType(LayerIndex layer_index); + +private: + /*! + * \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/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index 5154971d39..79a97b2e7e 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -152,7 +152,6 @@ void FffGcodeWriter::writeGCode(SliceDataStorage& storage, TimeKeeper& time_keep gcode.writeTravel(p, extruder_settings.get("speed_travel")); } - calculateExtruderOrderPerLayer(storage); calculatePrimeLayerPerExtruder(storage); @@ -572,7 +571,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(); @@ -592,7 +590,7 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) Shape 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_; @@ -746,6 +744,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); } @@ -759,7 +759,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; @@ -784,18 +783,9 @@ 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) - { - 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); @@ -908,11 +898,7 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) raft_polygons.clear(); raft_lines.clear(); - if (! prime_tower_added_on_this_layer) - { - setExtruder_addPrime(storage, gcode_layer, prime_tower_extruder_nr); - current_extruder_nr = prime_tower_extruder_nr; - } + endRaftLayer(storage, gcode_layer, layer_nr, current_extruder_nr); layer_plan_buffer.handle(gcode_layer, gcode); last_planned_position = gcode_layer.getLastPlannedPositionOrStartingPosition(); @@ -929,7 +915,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; @@ -954,20 +939,11 @@ 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 - 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); Shape raft_outline_path; @@ -1098,16 +1074,41 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) raft_lines.clear(); } - if (! prime_tower_added_on_this_layer) - { - setExtruder_addPrime(storage, gcode_layer, prime_tower_extruder_nr); - current_extruder_nr = prime_tower_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, const bool append_to_prime_tower) +{ + // If required, fill prime tower with 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 (! 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, append_to_prime_tower); + 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); @@ -1227,19 +1228,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); @@ -1266,14 +1259,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(); @@ -1555,7 +1540,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) @@ -1581,9 +1576,32 @@ 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(); + Raft::LayerType layer_type = Raft::getLayerType(layer_nr); + + 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_; + 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++) @@ -1606,7 +1624,7 @@ std::vector FffGcodeWriter::getUsedExtrudersOnLayer( } } - // Now check whether extuders should really 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) { @@ -3916,7 +3934,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); @@ -3949,7 +3967,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 diff --git a/src/PrimeTower.cpp b/src/PrimeTower.cpp index ecde02dffe..bc4e2a07a7 100644 --- a/src/PrimeTower.cpp +++ b/src/PrimeTower.cpp @@ -30,28 +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"); - - { - 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; - - would_have_actual_tower_ = enabled_; // Assume so for now. } void PrimeTower::initializeExtruders(const std::vector& used_extruders) @@ -112,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(); @@ -327,7 +309,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/gcodeExport.cpp b/src/gcodeExport.cpp index 98d95d3f07..f071582d77 100644 --- a/src/gcodeExport.cpp +++ b/src/gcodeExport.cpp @@ -767,69 +767,73 @@ 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; - 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(); + struct ExtruderInitialize + { + size_t nr; + Temperature temperature; + }; - if (scene.current_mesh_group->settings.get("material_print_temp_prepend") || (scene.current_mesh_group != scene.mesh_groups.begin())) + std::vector all_extruders; + std::vector extruders_used = storage.getExtrudersUsed(); + for (size_t extruder_nr = 0; extruder_nr < extruders_used.size(); ++extruder_nr) + { + if (extruders_used[extruder_nr]) { - for (unsigned extruder_nr = 0; extruder_nr < num_extruders; extruder_nr++) + const ExtruderTrain& train = scene.extruders[extruder_nr]; + Temperature extruder_temp; + if (extruder_nr == start_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); - } + 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"); } - if (scene.current_mesh_group->settings.get("material_print_temp_wait")) + else { - 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); - } - } + extruder_temp = train.settings_.get("material_standby_temperature"); } + + 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); } } } @@ -1476,7 +1480,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_write_on_equal) { const ExtruderTrain& extruder_train = Application::getInstance().current_slice_->scene.extruders[extruder]; @@ -1512,7 +1516,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_write_on_equal && extruder_attr_[extruder].current_temperature_ == temperature) { return; } diff --git a/src/raft.cpp b/src/raft.cpp index 8bc54ec41e..ef08c19d6d 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() @@ -182,39 +168,46 @@ coord_t Raft::getFillerLayerHeight() return round_divide(getZdiffBetweenRaftAndLayer0(), getFillerLayerCount()); } - size_t Raft::getTotalExtraLayers() +{ + return getBaseLayers() + getInterfaceLayers() + getSurfaceLayers() + getFillerLayerCount(); +} + +size_t Raft::getBaseLayers() { 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) { - 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; } @@ -228,5 +221,17 @@ Raft::LayerType Raft::getLayerType(LayerIndex layer_index) } } +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) + { + return 0; + } + + const ExtruderTrain& train = mesh_group_settings.get(extruder_nr_setting_name); + return train.settings_.get(target_raft_section); +} + } // namespace cura diff --git a/src/sliceDataStorage.cpp b/src/sliceDataStorage.cpp index 2447ce356f..b50bcc5c26 100644 --- a/src/sliceDataStorage.cpp +++ b/src/sliceDataStorage.cpp @@ -484,8 +484,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 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). @@ -497,11 +497,11 @@ std::vector SliceDataStorage::getExtrudersUsed(const LayerIndex layer_nr) } } } - else if (layer_nr == -raft_layers + 1) // 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; }