Custom G-code references are now being assigned to ToolOrdering::LayerTools()

and the superfluous M600 (color change) events are filtered out there.

Fixed a handful of compiler warnings.
This commit is contained in:
bubnikv 2020-01-14 11:54:09 +01:00
parent 8bfc986fa7
commit 98e49772ed
9 changed files with 100 additions and 131 deletions

View File

@ -107,9 +107,9 @@ double Flow::mm3_per_mm() const
{
float res = this->bridge ?
// Area of a circle with dmr of this->width.
(this->width * this->width) * 0.25 * PI :
float((this->width * this->width) * 0.25 * PI) :
// Rectangle with semicircles at the ends. ~ h (w - 0.215 h)
this->height * (this->width - this->height * (1. - 0.25 * PI));
float(this->height * (this->width - this->height * (1. - 0.25 * PI)));
//assert(res > 0.);
if (res <= 0.)
throw std::runtime_error("Flow::mm3_per_mm() produced negative flow. Did you set some extrusion width too small?");

View File

@ -1134,9 +1134,6 @@ void GCode::_do_export(Print& print, FILE* file)
m_enable_cooling_markers = true;
this->apply_print_config(print.config());
// Initialize custom gcode iterator.
m_custom_gcode_per_print_z_it = print.model().custom_gcode_per_print_z.cbegin();
m_volumetric_speed = DoExport::autospeed_volumetric_limit(print);
print.throw_if_canceled();
@ -1226,10 +1223,7 @@ void GCode::_do_export(Print& print, FILE* file)
// Find tool ordering for all the objects at once, and the initial extruder ID.
// If the tool ordering has been pre-calculated by Print class for wipe tower already, reuse it.
tool_ordering = print.wipe_tower_data().tool_ordering.empty() ?
ToolOrdering(print, initial_extruder_id, false,
// Use the extruder switches from Model::custom_gcode_per_print_z to override the extruder to print the object.
// Do it only if all the objects were configured to be printed with a single extruder.
(print.object_extruders().size() == 1) ? &custom_tool_changes(print.model(), (unsigned int)m_config.nozzle_diameter.size()) : nullptr) :
ToolOrdering(print, initial_extruder_id, false) :
print.wipe_tower_data().tool_ordering;
has_wipe_tower = print.has_wipe_tower() && tool_ordering.has_wipe_tower();
initial_extruder_id = (has_wipe_tower && ! print.config().single_extruder_multi_material_priming) ?
@ -1251,49 +1245,6 @@ void GCode::_do_export(Print& print, FILE* file)
}
print.throw_if_canceled();
// #ys_FIXME_no_exported_codes
/*
/* To avoid change filament for non-used extruder for Multi-material,
* check print.model().custom_gcode_per_print_z using tool_ordering values
* /
if (!m_custom_gcode_per_print_z. empty())
{
bool delete_executed = false;
auto it = m_custom_gcode_per_print_z.end();
while (it != m_custom_gcode_per_print_z.begin())
{
--it;
if (it->gcode != ColorChangeCode)
continue;
auto it_layer_tools = std::lower_bound(tool_ordering.begin(), tool_ordering.end(), LayerTools(it->print_z));
bool used_extruder = false;
for (; it_layer_tools != tool_ordering.end(); it_layer_tools++)
{
const std::vector<unsigned>& extruders = it_layer_tools->extruders;
if (std::find(extruders.begin(), extruders.end(), (unsigned)(it->extruder-1)) != extruders.end())
{
used_extruder = true;
break;
}
}
if (used_extruder)
continue;
/* If we are there, current extruder wouldn't be used,
* so this color change is a redundant move.
* Delete this item from m_custom_gcode_per_print_z
* /
it = m_custom_gcode_per_print_z.erase(it);
delete_executed = true;
}
if (delete_executed)
print.model().custom_gcode_per_print_z = m_custom_gcode_per_print_z;
}
*/
m_cooling_buffer->set_current_extruder(initial_extruder_id);
// Emit machine envelope limits for the Marlin firmware.
@ -1779,62 +1730,39 @@ namespace ProcessLayer
{
std::string emit_custom_gcode_per_print_z(
// Last processed CustomGCode.
std::vector<Model::CustomGCode>::const_iterator &custom_gcode_per_print_z_it,
const std::vector<Model::CustomGCode>::const_iterator custom_gcode_per_print_z_end,
// This layer's print_z.
coordf_t current_print_z,
const Model::CustomGCode *custom_gcode,
// ID of the first extruder printing this layer.
unsigned int first_extruder_id,
size_t num_extruders)
bool single_material_print)
{
// Let's issue a filament change command if requested at this layer.
// In case there are more toolchange requests that weren't done yet and should happen simultaneously, erase them all.
// (Layers can be close to each other, model could have been resliced with bigger layer height, ...).
bool has_colorchange = false;
std::string gcode;
std::string custom_code;
if (custom_gcode != nullptr) {
// Extruder switches are processed by LayerTools, they should be filtered out.
assert(custom_gcode->gcode != ExtruderChangeCode);
const std::string &custom_code = custom_gcode->gcode;
std::string pause_print_msg;
int m600_before_extruder = -1;
while (custom_gcode_per_print_z_it != custom_gcode_per_print_z_end) {
auto it_next = custom_gcode_per_print_z_it;
if ((++ it_next)->print_z >= current_print_z + EPSILON)
break;
custom_gcode_per_print_z_it = it_next;
}
if (custom_gcode_per_print_z_it != custom_gcode_per_print_z_end && custom_gcode_per_print_z_it->print_z < current_print_z + EPSILON) {
custom_code = custom_gcode_per_print_z_it->gcode;
if (custom_code == ColorChangeCode && custom_gcode_per_print_z_it->extruder > 0)
m600_before_extruder = custom_gcode_per_print_z_it->extruder - 1;
if (custom_code == PausePrintCode)
pause_print_msg = custom_gcode_per_print_z_it->color;
// This color change is consumed, don't use it again.
++ custom_gcode_per_print_z_it;
has_colorchange = true;
}
int m600_extruder_before_layer = -1;
if (custom_code == ColorChangeCode && custom_gcode->extruder > 0)
m600_extruder_before_layer = custom_gcode->extruder - 1;
else if (custom_code == PausePrintCode)
pause_print_msg = custom_gcode->color;
// we should add or not colorprint_change in respect to nozzle_diameter count instead of really used extruders count
// don't save "tool_change"(ExtruderChangeCode) code to GCode
std::string gcode;
if (has_colorchange && custom_code != ExtruderChangeCode) {
const bool single_material_print = num_extruders == 1;
if (custom_code == ColorChangeCode) // color change
{
// add tag for analyzer
gcode += "; " + GCodeAnalyzer::Color_Change_Tag + ",T" + std::to_string(m600_before_extruder) + "\n";
gcode += "; " + GCodeAnalyzer::Color_Change_Tag + ",T" + std::to_string(m600_extruder_before_layer) + "\n";
// add tag for time estimator
gcode += "; " + GCodeTimeEstimator::Color_Change_Tag + "\n";
if (!single_material_print && m600_before_extruder >= 0 && first_extruder_id != m600_before_extruder
if (!single_material_print && m600_extruder_before_layer >= 0 && first_extruder_id != m600_extruder_before_layer
// && !MMU1
) {
//! FIXME_in_fw show message during print pause
gcode += "M601\n"; // pause print
gcode += "M117 Change filament for Extruder " + std::to_string(m600_before_extruder) + "\n";
gcode += "M117 Change filament for Extruder " + std::to_string(m600_extruder_before_layer) + "\n";
}
else
gcode += custom_code + "\n";
@ -2048,11 +1976,7 @@ void GCode::process_layer(
if (single_object_instance_idx == size_t(-1) && object_layer != nullptr) {
// Normal (non-sequential) print.
gcode += ProcessLayer::emit_custom_gcode_per_print_z(
// input / output
m_custom_gcode_per_print_z_it,
// inputs
print.model().custom_gcode_per_print_z.cend(), layer.print_z, first_extruder_id, print.config().nozzle_diameter.size());
gcode += ProcessLayer::emit_custom_gcode_per_print_z(layer_tools.custom_gcode, first_extruder_id, print.config().nozzle_diameter.size() == 1);
// Extrude skirt at the print_z of the raft layers and normal object layers
// not at the print_z of the interlaced support material layers.
skirt_loops_per_extruder = first_layer ?

View File

@ -374,9 +374,6 @@ private:
bool m_second_layer_things_done;
// Index of a last object copy extruded.
std::pair<const PrintObject*, Point> m_last_obj_copy;
// Iterator to Model::custom_gcode_per_print_z, which is being increased by process_layer.
// The Model::custom_gcode_per_print_z may contain color changes, extruder switches, pauses and custom G-codes.
std::vector<Model::CustomGCode>::const_iterator m_custom_gcode_per_print_z_it;
// Time estimators
GCodeTimeEstimator m_normal_time_estimator;

View File

@ -956,7 +956,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ
GCodePreviewData::Extrusion::Path &path = paths.back();
path.polyline = polyline;
path.extrusion_role = data.extrusion_role;
path.mm3_per_mm = data.mm3_per_mm;
path.mm3_per_mm = float(data.mm3_per_mm);
path.width = data.width;
path.height = data.height;
path.feedrate = data.feedrate;

View File

@ -303,8 +303,8 @@ std::vector<PerExtruderAdjustments> CoolingBuffer::parse_layer_gcode(const std::
unsigned int extruder_id = extruders[i].id();
adj.extruder_id = extruder_id;
adj.cooling_slow_down_enabled = config.cooling.get_at(extruder_id);
adj.slowdown_below_layer_time = config.slowdown_below_layer_time.get_at(extruder_id);
adj.min_print_speed = config.min_print_speed.get_at(extruder_id);
adj.slowdown_below_layer_time = float(config.slowdown_below_layer_time.get_at(extruder_id));
adj.min_print_speed = float(config.min_print_speed.get_at(extruder_id));
map_extruder_to_per_extruder_adjustment[extruder_id] = i;
}

View File

@ -29,7 +29,7 @@ static inline BoundingBox extrusion_polyline_extents(const Polyline &polyline, c
static inline BoundingBoxf extrusionentity_extents(const ExtrusionPath &extrusion_path)
{
BoundingBox bbox = extrusion_polyline_extents(extrusion_path.polyline, scale_(0.5 * extrusion_path.width));
BoundingBox bbox = extrusion_polyline_extents(extrusion_path.polyline, coord_t(scale_(0.5 * extrusion_path.width)));
BoundingBoxf bboxf;
if (! empty(bbox)) {
bboxf.min = unscale(bbox.min);
@ -43,7 +43,7 @@ static inline BoundingBoxf extrusionentity_extents(const ExtrusionLoop &extrusio
{
BoundingBox bbox;
for (const ExtrusionPath &extrusion_path : extrusion_loop.paths)
bbox.merge(extrusion_polyline_extents(extrusion_path.polyline, scale_(0.5 * extrusion_path.width)));
bbox.merge(extrusion_polyline_extents(extrusion_path.polyline, coord_t(scale_(0.5 * extrusion_path.width))));
BoundingBoxf bboxf;
if (! empty(bbox)) {
bboxf.min = unscale(bbox.min);
@ -57,7 +57,7 @@ static inline BoundingBoxf extrusionentity_extents(const ExtrusionMultiPath &ext
{
BoundingBox bbox;
for (const ExtrusionPath &extrusion_path : extrusion_multi_path.paths)
bbox.merge(extrusion_polyline_extents(extrusion_path.polyline, scale_(0.5 * extrusion_path.width)));
bbox.merge(extrusion_polyline_extents(extrusion_path.polyline, coord_t(scale_(0.5 * extrusion_path.width))));
BoundingBoxf bboxf;
if (! empty(bbox)) {
bboxf.min = unscale(bbox.min);

View File

@ -15,6 +15,8 @@
#include <libslic3r.h>
#include "../GCodeWriter.hpp"
namespace Slic3r {
@ -99,7 +101,7 @@ ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extrude
// For the use case when all objects are printed at once.
// (print.config().complete_objects is false).
ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool prime_multi_material, const std::vector<std::pair<double, unsigned int>> *per_layer_extruder_switches)
ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool prime_multi_material)
{
m_print_config_ptr = &print.config();
@ -124,9 +126,16 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool
this->initialize_layers(zs);
}
// Use the extruder switches from Model::custom_gcode_per_print_z to override the extruder to print the object.
// Do it only if all the objects were configured to be printed with a single extruder.
const std::vector<std::pair<double, unsigned int>> *per_layer_extruder_switches = (print.object_extruders().size() == 1) ?
&custom_tool_changes(print.model(), (unsigned int)print.config().nozzle_diameter.size()) : nullptr;
if (per_layer_extruder_switches != nullptr && per_layer_extruder_switches->empty())
per_layer_extruder_switches = nullptr;
// Collect extruders reuqired to print the layers.
for (auto object : print.objects())
this->collect_extruders(*object, (per_layer_extruder_switches != nullptr && ! per_layer_extruder_switches->empty()) ? per_layer_extruder_switches : nullptr);
this->collect_extruders(*object, per_layer_extruder_switches);
// Reorder the extruders to minimize tool switches.
this->reorder_extruders(first_extruder);
@ -134,6 +143,11 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool
this->fill_wipe_tower_partitions(print.config(), object_bottom_z);
this->collect_extruder_statistics(prime_multi_material);
// Assign custom G-code actions from Model::custom_gcode_per_print_z to their respecive layers,
// ignoring the extruder switches, which were processed above, and ignoring color changes for extruders,
// that do not print above their respective print_z.
this->assign_custom_gcodes(print);
}
void ToolOrdering::initialize_layers(std::vector<coordf_t> &zs)
@ -444,6 +458,46 @@ void ToolOrdering::collect_extruder_statistics(bool prime_multi_material)
}
}
// Assign a pointer to a custom G-code to the respective ToolOrdering::LayerTools.
// Ignore color changes, which are performed on a layer and for such an extruder, that the extruder will not be printing above that layer.
// If multiple events are planned over a span of a single layer, use the last one.
void ToolOrdering::assign_custom_gcodes(const Print &print)
{
const std::vector<Model::CustomGCode> &custom_gcode_per_print_z = print.model().custom_gcode_per_print_z;
if (custom_gcode_per_print_z.empty())
return;
unsigned int num_extruders = *std::max_element(m_all_printing_extruders.begin(), m_all_printing_extruders.end()) + 1;
std::vector<unsigned char> extruder_printing_above(num_extruders, false);
auto custom_gcode_it = custom_gcode_per_print_z.rbegin();
// From the last layer to the first one:
for (auto it_lt = m_layer_tools.rbegin(); it_lt != m_layer_tools.rend(); ++ it_lt) {
LayerTools &lt = *it_lt;
// Add the extruders of the current layer to the set of extruders printing at and above this print_z.
for (unsigned int i : lt.extruders)
extruder_printing_above[i] = true;
// Skip all custom G-codes above this layer and skip all extruder switches.
for (; custom_gcode_it != custom_gcode_per_print_z.rend() && (custom_gcode_it->print_z > lt.print_z + EPSILON || custom_gcode_it->gcode == ExtruderChangeCode); ++ custom_gcode_it);
if (custom_gcode_it == custom_gcode_per_print_z.rend())
// Custom G-codes were processed.
break;
// Some custom G-code is configured for this layer or a layer below.
const Model::CustomGCode &custom_gcode = *custom_gcode_it;
// print_z of the layer below the current layer.
coordf_t print_z_below = 0.;
if (auto it_lt_below = it_lt; -- it_lt_below != m_layer_tools.rend())
print_z_below = it_lt_below->print_z;
if (custom_gcode.print_z > print_z_below - EPSILON) {
// The custom G-code applies to the current layer.
if (custom_gcode.gcode != ColorChangeCode || extruder_printing_above[unsigned(custom_gcode.extruder - 1)])
// If it is color change, it will actually be useful as the exturder above will print.
lt.custom_gcode = &custom_gcode;
// Consume that custom G-code event.
-- custom_gcode_it;
}
}
}
const LayerTools& ToolOrdering::tools_for_layer(coordf_t print_z) const
{
auto it_layer_tools = std::lower_bound(m_layer_tools.begin(), m_layer_tools.end(), LayerTools(print_z - EPSILON));

View File

@ -80,14 +80,7 @@ private:
class LayerTools
{
public:
LayerTools(const coordf_t z) :
print_z(z),
has_object(false),
has_support(false),
extruder_override(0),
has_wipe_tower(false),
wipe_tower_partitions(0),
wipe_tower_layer_height(0.) {}
LayerTools(const coordf_t z) : print_z(z) {}
// Changing these operators to epsilon version can make a problem in cases where support and object layers get close to each other.
// In case someone tries to do it, make sure you know what you're doing and test it properly (slice multiple objects at once with supports).
@ -104,22 +97,24 @@ public:
// Returns a zero based extruder this eec should be printed with, according to PrintRegion config or extruder_override if overriden.
unsigned int extruder(const ExtrusionEntityCollection &extrusions, const PrintRegion &region) const;
coordf_t print_z;
bool has_object;
bool has_support;
coordf_t print_z = 0.;
bool has_object = false;
bool has_support = false;
// Zero based extruder IDs, ordered to minimize tool switches.
std::vector<unsigned int> extruders;
// If per layer extruder switches are inserted by the G-code preview slider, this value contains the new (1 based) extruder, with which the whole object layer is being printed with.
// If not overriden, it is set to 0.
unsigned int extruder_override;
unsigned int extruder_override = 0;
// Will there be anything extruded on this layer for the wipe tower?
// Due to the support layers possibly interleaving the object layers,
// wipe tower will be disabled for some support only layers.
bool has_wipe_tower;
bool has_wipe_tower = false;
// Number of wipe tower partitions to support the required number of tool switches
// and to support the wipe tower partitions above this one.
size_t wipe_tower_partitions;
coordf_t wipe_tower_layer_height;
size_t wipe_tower_partitions = 0;
coordf_t wipe_tower_layer_height = 0.;
// Custom G-code (color change, extruder switch, pause) to be performed before this layer starts to print.
const Model::CustomGCode *custom_gcode = nullptr;
WipingExtrusions& wiping_extrusions() {
m_wiping_extrusions.set_layer_tools_ptr(this);
@ -144,7 +139,7 @@ public:
// For the use case when all objects are printed at once.
// (print.config.complete_objects is false).
ToolOrdering(const Print &print, unsigned int first_extruder, bool prime_multi_material = false, const std::vector<std::pair<double, unsigned int>> *per_layer_extruder_switches = nullptr);
ToolOrdering(const Print &print, unsigned int first_extruder, bool prime_multi_material = false);
void clear() { m_layer_tools.clear(); }
@ -175,6 +170,7 @@ private:
void reorder_extruders(unsigned int last_extruder_id);
void fill_wipe_tower_partitions(const PrintConfig &config, coordf_t object_bottom_z);
void collect_extruder_statistics(bool prime_multi_material);
void assign_custom_gcodes(const Print &print);
std::vector<LayerTools> m_layer_tools;
// First printing extruder, including the multi-material priming sequence.
@ -184,7 +180,6 @@ private:
// All extruders, which extrude some material over m_layer_tools.
std::vector<unsigned int> m_all_printing_extruders;
const PrintConfig* m_print_config_ptr = nullptr;
};

View File

@ -1912,8 +1912,8 @@ const WipeTowerData& Print::wipe_tower_data(size_t extruders_cnt, double first_l
// If the wipe tower wasn't created yet, make sure the depth and brim_width members are set to default.
if (! is_step_done(psWipeTower) && extruders_cnt !=0) {
float width = m_config.wipe_tower_width;
float brim_spacing = nozzle_diameter * 1.25f - first_layer_height * (1. - M_PI_4);
float width = float(m_config.wipe_tower_width);
float brim_spacing = float(nozzle_diameter * 1.25f - first_layer_height * (1. - M_PI_4));
const_cast<Print*>(this)->m_wipe_tower_data.depth = (900.f/width) * float(extruders_cnt - 1);
const_cast<Print*>(this)->m_wipe_tower_data.brim_width = 4.5f * brim_spacing;
@ -1938,8 +1938,7 @@ void Print::_make_wipe_tower()
wipe_volumes.push_back(std::vector<float>(wiping_matrix.begin()+i*number_of_extruders, wiping_matrix.begin()+(i+1)*number_of_extruders));
// Let the ToolOrdering class know there will be initial priming extrusions at the start of the print.
m_wipe_tower_data.tool_ordering = ToolOrdering(*this, (unsigned int)-1, true,
(this->object_extruders().size() == 1) ? &custom_tool_changes(this->model(), (unsigned int)m_config.nozzle_diameter.size()) : nullptr);
m_wipe_tower_data.tool_ordering = ToolOrdering(*this, (unsigned int)-1, true);
if (! m_wipe_tower_data.tool_ordering.has_wipe_tower())
// Don't generate any wipe tower.