Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/libslic3r/GCode.cpp')
-rw-r--r--src/libslic3r/GCode.cpp274
1 files changed, 193 insertions, 81 deletions
diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp
index c93303257..495c32bfd 100644
--- a/src/libslic3r/GCode.cpp
+++ b/src/libslic3r/GCode.cpp
@@ -91,7 +91,7 @@ NEXT: ;
}
void AvoidCrossingPerimeters::init_external_mp(const Print &print)
-{
+{
m_external_mp = Slic3r::make_unique<MotionPlanner>(union_ex(this->collect_contours_all_layers(print.objects())));
}
@@ -198,10 +198,10 @@ std::string OozePrevention::pre_toolchange(GCode &gcodegen)
"move to standby position");
}
- if (gcodegen.config().standby_temperature_delta.value != 0) {
+ if (gcodegen.config().standby_temperature_delta.value != 0 && gcodegen.writer().tool_is_extruder()) {
// we assume that heating is always slower than cooling, so no need to block
gcode += gcodegen.writer().set_temperature
- (this->_get_temp(gcodegen) + gcodegen.config().standby_temperature_delta.value, false, gcodegen.writer().extruder()->id());
+ (this->_get_temp(gcodegen) + gcodegen.config().standby_temperature_delta.value, false, gcodegen.writer().tool()->id());
}
return gcode;
@@ -209,17 +209,20 @@ std::string OozePrevention::pre_toolchange(GCode &gcodegen)
std::string OozePrevention::post_toolchange(GCode &gcodegen)
{
- return (gcodegen.config().standby_temperature_delta.value != 0) ?
- gcodegen.writer().set_temperature(this->_get_temp(gcodegen), true, gcodegen.writer().extruder()->id()) :
+ return (gcodegen.config().standby_temperature_delta.value != 0 && gcodegen.writer().tool_is_extruder()) ?
+ gcodegen.writer().set_temperature(this->_get_temp(gcodegen), true, gcodegen.writer().tool()->id()) :
std::string();
}
int
OozePrevention::_get_temp(GCode &gcodegen)
{
- return (gcodegen.layer() != NULL && gcodegen.layer()->id() == 0)
- ? gcodegen.config().first_layer_temperature.get_at(gcodegen.writer().extruder()->id())
- : gcodegen.config().temperature.get_at(gcodegen.writer().extruder()->id());
+ if (gcodegen.writer().tool_is_extruder())
+ return (gcodegen.layer() != NULL && gcodegen.layer()->id() == 0)
+ ? gcodegen.config().first_layer_temperature.get_at(gcodegen.writer().tool()->id())
+ : gcodegen.config().temperature.get_at(gcodegen.writer().tool()->id());
+ else
+ return 0;
}
std::string Wipe::wipe(GCode &gcodegen, bool toolchange)
@@ -232,16 +235,16 @@ std::string Wipe::wipe(GCode &gcodegen, bool toolchange)
// get the retraction length
double length = toolchange
- ? gcodegen.writer().extruder()->retract_length_toolchange()
- : gcodegen.writer().extruder()->retract_length();
+ ? gcodegen.writer().tool()->retract_length_toolchange()
+ : gcodegen.writer().tool()->retract_length();
// Shorten the retraction length by the amount already retracted before wipe.
- length *= (1. - gcodegen.writer().extruder()->retract_before_wipe());
+ length *= (1. - gcodegen.writer().tool()->retract_before_wipe());
- if (length > 0) {
+ if (length > 0 && gcodegen.writer().tool()->retract_speed() > 0) {
/* Calculate how long we need to travel in order to consume the required
amount of retraction. In other words, how far do we move in XY at wipe_speed
for the time needed to consume retract_length at retract_speed? */
- double wipe_dist = scale_(length / gcodegen.writer().extruder()->retract_speed() * wipe_speed);
+ double wipe_dist = scale_(length / gcodegen.writer().tool()->retract_speed() * wipe_speed);
/* Take the stored wipe path and replace first point with the current actual position
(they might be different, for example, in case of loop clipping). */
@@ -345,13 +348,13 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
// Process the end filament gcode.
std::string end_filament_gcode_str;
- if (gcodegen.writer().extruder() != nullptr) {
+ if (gcodegen.writer().tool() != nullptr && gcodegen.writer().tool_is_extruder()) {
// Process the custom end_filament_gcode in case of single_extruder_multi_material.
- unsigned int old_extruder_id = gcodegen.writer().extruder()->id();
+ unsigned int old_extruder_id = gcodegen.writer().tool()->id();
const std::string &end_filament_gcode = gcodegen.config().end_filament_gcode.get_at(old_extruder_id);
- if (gcodegen.writer().extruder() != nullptr && ! end_filament_gcode.empty()) {
+ if (gcodegen.writer().tool() != nullptr && ! end_filament_gcode.empty()) {
DynamicConfig config;
- int previous_extruder_id = gcodegen.writer().extruder() ? (int)gcodegen.writer().extruder()->id() : -1;
+ int previous_extruder_id = gcodegen.writer().tool() ? (int)gcodegen.writer().tool()->id() : -1;
config.set_key_value("previous_extruder", new ConfigOptionInt(previous_extruder_id));
config.set_key_value("next_extruder", new ConfigOptionInt((int)new_extruder_id));
config.set_key_value("layer_num", new ConfigOptionInt(gcodegen.m_layer_index));
@@ -368,7 +371,7 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
const std::string& toolchange_gcode = gcodegen.config().toolchange_gcode.value;
if (!toolchange_gcode.empty()) {
DynamicConfig config;
- int previous_extruder_id = gcodegen.writer().extruder() ? (int)gcodegen.writer().extruder()->id() : -1;
+ int previous_extruder_id = gcodegen.writer().tool() ? (int)gcodegen.writer().tool()->id() : -1;
config.set_key_value("previous_extruder", new ConfigOptionInt(previous_extruder_id));
config.set_key_value("next_extruder", new ConfigOptionInt((int)new_extruder_id));
config.set_key_value("layer_num", new ConfigOptionInt(gcodegen.m_layer_index));
@@ -396,7 +399,7 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
// Process the start_filament_gcode for the active filament only.
DynamicConfig config;
config.set_key_value("filament_extruder_id", new ConfigOptionInt(new_extruder_id));
- config.set_key_value("previous_extruder", new ConfigOptionInt(gcodegen.writer().extruder() ? (int)gcodegen.writer().extruder()->id() : -1));
+ config.set_key_value("previous_extruder", new ConfigOptionInt(gcodegen.writer().tool() ? (int)gcodegen.writer().tool()->id() : -1));
config.set_key_value("next_extruder", new ConfigOptionInt(new_extruder_id));
config.set_key_value("layer_num", new ConfigOptionInt(0));
config.set_key_value("layer_z", new ConfigOptionFloat(z));
@@ -598,6 +601,8 @@ std::string WipeTowerIntegration::finalize(GCode &gcodegen)
}
#define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_writer.extruder()->id())
+#define EXTRUDER_CONFIG_WITH_DEFAULT(OPT,DEF) (m_writer.tool_is_extruder()?m_config.OPT.get_at(m_writer.tool()->id()):DEF)
+#define BOOL_EXTRUDER_CONFIG(OPT) m_writer.tool_is_extruder() && m_config.OPT.get_at(m_writer.tool()->id())
// Collect pairs of object_layer + support_layer sorted by print_z.
// object_layer & support_layer are considered to be on the same print_z, if they are not further than EPSILON.
@@ -905,12 +910,12 @@ namespace DoExport {
// send extruder offset data to analyzer
GCodeAnalyzer::ExtruderOffsetsMap extruder_offsets;
unsigned int num_extruders = static_cast<unsigned int>(config.nozzle_diameter.values.size());
- for (unsigned int extruder_id = 0; extruder_id < num_extruders; ++ extruder_id)
- {
- Vec2d offset = config.extruder_offset.get_at(extruder_id);
- if (!offset.isApprox(Vec2d::Zero()))
- extruder_offsets[extruder_id] = offset;
- }
+ for (unsigned int extruder_id = 0; extruder_id < num_extruders; ++extruder_id)
+ {
+ Vec2d offset = config.extruder_offset.get_at(extruder_id);
+ if (!offset.isApprox(Vec2d::Zero()))
+ extruder_offsets[extruder_id] = offset;
+ }
analyzer.set_extruder_offsets(extruder_offsets);
// tell analyzer about the extrusion axis
@@ -1330,6 +1335,19 @@ void GCode::_do_export(Print &print, FILE *file)
bool has_wipe_tower = false;
std::vector<const PrintInstance*> print_object_instances_ordering;
std::vector<const PrintInstance*>::const_iterator print_object_instance_sequential_active;
+ bool has_milling = false;
+ if (!config().milling_diameter.values.empty()) {
+ for (const PrintObject* obj : print.objects()) {
+ for (const Layer *layer : obj->layers()) {
+ for (const LayerRegion *lr : layer->regions()) {
+ if (!lr->milling.empty()) {
+ has_milling = true;
+ break;
+ }
+ }
+ }
+ }
+ }
if (print.config().complete_objects.value) {
// Order object instances for sequential print.
if(print.config().complete_objects_sort.value == cosObject)
@@ -1348,6 +1366,8 @@ void GCode::_do_export(Print &print, FILE *file)
// We don't allow switching of extruders per layer by Model::custom_gcode_per_print_z in sequential mode.
// Use the extruder IDs collected from Regions.
this->set_extruders(print.extruders());
+ if(has_milling)
+ m_writer.set_mills(std::vector<uint16_t>() = { 0 });
} else {
// 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.
@@ -1362,6 +1382,8 @@ void GCode::_do_export(Print &print, FILE *file)
// In non-sequential print, the printing extruders may have been modified by the extruder switches stored in Model::custom_gcode_per_print_z.
// Therefore initialize the printing extruders from there.
this->set_extruders(tool_ordering.all_extruders());
+ if (has_milling)
+ m_writer.set_mills(std::vector<uint16_t>() = { 0 });
// Order object instances using a nearest neighbor search.
print_object_instances_ordering = chain_print_object_instances(print);
}
@@ -1566,22 +1588,25 @@ void GCode::_do_export(Print &print, FILE *file)
{
DynamicConfig config;
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
- config.set_key_value("layer_z", new ConfigOptionFloat(m_writer.get_position()(2) - m_config.z_offset.value));
- if (print.config().single_extruder_multi_material) {
- // Process the end_filament_gcode for the active filament only.
- int extruder_id = m_writer.extruder()->id();
- config.set_key_value("filament_extruder_id", new ConfigOptionInt(extruder_id));
- _writeln(file, this->placeholder_parser_process("end_filament_gcode", print.config().end_filament_gcode.get_at(extruder_id), extruder_id, &config));
- } else {
- for (const std::string &end_gcode : print.config().end_filament_gcode.values) {
- int extruder_id = (unsigned int)(&end_gcode - &print.config().end_filament_gcode.values.front());
+ config.set_key_value("layer_z", new ConfigOptionFloat(m_writer.get_position()(2) - m_config.z_offset.value));
+ config.set_key_value("current_extruder_id", new ConfigOptionInt((int)m_writer.tool()->id()));
+ if (m_writer.tool_is_extruder()) {
+ if (print.config().single_extruder_multi_material) {
+ // Process the end_filament_gcode for the active filament only.
+ int extruder_id = m_writer.tool()->id();
config.set_key_value("filament_extruder_id", new ConfigOptionInt(extruder_id));
- config.set_key_value("previous_extruder", new ConfigOptionInt(extruder_id));
- config.set_key_value("next_extruder", new ConfigOptionInt(0));
- _writeln(file, this->placeholder_parser_process("end_filament_gcode", end_gcode, extruder_id, &config));
+ _writeln(file, this->placeholder_parser_process("end_filament_gcode", print.config().end_filament_gcode.get_at(extruder_id), extruder_id, &config));
+ } else {
+ for (const std::string& end_gcode : print.config().end_filament_gcode.values) {
+ int extruder_id = (unsigned int)(&end_gcode - &print.config().end_filament_gcode.values.front());
+ config.set_key_value("filament_extruder_id", new ConfigOptionInt(extruder_id));
+ config.set_key_value("previous_extruder", new ConfigOptionInt(extruder_id));
+ config.set_key_value("next_extruder", new ConfigOptionInt(0));
+ _writeln(file, this->placeholder_parser_process("end_filament_gcode", end_gcode, extruder_id, &config));
+ }
}
}
- _writeln(file, this->placeholder_parser_process("end_gcode", print.config().end_gcode, m_writer.extruder()->id(), &config));
+ _writeln(file, this->placeholder_parser_process("end_gcode", print.config().end_gcode, m_writer.tool()->id(), &config));
}
_write(file, m_writer.update_progress(m_layer_count, m_layer_count, true)); // 100%
_write(file, m_writer.postamble());
@@ -1889,17 +1914,17 @@ std::string GCode::emit_custom_gcode_per_print_z(
//update stats : weight
double previously_extruded = 0;
for (const auto& tuple : stats.color_extruderid_to_used_weight)
- if (tuple.first == this->m_writer.extruder()->id())
+ if (tuple.first == this->m_writer.tool()->id())
previously_extruded += tuple.second;
- double extruded = this->m_writer.extruder()->filament_density() * this->m_writer.extruder()->extruded_volume();
- stats.color_extruderid_to_used_weight.emplace_back(this->m_writer.extruder()->id(), extruded - previously_extruded);
+ double extruded = this->m_writer.tool()->filament_density() * this->m_writer.tool()->extruded_volume();
+ stats.color_extruderid_to_used_weight.emplace_back(this->m_writer.tool()->id(), extruded - previously_extruded);
//update stats : length
previously_extruded = 0;
for (const auto& tuple : stats.color_extruderid_to_used_filament)
- if (tuple.first == this->m_writer.extruder()->id())
+ if (tuple.first == this->m_writer.tool()->id())
previously_extruded += tuple.second;
- stats.color_extruderid_to_used_filament.emplace_back(this->m_writer.extruder()->id(), this->m_writer.extruder()->used_filament() - previously_extruded);
+ stats.color_extruderid_to_used_filament.emplace_back(this->m_writer.tool()->id(), this->m_writer.tool()->used_filament() - previously_extruded);
}
// we should add or not colorprint_change in respect to nozzle_diameter count instead of really used extruders count
@@ -2085,7 +2110,7 @@ void GCode::process_layer(
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index + 1));
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
gcode += this->placeholder_parser_process("before_layer_gcode",
- print.config().before_layer_gcode.value, m_writer.extruder()->id(), &config)
+ print.config().before_layer_gcode.value, m_writer.tool()->id(), &config)
+ "\n";
}
gcode += this->change_layer(print_z); // this will increase m_layer_index
@@ -2095,7 +2120,7 @@ void GCode::process_layer(
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
gcode += this->placeholder_parser_process("layer_gcode",
- print.config().layer_gcode.value, m_writer.extruder()->id(), &config)
+ print.config().layer_gcode.value, m_writer.tool()->id(), &config)
+ "\n";
}
@@ -2103,7 +2128,7 @@ void GCode::process_layer(
// Transition from 1st to 2nd layer. Adjust nozzle temperatures as prescribed by the nozzle dependent
// first_layer_temperature vs. temperature settings.
for (const Extruder &extruder : m_writer.extruders()) {
- if (print.config().single_extruder_multi_material.value && extruder.id() != m_writer.extruder()->id())
+ if (print.config().single_extruder_multi_material.value && extruder.id() != m_writer.tool()->id())
// In single extruder multi material mode, set the temperature for the current extruder only.
continue;
int temperature = print.config().temperature.get_at(extruder.id());
@@ -2434,6 +2459,81 @@ void GCode::process_layer(
if (m_spiral_vase)
gcode = m_spiral_vase->process_layer(gcode);
+
+ //add milling post-process if enabled
+ if (!config().milling_diameter.values.empty()) {
+ bool milling_ok = false;
+ for (const LayerToPrint& ltp : layers) {
+ if (ltp.object_layer != nullptr) {
+ for (const LayerRegion* lr : ltp.object_layer->regions()) {
+ if (!lr->milling.empty()) {
+ milling_ok = true;
+ break;
+ }
+ }
+ }
+ }
+ if (milling_ok) {
+ //switch to mill
+ gcode += "; milling ok\n";
+ uint32_t current_extruder_filament = m_writer.tool()->id();
+ uint32_t milling_extruder_id = config().nozzle_diameter.values.size();
+ gcode += "; toolchange:\n";
+ gcode += m_writer.toolchange(milling_extruder_id);
+ gcode += "; toolchange done\n";
+ m_placeholder_parser.set("current_extruder", milling_extruder_id);
+ // Append the filament start G-code.
+ const std::string& start_mill_gcode = m_config.milling_toolchange_start_gcode.get_at(0);
+ if (!start_mill_gcode.empty()) {
+ DynamicConfig config;
+ config.set_key_value("previous_extruder", new ConfigOptionInt((int)current_extruder_filament));
+ config.set_key_value("next_extruder", new ConfigOptionInt((int)milling_extruder_id));
+ config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
+ config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
+ // Process the start_mill_gcode for the new filament.
+ gcode += this->placeholder_parser_process("milling_toolchange_start_gcode", start_mill_gcode, current_extruder_filament, &config);
+ check_add_eol(gcode);
+ }
+
+ gcode += "\n; began print:";
+ for (const LayerToPrint& ltp : layers) {
+ if (ltp.object_layer != nullptr) {
+ for (const PrintInstance& print_instance : ltp.object()->instances()){
+ this->set_origin(unscale(print_instance.shift));
+ for (const LayerRegion* lr : ltp.object_layer->regions()) {
+ if (!lr->milling.empty()) {
+ //EXTRUDE MOVES
+ gcode += "; extrude lr->milling\n";
+ gcode += this->extrude_entity(lr->milling, "; milling post-process");
+ }
+ }
+ }
+ }
+ }
+
+ //switch to extruder
+ m_placeholder_parser.set("current_extruder", milling_extruder_id);
+ // Append the filament start G-code.
+ const std::string& end_mill_gcode = m_config.milling_toolchange_end_gcode.get_at(0);
+ if (!end_mill_gcode.empty()) {
+ DynamicConfig config;
+ config.set_key_value("previous_extruder", new ConfigOptionInt((int)milling_extruder_id));
+ config.set_key_value("next_extruder", new ConfigOptionInt((int)current_extruder_filament));
+ config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
+ config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
+ // Process the end_mill_gcode for the new filament.
+ gcode += this->placeholder_parser_process("milling_toolchange_start_gcode", end_mill_gcode, current_extruder_filament, &config);
+ check_add_eol(gcode);
+ }
+ gcode += "; will go back to normal extruder\n";
+ //TODO: change wipetower code to add an other filament change per layer.
+ gcode += (layer_tools.has_wipe_tower && m_wipe_tower) ?
+ m_wipe_tower->tool_change(*this, current_extruder_filament, current_extruder_filament == layer_tools.extruders.back()) :
+ this->set_extruder(current_extruder_filament, print_z);
+ }
+ }
+
+
// Apply cooling logic; this may alter speeds.
if (m_cooling_buffer)
gcode = m_cooling_buffer->process_layer(gcode, layer.id());
@@ -2487,10 +2587,10 @@ void GCode::append_full_config(const Print &print, std::string &str)
str += "; " + key + " = " + cfg.opt_serialize(key) + "\n";
}
-void GCode::set_extruders(const std::vector<unsigned int> &extruder_ids)
+void GCode::set_extruders(const std::vector<uint16_t>& extruder_ids)
{
m_writer.set_extruders(extruder_ids);
-
+
// enable wipe path generation if any extruder has wipe enabled
m_wipe.enable = false;
for (auto id : extruder_ids)
@@ -2533,7 +2633,7 @@ std::string GCode::change_layer(coordf_t print_z)
// Increment a progress bar indicator.
gcode += m_writer.update_progress(++ m_layer_index, m_layer_count);
coordf_t z = print_z + m_config.z_offset.value; // in unscaled coordinates
- if (EXTRUDER_CONFIG(retract_layer_change) && m_writer.will_move_z(z))
+ if (BOOL_EXTRUDER_CONFIG(retract_layer_change) && m_writer.will_move_z(z))
gcode += this->retract();
{
@@ -2756,7 +2856,7 @@ std::string GCode::extrude_loop_vase(const ExtrusionLoop &original_loop, const s
// if polyline was shorter than the clipping distance we'd get a null polyline, so
// we discard it in that case
double clip_length = m_enable_loop_clipping ?
- scale_(EXTRUDER_CONFIG(nozzle_diameter)) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER :
+ scale_(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter,0)) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER :
0;
// get paths
@@ -2776,7 +2876,7 @@ std::string GCode::extrude_loop_vase(const ExtrusionLoop &original_loop, const s
}
//all in unscaled coordinates (hence why it's coordf_t and not coord_t)
- const coordf_t min_height = EXTRUDER_CONFIG(min_layer_height);
+ const coordf_t min_height = EXTRUDER_CONFIG_WITH_DEFAULT(min_layer_height, this->m_layer->height);
const coordf_t bot_init_z = - this->m_layer->height;
//const coordf_t bot_last_z = bot_init_z + this->m_layer->height - EXTRUDER_CONFIG(min_layer_height);
const coordf_t init_z = bot_init_z + min_height;
@@ -2807,7 +2907,7 @@ std::string GCode::extrude_loop_vase(const ExtrusionLoop &original_loop, const s
Vec2d p1 = paths.front().polyline.points.front().cast<double>();
Vec2d p2 = paths.front().polyline.points[1].cast<double>();
Vec2d v = p2 - p1;
- double nd = scale_(EXTRUDER_CONFIG(nozzle_diameter));
+ double nd = scale_(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, paths.front().width));
double l2 = v.squaredNorm();
// Shift by no more than a nozzle diameter.
//FIXME Hiding the seams will not work nicely for very densely discretized contours!
@@ -2856,7 +2956,7 @@ std::string GCode::extrude_loop_vase(const ExtrusionLoop &original_loop, const s
// calculate extrusion length per distance unit
double e_per_mm_per_height = (path->mm3_per_mm / this->m_layer->height)
- * m_writer.extruder()->e_per_mm3()
+ * m_writer.tool()->e_per_mm3()
* this->config().print_extrusion_multiplier.get_abs_value(1);
if (m_writer.extrusion_axis().empty()) e_per_mm_per_height = 0;
{
@@ -2864,7 +2964,7 @@ std::string GCode::extrude_loop_vase(const ExtrusionLoop &original_loop, const s
for (const Line &line : path->polyline.lines()) {
const coordf_t line_length = line.length() * SCALING_FACTOR;
//don't go (much) more than a nozzle_size without a refresh of the z & extrusion rate
- const int nb_sections = std::max(1,int(line_length / EXTRUDER_CONFIG(nozzle_diameter)));
+ const int nb_sections = std::max(1,int(line_length / EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, paths.front().width)));
const coordf_t height_increment = height_per_length * line_length / nb_sections;
Vec3d last_point{ this->point_to_gcode(line.a).x(), this->point_to_gcode(line.a).y(), current_z };
const Vec3d pos_increment{ (this->point_to_gcode(line.b).x() - last_point.x()) / nb_sections,
@@ -2955,7 +3055,7 @@ std::string GCode::extrude_loop_vase(const ExtrusionLoop &original_loop, const s
Vec2d p1 = paths.front().polyline.points.front().cast<double>();
Vec2d p2 = paths.front().polyline.points[1].cast<double>();
Vec2d v = p2 - p1;
- double nd = scale_(EXTRUDER_CONFIG(nozzle_diameter));
+ double nd = scale_(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, paths.front().width));
double l2 = v.squaredNorm();
// Shift by no more than a nozzle diameter.
//FIXME Hiding the seams will not work nicely for very densely discretized contours!
@@ -2971,6 +3071,8 @@ std::string GCode::extrude_loop_vase(const ExtrusionLoop &original_loop, const s
void GCode::split_at_seam_pos(ExtrusionLoop &loop, std::unique_ptr<EdgeGrid::Grid> *lower_layer_edge_grid)
{
+ if (loop.paths.empty())
+ return;
SeamPosition seam_position = m_config.seam_position;
if (loop.loop_role() == elrSkirt)
@@ -2983,7 +3085,7 @@ void GCode::split_at_seam_pos(ExtrusionLoop &loop, std::unique_ptr<EdgeGrid::Gri
loop.split_at(last_pos, false);
} else if (seam_position == spNearest || seam_position == spAligned || seam_position == spRear || seam_position == spHidden) {
Polygon polygon = loop.polygon();
- const coordf_t nozzle_dmr = EXTRUDER_CONFIG(nozzle_diameter);
+ const coordf_t nozzle_dmr = EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, loop.paths.front().width);
const coord_t nozzle_r = coord_t(scale_(0.5 * nozzle_dmr) + 0.5);
// Retrieve the last start position for this object.
@@ -3177,7 +3279,7 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s
//but not for the first layer
&& this->m_layer->id() > 0
//exclude if min_layer_height * 2 > layer_height (increase from 2 to 3 because it's working but uses in-between)
- && this->m_layer->height >= EXTRUDER_CONFIG(min_layer_height) * 2 - EPSILON
+ && this->m_layer->height >= EXTRUDER_CONFIG_WITH_DEFAULT(min_layer_height, 0) * 2 - EPSILON
) {
return extrude_loop_vase(original_loop, description, speed, lower_layer_edge_grid);
}
@@ -3224,7 +3326,7 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s
// if polyline was shorter than the clipping distance we'd get a null polyline, so
// we discard it in that case
double clip_length = m_enable_loop_clipping ?
- scale_(EXTRUDER_CONFIG(nozzle_diameter)) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER :
+ scale_(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter,0)) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER :
0;
// get paths
@@ -3260,8 +3362,8 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s
Point next_point = paths.front().polyline.points[1]; // second point
//extra wipe before the little move.
- if (EXTRUDER_CONFIG(wipe_extra_perimeter) > 0) {
- coord_t wipe_dist = scale_(EXTRUDER_CONFIG(wipe_extra_perimeter));
+ if (EXTRUDER_CONFIG_WITH_DEFAULT(wipe_extra_perimeter, 0) > 0) {
+ coord_t wipe_dist = scale_(EXTRUDER_CONFIG_WITH_DEFAULT(wipe_extra_perimeter,0));
ExtrusionPaths paths_wipe;
for (int i = 0; i < paths.size(); i++) {
ExtrusionPath& path = paths[i];
@@ -3319,7 +3421,7 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s
Vec2d current_pos = current_point.cast<double>();
Vec2d next_pos = next_point.cast<double>();
Vec2d vec_dist = next_pos - current_pos;
- double nd = scale_(EXTRUDER_CONFIG(nozzle_diameter));
+ double nd = scale_(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter,0));
double l2 = vec_dist.squaredNorm();
// Shift by no more than a nozzle diameter.
//FIXME Hiding the seams will not work nicely for very densely discretized contours!
@@ -3359,7 +3461,7 @@ std::string GCode::extrude_multi_path3D(const ExtrusionMultiPath3D &multipath3D,
// calculate extrusion length per distance unit
double e_per_mm = path.mm3_per_mm
- * m_writer.extruder()->e_per_mm3()
+ * m_writer.tool()->e_per_mm3()
* this->config().print_extrusion_multiplier.get_abs_value(1);
if (m_writer.extrusion_axis().empty()) e_per_mm = 0;
double path_length = 0.;
@@ -3428,7 +3530,7 @@ std::string GCode::extrude_path_3D(const ExtrusionPath3D &path, const std::strin
// calculate extrusion length per distance unit
double e_per_mm = path.mm3_per_mm
- * m_writer.extruder()->e_per_mm3()
+ * m_writer.tool()->e_per_mm3()
* this->config().print_extrusion_multiplier.get_abs_value(1);
if (m_writer.extrusion_axis().empty()) e_per_mm = 0;
double path_length = 0.;
@@ -3589,7 +3691,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string &descri
// calculate extrusion length per distance unit
double e_per_mm = path.mm3_per_mm
- * m_writer.extruder()->e_per_mm3()
+ * m_writer.tool()->e_per_mm3()
* this->config().print_extrusion_multiplier.get_abs_value(1);
if (this->m_layer_index <= 0) e_per_mm *= this->config().first_layer_flow_ratio.get_abs_value(1);
if (m_writer.extrusion_axis().empty()) e_per_mm = 0;
@@ -3724,6 +3826,8 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string
speed = m_config.get_abs_value("gap_fill_speed");
} else if (path.role() == erNone) {
speed = m_config.get_abs_value("travel_speed");
+ } else if (path.role() == erMilling) {
+ speed = m_config.get_abs_value("milling_speed");
} else {
throw std::invalid_argument("Invalid speed");
}
@@ -3742,11 +3846,11 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string
m_config.max_volumetric_speed.value / path.mm3_per_mm
);
}
- if (EXTRUDER_CONFIG(filament_max_volumetric_speed) > 0) {
+ if (EXTRUDER_CONFIG_WITH_DEFAULT(filament_max_volumetric_speed,0) > 0) {
// cap speed with max_volumetric_speed anyway (even if user is not using autospeed)
speed = std::min(
speed,
- EXTRUDER_CONFIG(filament_max_volumetric_speed) / path.mm3_per_mm
+ EXTRUDER_CONFIG_WITH_DEFAULT(filament_max_volumetric_speed, speed) / path.mm3_per_mm
);
}
double F = speed * 60; // convert mm/sec to mm/min
@@ -3758,7 +3862,7 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index + 1));
config.set_key_value("layer_z", new ConfigOptionFloat(m_config.z_offset.value));
gcode += this->placeholder_parser_process("feature_gcode",
- m_config.feature_gcode.value, m_writer.extruder()->id(), &config)
+ m_config.feature_gcode.value, m_writer.tool()->id(), &config)
+ "\n";
}
if (m_enable_extrusion_role_markers) {
@@ -3891,7 +3995,7 @@ std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string
bool GCode::needs_retraction(const Polyline &travel, ExtrusionRole role)
{
- if (travel.length() < scale_(EXTRUDER_CONFIG(retract_before_travel))) {
+ if (travel.length() < scale_(EXTRUDER_CONFIG_WITH_DEFAULT(retract_before_travel, 0))) {
// skip retraction if the move is shorter than the configured threshold
return false;
}
@@ -3921,7 +4025,7 @@ std::string GCode::retract(bool toolchange)
{
std::string gcode;
- if (m_writer.extruder() == nullptr)
+ if (m_writer.tool() == nullptr)
return gcode;
// We need to reset e before any extrusion or wipe to allow the reset to happen at the real
@@ -3929,7 +4033,7 @@ std::string GCode::retract(bool toolchange)
gcode += m_writer.reset_e();
// wipe (if it's enabled for this extruder and we have a stored wipe path)
- if (EXTRUDER_CONFIG(wipe) && m_wipe.has_path()) {
+ if (BOOL_EXTRUDER_CONFIG(wipe) && m_wipe.has_path()) {
gcode += toolchange ? m_writer.retract_for_toolchange(true) : m_writer.retract(true);
gcode += m_wipe.wipe(*this, toolchange);
}
@@ -3939,8 +4043,14 @@ std::string GCode::retract(bool toolchange)
methods even if we performed wipe, since this will ensure the entire retraction
length is honored in case wipe path was too short. */
gcode += toolchange ? m_writer.retract_for_toolchange() : m_writer.retract();
- if (toolchange || !this->m_config.retract_lift_not_last_layer.get_at(m_writer.extruder()->id()) || !(this->m_last_extrusion_role == ExtrusionRole::erTopSolidInfill))
- if (m_writer.extruder()->retract_length() > 0 || m_config.use_firmware_retraction)
+ if (toolchange
+ || !(BOOL_EXTRUDER_CONFIG(retract_lift_not_last_layer) && (this->m_last_extrusion_role == ExtrusionRole::erTopSolidInfill ))
+ || !m_writer.tool_is_extruder()
+ )
+ if (m_writer.tool()->retract_length() > 0
+ || m_config.use_firmware_retraction
+ || (!m_writer.tool_is_extruder() && m_writer.tool()->retract_lift() != 0)
+ )
gcode += m_writer.lift();
return gcode;
@@ -3978,14 +4088,14 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
// Always reset the extrusion path, even if the tool change retract is set to zero.
m_wipe.reset_path();
- if (m_writer.extruder() != nullptr) {
+ if (m_writer.tool() != nullptr) {
// Process the custom end_filament_gcode. set_extruder() is only called if there is no wipe tower
// so it should not be injected twice.
- unsigned int old_extruder_id = m_writer.extruder()->id();
+ unsigned int old_extruder_id = m_writer.tool()->id();
const std::string &end_filament_gcode = m_config.end_filament_gcode.get_at(old_extruder_id);
if (! end_filament_gcode.empty()) {
DynamicConfig config;
- config.set_key_value("previous_extruder", new ConfigOptionInt((int)(m_writer.extruder() != nullptr ? m_writer.extruder()->id() : -1)));
+ config.set_key_value("previous_extruder", new ConfigOptionInt((int)(m_writer.tool() != nullptr ? m_writer.tool()->id() : -1)));
config.set_key_value("next_extruder", new ConfigOptionInt((int)extruder_id));
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
@@ -3997,7 +4107,7 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
// If ooze prevention is enabled, park current extruder in the nearest
// standby point and set it to the standby temperature.
- if (m_ooze_prevention.enable && m_writer.extruder() != nullptr)
+ if (m_ooze_prevention.enable && m_writer.tool() != nullptr)
gcode += m_ooze_prevention.pre_toolchange(*this);
const std::string& toolchange_gcode = m_config.toolchange_gcode.value;
@@ -4006,7 +4116,7 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
// Process the custom toolchange_gcode. If it is empty, insert just a Tn command.
if (!toolchange_gcode.empty()) {
DynamicConfig config;
- config.set_key_value("previous_extruder", new ConfigOptionInt((int)(m_writer.extruder() != nullptr ? m_writer.extruder()->id() : -1 )));
+ config.set_key_value("previous_extruder", new ConfigOptionInt((int)(m_writer.tool() != nullptr ? m_writer.tool()->id() : -1 )));
config.set_key_value("next_extruder", new ConfigOptionInt((int)extruder_id));
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
@@ -4037,7 +4147,7 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
const std::string &start_filament_gcode = m_config.start_filament_gcode.get_at(extruder_id);
if (! start_filament_gcode.empty()) {
DynamicConfig config;
- config.set_key_value("previous_extruder", new ConfigOptionInt((int)(m_writer.extruder() != nullptr ? m_writer.extruder()->id() : -1)));
+ config.set_key_value("previous_extruder", new ConfigOptionInt((int)(m_writer.tool() != nullptr ? m_writer.tool()->id() : -1)));
config.set_key_value("next_extruder", new ConfigOptionInt((int)extruder_id));
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
@@ -4055,13 +4165,13 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
// convert a model-space scaled point into G-code coordinates
Vec2d GCode::point_to_gcode(const Point &point) const
{
- Vec2d extruder_offset = EXTRUDER_CONFIG(extruder_offset);
+ Vec2d extruder_offset = EXTRUDER_CONFIG_WITH_DEFAULT(extruder_offset, Vec2d(0, 0)); //FIXME : mill ofsset
return unscale(point) + m_origin - extruder_offset;
}
// convert a model-space scaled point into G-code coordinates
Vec3d GCode::point_to_gcode(const Point &point, const coord_t z_offset) const {
- Vec2d extruder_offset = EXTRUDER_CONFIG(extruder_offset);
+ Vec2d extruder_offset = EXTRUDER_CONFIG_WITH_DEFAULT(extruder_offset, Vec2d(0, 0)); //FIXME : mill ofsset
Vec3d ret_vec(unscale_(point.x()) + m_origin.x() - extruder_offset.x(),
unscale_(point.y()) + m_origin.y() - extruder_offset.y(),
unscale_(z_offset));
@@ -4071,7 +4181,7 @@ Vec3d GCode::point_to_gcode(const Point &point, const coord_t z_offset) const {
// convert a model-space scaled point into G-code coordinates
Point GCode::gcode_to_point(const Vec2d &point) const
{
- Vec2d extruder_offset = EXTRUDER_CONFIG(extruder_offset);
+ Vec2d extruder_offset = EXTRUDER_CONFIG_WITH_DEFAULT(extruder_offset, Vec2d(0, 0)); //FIXME : mill ofsset
return Point(
scale_(point(0) - m_origin(0) + extruder_offset(0)),
scale_(point(1) - m_origin(1) + extruder_offset(1)));
@@ -4205,6 +4315,8 @@ GCode::extrusion_role_to_string_for_parser(const ExtrusionRole & role) {
return "SupportMaterialInterface";
case erWipeTower:
return "WipeTower";
+ case erMilling:
+ return "Mill";
case erCustom:
case erMixed:
case erCount: