diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index 984ebc92fc..e814be9f5c 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -165,6 +165,7 @@ sub thread_cleanup { no warnings 'redefine'; *Slic3r::Config::DESTROY = sub {}; *Slic3r::Config::Full::DESTROY = sub {}; + *Slic3r::Config::GCode::DESTROY = sub {}; *Slic3r::Config::Print::DESTROY = sub {}; *Slic3r::Config::PrintObject::DESTROY = sub {}; *Slic3r::Config::PrintRegion::DESTROY = sub {}; diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm index 7f36b5f504..2d39337e3c 100644 --- a/lib/Slic3r/GCode.pm +++ b/lib/Slic3r/GCode.pm @@ -71,6 +71,20 @@ sub init_external_mp { $self->_external_mp(Slic3r::MotionPlanner->new($islands)); } +sub preamble { + my ($self) = @_; + + my $gcode = $self->writer->preamble; + + # Perform a *silent* move to z_offset: we need this to initialize the Z + # position of our writer object so that any initial lift taking place + # before the first layer change will raise the extruder from the correct + # initial Z instead of 0. + $self->writer->travel_to_z($self->config->z_offset, ''); + + return $gcode; +} + sub change_layer { my ($self, $layer) = @_; diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index b50cfbaf63..8d464ac247 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -546,7 +546,7 @@ sub write_gcode { $print_first_layer_temperature->(1); # set other general things - print $fh $gcodegen->writer->preamble; + print $fh $gcodegen->preamble; # initialize a motion planner for object-to-object travel moves if ($self->config->avoid_crossing_perimeters) { diff --git a/t/gcode.t b/t/gcode.t index 5738334284..17393e7cf0 100644 --- a/t/gcode.t +++ b/t/gcode.t @@ -1,4 +1,4 @@ -use Test::More tests => 16; +use Test::More tests => 19; use strict; use warnings; @@ -41,6 +41,34 @@ use Slic3r::Test; ok !defined (first { abs($_ - $config->retract_speed->[0]*60) < 5 } @retract_speeds), 'wipe moves don\'t retract faster than configured speed'; } +{ + my $config = Slic3r::Config->new_from_defaults; + $config->set('z_offset', 5); + $config->set('start_gcode', ''); + + my $test = sub { + my ($comment) = @_; + my $print = Slic3r::Test::init_print('20mm_cube', config => $config); + my $moves_below_z_offset = 0; + Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub { + my ($self, $cmd, $args, $info) = @_; + + if ($info->{travel} && exists $args->{Z}) { + $moves_below_z_offset++ if $args->{Z} < $config->z_offset; + } + }); + is $moves_below_z_offset, 0, "no Z moves below Z offset ($comment)"; + }; + + $test->("no lift"); + + $config->set('retract_lift', [3]); + $test->("lift < z_offset"); + + $config->set('retract_lift', [6]); + $test->("lift > z_offset"); +} + { # This tests the following behavior: # - complete objects does not crash