diff --git a/xs/src/libslic3r/ExtrusionEntity.hpp b/xs/src/libslic3r/ExtrusionEntity.hpp index 16ef51c1f..15363e8ed 100644 --- a/xs/src/libslic3r/ExtrusionEntity.hpp +++ b/xs/src/libslic3r/ExtrusionEntity.hpp @@ -92,6 +92,7 @@ public: virtual double min_mm3_per_mm() const = 0; virtual Polyline as_polyline() const = 0; virtual double length() const = 0; + virtual double total_volume() const = 0; }; typedef std::vector ExtrusionEntitiesPtr; @@ -148,6 +149,7 @@ public: // Minimum volumetric velocity of this extrusion entity. Used by the constant nozzle pressure algorithm. double min_mm3_per_mm() const { return this->mm3_per_mm; } Polyline as_polyline() const { return this->polyline; } + virtual double total_volume() const { return mm3_per_mm * unscale(length()); } private: void _inflate_collection(const Polylines &polylines, ExtrusionEntityCollection* collection) const; @@ -194,6 +196,7 @@ public: // Minimum volumetric velocity of this extrusion entity. Used by the constant nozzle pressure algorithm. double min_mm3_per_mm() const; Polyline as_polyline() const; + virtual double total_volume() const { double volume =0.; for (const auto& path : paths) volume += path.total_volume(); return volume; } }; // Single continuous extrusion loop, possibly with varying extrusion thickness, extrusion height or bridging / non bridging. @@ -241,6 +244,7 @@ public: // Minimum volumetric velocity of this extrusion entity. Used by the constant nozzle pressure algorithm. double min_mm3_per_mm() const; Polyline as_polyline() const { return this->polygon().split_at_first_point(); } + virtual double total_volume() const { double volume =0.; for (const auto& path : paths) volume += path.total_volume(); return volume; } private: ExtrusionLoopRole m_loop_role; diff --git a/xs/src/libslic3r/ExtrusionEntityCollection.cpp b/xs/src/libslic3r/ExtrusionEntityCollection.cpp index 4513139e2..7a086bcbf 100644 --- a/xs/src/libslic3r/ExtrusionEntityCollection.cpp +++ b/xs/src/libslic3r/ExtrusionEntityCollection.cpp @@ -125,6 +125,7 @@ void ExtrusionEntityCollection::chained_path_from(Point start_near, ExtrusionEnt continue; } } + ExtrusionEntity* entity = (*it)->clone(); my_paths.push_back(entity); if (orig_indices != NULL) indices_map[entity] = it - this->entities.begin(); diff --git a/xs/src/libslic3r/ExtrusionEntityCollection.hpp b/xs/src/libslic3r/ExtrusionEntityCollection.hpp index 03bd2ba97..d292248fc 100644 --- a/xs/src/libslic3r/ExtrusionEntityCollection.hpp +++ b/xs/src/libslic3r/ExtrusionEntityCollection.hpp @@ -79,6 +79,7 @@ public: void flatten(ExtrusionEntityCollection* retval) const; ExtrusionEntityCollection flatten() const; double min_mm3_per_mm() const; + virtual double total_volume() const {double volume=0.; for (const auto& ent : entities) volume+=ent->total_volume(); return volume; } // Following methods shall never be called on an ExtrusionEntityCollection. Polyline as_polyline() const { @@ -89,6 +90,21 @@ public: CONFESS("Calling length() on a ExtrusionEntityCollection"); return 0.; } + + void set_extruder_override(int extruder) { + extruder_override = extruder; + for (auto& member : entities) { + if (member->is_collection()) + dynamic_cast(member)->set_extruder_override(extruder); + } + } + int get_extruder_override() const { return extruder_override; } + bool is_extruder_overridden() const { return extruder_override != -1; } + + +private: + // Set this variable to explicitly state you want to use specific extruder for thie EEC (used for MM infill wiping) + int extruder_override = -1; }; } diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index b581b3e76..3536c0c9c 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -1249,7 +1249,7 @@ void GCode::process_layer( break; } } - + // process infill // layerm->fills is a collection of Slic3r::ExtrusionPath::Collection objects (C++ class ExtrusionEntityCollection), // each one containing the ExtrusionPath objects of a certain infill "group" (also called "surface" @@ -1261,6 +1261,10 @@ void GCode::process_layer( if (fill->entities.empty()) // This shouldn't happen but first_point() would fail. continue; + + if (fill->is_extruder_overridden()) + continue; + // init by_extruder item only if we actually use the extruder int extruder_id = std::max(0, (is_solid_infill(fill->entities.front()->role()) ? region.config.solid_infill_extruder : region.config.infill_extruder) - 1); // Init by_extruder item only if we actually use the extruder. @@ -1334,15 +1338,37 @@ void GCode::process_layer( m_avoid_crossing_perimeters.disable_once = true; } + for (const auto& layer_to_print : layers) { // iterate through all objects + if (layer_to_print.object_layer == nullptr) + continue; + std::vector overridden; + for (size_t region_id = 0; region_id < print.regions.size(); ++ region_id) { + ObjectByExtruder::Island::Region new_region; + overridden.push_back(new_region); + for (ExtrusionEntity *ee : (*layer_to_print.object_layer).regions[region_id]->fills.entities) { + auto *fill = dynamic_cast(ee); + if (fill->get_extruder_override() == extruder_id) { + overridden.back().infills.append(*fill); + fill->set_extruder_override(-1); + } + } + m_config.apply((layer_to_print.object_layer)->object()->config, true); + Point copy = (layer_to_print.object_layer)->object()->_shifted_copies.front(); + this->set_origin(unscale(copy.x), unscale(copy.y)); + gcode += this->extrude_infill(print, overridden); + } + } + + auto objects_by_extruder_it = by_extruder.find(extruder_id); if (objects_by_extruder_it == by_extruder.end()) continue; for (const ObjectByExtruder &object_by_extruder : objects_by_extruder_it->second) { const size_t layer_id = &object_by_extruder - objects_by_extruder_it->second.data(); const PrintObject *print_object = layers[layer_id].object(); - if (print_object == nullptr) - // This layer is empty for this particular object, it has neither object extrusions nor support extrusions at this print_z. - continue; + if (print_object == nullptr) + // This layer is empty for this particular object, it has neither object extrusions nor support extrusions at this print_z. + continue; m_config.apply(print_object->config, true); m_layer = layers[layer_id].layer(); @@ -1355,6 +1381,7 @@ void GCode::process_layer( copies.push_back(print_object->_shifted_copies[single_object_idx]); // Sort the copies by the closest point starting with the current print position. + for (const Point © : copies) { // When starting a new object, use the external motion planner for the first travel move. std::pair this_object_copy(print_object, copy); @@ -2004,6 +2031,7 @@ std::string GCode::extrude_perimeters(const Print &print, const std::vector &by_region) { std::string gcode; diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 643ab3f31..82f513d70 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -1037,6 +1037,26 @@ void Print::_make_wipe_tower() if (! this->has_wipe_tower()) return; + + int wiping_extruder = 0; + + for (size_t i = 0; i < objects.size(); ++ i) { + for (Layer* lay : objects[i]->layers) { + for (LayerRegion* reg : lay->regions) { + ExtrusionEntityCollection& eec = reg->fills; + for (ExtrusionEntity* ee : eec.entities) { + auto* fill = dynamic_cast(ee); + /*if (fill->total_volume() > 1.)*/ { + fill->set_extruder_override(wiping_extruder); + if (++wiping_extruder > 3) + wiping_extruder = 0; + } + } + } + } + } + + // Let the ToolOrdering class know there will be initial priming extrusions at the start of the print. m_tool_ordering = ToolOrdering(*this, (unsigned int)-1, true); if (! m_tool_ordering.has_wipe_tower())