diff --git a/lib/Slic3r/Model.pm b/lib/Slic3r/Model.pm index 2d7436c8b..d9b5ef463 100644 --- a/lib/Slic3r/Model.pm +++ b/lib/Slic3r/Model.pm @@ -166,7 +166,8 @@ sub duplicate { # note that this will leave the object count unaltered foreach my $object (@{$self->objects}) { - foreach my $instance (@{$object->instances}) { + my @instances = @{$object->instances}; # store separately to avoid recursion from add_instance() below + foreach my $instance (@instances) { foreach my $pos (@positions) { ### $object->add_instance($instance->clone); if we had clone() $object->add_instance( diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index 2114ead08..458dd2f77 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -191,6 +191,7 @@ sub validate { # now we need that no instance of $convex_hull does not intersect any of the previously checked object instances for my $copy (@{$object->_shifted_copies}) { my $p = $convex_hull->clone; + $p->translate(@$copy); if (@{ intersection(\@a, [$p]) }) { die "Some objects are too close; your extruder will collide with them.\n"; @@ -837,14 +838,13 @@ sub write_gcode { # do all objects for each layer if ($Slic3r::Config->complete_objects) { - # print objects from the smallest to the tallest to avoid collisions # when moving onto next object starting point my @obj_idx = sort { $self->objects->[$a]->size->[Z] <=> $self->objects->[$b]->size->[Z] } 0..$#{$self->objects}; my $finished_objects = 0; for my $obj_idx (@obj_idx) { - for my $copy (@{ $self->objects->[$obj_idx]->copies }) { + for my $copy (@{ $self->objects->[$obj_idx]->_shifted_copies }) { # move to the origin position for the copy we're going to print. # this happens before Z goes down to layer 0 again, so that # no collision happens hopefully. @@ -929,8 +929,7 @@ sub write_gcode { # append full config print $fh "\n"; foreach my $opt_key (sort @{$self->config->get_keys}) { - next if $Slic3r::Config::Options->{$opt_key}{shortcut}; - next if $Slic3r::Config::Options->{$opt_key}{gui_only}; + next if @{$Slic3r::Config::Options->{$opt_key}{shortcut}}; printf $fh "; %s = %s\n", $opt_key, $self->config->serialize($opt_key); } } diff --git a/lib/Slic3r/Test.pm b/lib/Slic3r/Test.pm index f4f83fed4..3a3944318 100644 --- a/lib/Slic3r/Test.pm +++ b/lib/Slic3r/Test.pm @@ -90,7 +90,7 @@ sub model { my $object = $model->add_object; $object->add_volume(mesh => $mesh); $object->add_instance( - offset => Slic3r::Point->new(0,0), + offset => [0,0], rotation => $params{rotation} // 0, ); return $model; @@ -108,6 +108,9 @@ sub init_print { $model_name = [$model_name] if ref($model_name) ne 'ARRAY'; for my $model (map model($_, %params), @$model_name) { die "Unknown model in test" if !defined $model; + if (defined $params{duplicate} && $params{duplicate} > 1) { + $model->duplicate($params{duplicate} // 1, $config->min_object_distance); + } $model->arrange_objects($config->min_object_distance); $model->center_instances_around_point($config->print_center); $print->add_model_object($_) for @{$model->objects}; diff --git a/t/gcode.t b/t/gcode.t index 17f4ed824..c8db2f816 100644 --- a/t/gcode.t +++ b/t/gcode.t @@ -48,13 +48,13 @@ use Slic3r::Test; # - no hard-coded "E" are generated # - Z moves are correctly generated for both objects my $config = Slic3r::Config->new_from_defaults; + $config->set('gcode_comments', 1); $config->set('complete_objects', 1); - $config->set('duplicate', 2); $config->set('extrusion_axis', 'A'); $config->set('start_gcode', ''); # prevent any default extra Z move $config->set('layer_height', 0.4); $config->set('first_layer_height', 0.4); - my $print = Slic3r::Test::init_print('20mm_cube', config => $config); + my $print = Slic3r::Test::init_print('20mm_cube', config => $config, duplicate => 2); ok my $gcode = Slic3r::Test::gcode($print), "complete_objects"; my @z_moves = (); Slic3r::GCode::Reader->new->parse($gcode, sub { diff --git a/t/retraction.t b/t/retraction.t index 8221c4deb..636359149 100644 --- a/t/retraction.t +++ b/t/retraction.t @@ -11,12 +11,13 @@ use Slic3r; use Slic3r::Test qw(_eq); my $config = Slic3r::Config->new_from_defaults; +my $duplicate = 1; my $test = sub { my ($conf) = @_; $conf ||= $config; - my $print = Slic3r::Test::init_print('20mm_cube', config => $conf); + my $print = Slic3r::Test::init_print('20mm_cube', config => $conf, duplicate => $duplicate); my $tool = 0; my @toolchange_count = (); # track first usages so that we don't expect retract_length_toolchange when extruders are used for the first time @@ -115,13 +116,13 @@ my $retract_tests = sub { $retract_tests->(''); -$config->set('duplicate', 2); +$duplicate = 2; $retract_tests->(' (duplicate)'); $config->set('g0', 1); $retract_tests->(' (G0 and duplicate)'); -$config->set('duplicate', 1); +$duplicate = 1; $config->set('g0', 0); $config->set('infill_extruder', 2); $config->set('skirts', 4);