diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm index 96a3170fd..db5ce284c 100644 --- a/lib/Slic3r/GCode.pm +++ b/lib/Slic3r/GCode.pm @@ -334,90 +334,4 @@ sub travel_to { return $gcode; } -sub set_extruder { - my ($self, $extruder_id) = @_; - - $self->placeholder_parser->set('current_extruder', $extruder_id); - return "" if !$self->writer->need_toolchange($extruder_id); - - # if we are running a single-extruder setup, just set the extruder and return nothing - if (!$self->writer->multiple_extruders) { - return $self->writer->toolchange($extruder_id); - } - - # prepend retraction on the current extruder - my $gcode = $self->retract(1); - - # append custom toolchange G-code - if (defined $self->writer->extruder && $self->config->toolchange_gcode) { - my $pp = $self->placeholder_parser->clone; - $pp->set('previous_extruder' => $self->writer->extruder->id); - $pp->set('next_extruder' => $extruder_id); - $gcode .= sprintf "%s\n", $pp->process($self->config->toolchange_gcode); - } - - # if ooze prevention is enabled, park current extruder in the nearest - # standby point and set it to the standby temperature - $gcode .= $self->ooze_prevention->pre_toolchange($self) - if $self->ooze_prevention->enable && defined $self->writer->extruder; - - # append the toolchange command - $gcode .= $self->writer->toolchange($extruder_id); - - # set the new extruder to the operating temperature - $gcode .= $self->ooze_prevention->post_toolchange($self) - if $self->ooze_prevention->enable; - - return $gcode; -} - -package Slic3r::GCode::OozePrevention; -use strict; -use warnings; - -use Slic3r::Geometry qw(scale); - -sub pre_toolchange { - my ($self, $gcodegen) = @_; - - my $gcode = ""; - - # move to the nearest standby point - if (@{$self->standby_points}) { - # get current position in print coordinates - my $pos = Slic3r::Point->new_scale(@{$gcodegen->writer->get_position}[0,1]); - - my $standby_point = Slic3r::Pointf->new_unscale(@{$pos->nearest_point($self->standby_points)}); - # We don't call $gcodegen->travel_to() because we don't need retraction (it was already - # triggered by the caller) nor avoid_crossing_perimeters and also because the coordinates - # of the destination point must not be transformed by origin nor current extruder offset. - $gcode .= $gcodegen->writer->travel_to_xy($standby_point, 'move to standby position'); - } - - if ($gcodegen->config->standby_temperature_delta != 0) { - my $temp = $gcodegen->has_layer && $gcodegen->layer->id == 0 - ? $gcodegen->config->get_at('first_layer_temperature', $gcodegen->writer->extruder->id) - : $gcodegen->config->get_at('temperature', $gcodegen->writer->extruder->id); - # we assume that heating is always slower than cooling, so no need to block - $gcode .= $gcodegen->writer->set_temperature($temp + $gcodegen->config->standby_temperature_delta, 0); - } - - return $gcode; -} - -sub post_toolchange { - my ($self, $gcodegen) = @_; - - my $gcode = ""; - - if ($gcodegen->config->standby_temperature_delta != 0) { - my $temp = $gcodegen->has_layer && $gcodegen->layer->id == 0 - ? $gcodegen->config->get_at('first_layer_temperature', $gcodegen->writer->extruder->id) - : $gcodegen->config->get_at('temperature', $gcodegen->writer->extruder->id); - $gcode .= $gcodegen->writer->set_temperature($temp, 1); - } - - return $gcode; -} - 1; diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index abeba12e9..fe6e3089e 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -72,6 +72,57 @@ OozePrevention::OozePrevention() { } +std::string +OozePrevention::pre_toolchange(GCode &gcodegen) +{ + std::string gcode; + + // move to the nearest standby point + if (!this->standby_points.empty()) { + // get current position in print coordinates + Pointf3 writer_pos = gcodegen.writer.get_position(); + Point pos = Point::new_scale(writer_pos.x, writer_pos.y); + + // find standby point + Point standby_point; + pos.nearest_point(this->standby_points, &standby_point); + + /* We don't call gcodegen.travel_to() because we don't need retraction (it was already + triggered by the caller) nor avoid_crossing_perimeters and also because the coordinates + of the destination point must not be transformed by origin nor current extruder offset. */ + gcode += gcodegen.writer.travel_to_xy(Pointf::new_unscale(standby_point), + "move to standby position"); + } + + if (gcodegen.config.standby_temperature_delta.value != 0) { + // 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); + } + + return gcode; +} + +std::string +OozePrevention::post_toolchange(GCode &gcodegen) +{ + std::string gcode; + + if (gcodegen.config.standby_temperature_delta.value != 0) { + gcode += gcodegen.writer.set_temperature(this->_get_temp(gcodegen), true); + } + + return gcode; +} + +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); +} + #ifdef SLIC3RXS REGISTER_CLASS(OozePrevention, "GCode::OozePrevention"); #endif @@ -289,6 +340,44 @@ GCode::unretract() return gcode; } +std::string +GCode::set_extruder(unsigned int extruder_id) +{ + this->placeholder_parser->set("current_extruder", extruder_id); + if (!this->writer.need_toolchange(extruder_id)) + return ""; + + // if we are running a single-extruder setup, just set the extruder and return nothing + if (!this->writer.multiple_extruders) { + return this->writer.toolchange(extruder_id); + } + + // prepend retraction on the current extruder + std::string gcode = this->retract(true); + + // append custom toolchange G-code + if (this->writer.extruder() != NULL && !this->config.toolchange_gcode.value.empty()) { + PlaceholderParser pp = *this->placeholder_parser; + pp.set("previous_extruder", this->writer.extruder()->id); + pp.set("next_extruder", extruder_id); + gcode += pp.process(this->config.toolchange_gcode.value) + '\n'; + } + + // if ooze prevention is enabled, park current extruder in the nearest + // standby point and set it to the standby temperature + if (this->ooze_prevention.enable && this->writer.extruder() != NULL) + gcode += this->ooze_prevention.pre_toolchange(*this); + + // append the toolchange command + gcode += this->writer.toolchange(extruder_id); + + // set the new extruder to the operating temperature + if (this->ooze_prevention.enable) + gcode += this->ooze_prevention.post_toolchange(*this); + + return gcode; +} + // convert a model-space scaled point into G-code coordinates Pointf GCode::point_to_gcode(const Point &point) diff --git a/xs/src/libslic3r/GCode.hpp b/xs/src/libslic3r/GCode.hpp index 846b82299..ee6f78c57 100644 --- a/xs/src/libslic3r/GCode.hpp +++ b/xs/src/libslic3r/GCode.hpp @@ -44,6 +44,11 @@ class OozePrevention { Points standby_points; OozePrevention(); + std::string pre_toolchange(GCode &gcodegen); + std::string post_toolchange(GCode &gcodegen); + + private: + int _get_temp(GCode &gcodegen); }; class Wipe { @@ -90,6 +95,7 @@ class GCode { bool needs_retraction(const Polyline &travel, ExtrusionRole role = erNone); std::string retract(bool toolchange = false); std::string unretract(); + std::string set_extruder(unsigned int extruder_id); Pointf point_to_gcode(const Point &point); private: diff --git a/xs/xsp/GCode.xsp b/xs/xsp/GCode.xsp index 5095fcfab..3465c3c2c 100644 --- a/xs/xsp/GCode.xsp +++ b/xs/xsp/GCode.xsp @@ -43,6 +43,11 @@ %code{% RETVAL = THIS->standby_points; %}; void set_standby_points(Points points) %code{% THIS->standby_points = points; %}; + + std::string pre_toolchange(GCode* gcodegen) + %code{% RETVAL = THIS->pre_toolchange(*gcodegen); %}; + std::string post_toolchange(GCode* gcodegen) + %code{% RETVAL = THIS->post_toolchange(*gcodegen); %}; }; %name{Slic3r::GCode::Wipe} class Wipe { @@ -156,6 +161,7 @@ %code{% RETVAL = THIS->needs_retraction(*travel, role); %}; std::string retract(bool toolchange = false); std::string unretract(); + std::string set_extruder(unsigned int extruder_id); Clone point_to_gcode(Point* point) %code{% RETVAL = THIS->point_to_gcode(*point); %}; };