1
use Test::More tests => 13;
7
use lib "$FindBin::Bin/../lib";
10
use List::Util qw(first);
12
use Slic3r::Geometry qw(scale convex_hull);
13
use Slic3r::Geometry::Clipper qw(offset);
17
my $config = Slic3r::Config->new_from_defaults;
18
$config->set('raft_layers', 2);
19
$config->set('infill_extruder', 2);
20
$config->set('support_material_extruder', 3);
21
$config->set('ooze_prevention', 1);
22
$config->set('extruder_offset', [ [0,0], [20,0], [0,20] ]);
23
$config->set('temperature', [200, 180, 170]);
24
$config->set('first_layer_temperature', [206, 186, 166]);
25
$config->set('toolchange_gcode', ';toolchange'); # test that it doesn't crash when this is supplied
27
my $print = Slic3r::Test::init_print('20mm_cube', config => $config);
30
my @tool_temp = (0,0,0);
31
my @toolchange_points = ();
32
my @extrusion_points = ();
33
Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub {
34
my ($self, $cmd, $args, $info) = @_;
36
if ($cmd =~ /^T(\d+)/) {
38
my $expected_temp = $self->Z == ($config->get_value('first_layer_height') + $config->z_offset)
39
? $config->first_layer_temperature->[$tool]
40
: $config->temperature->[$tool];
41
die 'standby temperature was not set before toolchange'
42
if $tool_temp[$tool] != $expected_temp + $config->standby_temperature_delta;
44
# ignore initial toolchange
45
push @toolchange_points, Slic3r::Point->new_scale($self->X, $self->Y);
48
} elsif ($cmd eq 'M104' || $cmd eq 'M109') {
49
my $t = $args->{T} // $tool;
50
if ($tool_temp[$t] == 0) {
51
fail 'initial temperature is not equal to first layer temperature + standby delta'
52
unless $args->{S} == $config->first_layer_temperature->[$t] + $config->standby_temperature_delta;
54
$tool_temp[$t] = $args->{S};
55
} elsif ($cmd eq 'G1' && $info->{extruding} && $info->{dist_XY} > 0) {
56
push @extrusion_points, my $point = Slic3r::Point->new_scale($args->{X}, $args->{Y});
57
$point->translate(map scale($_), @{ $config->extruder_offset->[$tool] });
60
my $convex_hull = convex_hull(\@extrusion_points);
61
ok !(defined first { $convex_hull->contains_point($_) } @toolchange_points), 'all toolchanges happen outside skirt';
63
# offset the skirt by the maximum displacement between extruders plus a safety extra margin
64
my $delta = scale(20 * sqrt(2) + 1);
65
my $outer_convex_hull = offset([$convex_hull], +$delta)->[0];
66
ok !(defined first { !$outer_convex_hull->contains_point($_) } @toolchange_points), 'all toolchanges happen within expected area';
70
my $config = Slic3r::Config->new_from_defaults;
71
$config->set('support_material_extruder', 3);
73
my $print = Slic3r::Test::init_print('20mm_cube', config => $config);
74
ok Slic3r::Test::gcode($print), 'no errors when using non-consecutive extruders';
78
my $config = Slic3r::Config->new;
79
$config->set('extruder', 2);
81
my $print = Slic3r::Test::init_print('20mm_cube', config => $config);
82
like Slic3r::Test::gcode($print), qr/ T1/, 'extruder shortcut';
86
my $config = Slic3r::Config->new;
87
$config->set('perimeter_extruder', 2);
88
$config->set('infill_extruder', 2);
89
$config->set('support_material_extruder', 2);
90
$config->set('support_material_interface_extruder', 2);
92
my $print = Slic3r::Test::init_print('20mm_cube', config => $config);
93
ok Slic3r::Test::gcode($print), 'no errors when using multiple skirts with a single, non-zero, extruder';
97
my $model = stacked_cubes();
98
my $lower_config = $model->get_material('lower')->config;
99
my $upper_config = $model->get_material('upper')->config;
101
$lower_config->set('extruder', 1);
102
$lower_config->set('bottom_solid_layers', 0);
103
$lower_config->set('top_solid_layers', 1);
104
$upper_config->set('extruder', 2);
105
$upper_config->set('bottom_solid_layers', 1);
106
$upper_config->set('top_solid_layers', 0);
107
my $config = Slic3r::Config->new_from_defaults;
108
$config->set('fill_density', 0);
109
$config->set('solid_infill_speed', 99);
110
$config->set('top_solid_infill_speed', 99);
111
$config->set('cooling', 0); # for preventing speeds from being altered
112
$config->set('first_layer_speed', '100%'); # for preventing speeds from being altered
115
my $print = Slic3r::Test::init_print($model, config => $config);
117
my %T0_shells = my %T1_shells = (); # Z => 1
118
Slic3r::GCode::Reader->new->parse(my $gcode = Slic3r::Test::gcode($print), sub {
119
my ($self, $cmd, $args, $info) = @_;
121
if ($cmd =~ /^T(\d+)/) {
123
} elsif ($cmd eq 'G1' && $info->{extruding} && $info->{dist_XY} > 0) {
124
if (($args->{F} // $self->F) == $config->solid_infill_speed*60) {
126
$T0_shells{$self->Z} = 1;
127
} elsif ($tool == 1) {
128
$T1_shells{$self->Z} = 1;
133
return [ sort keys %T0_shells ], [ sort keys %T1_shells ];
137
my ($t0, $t1) = $test->();
138
is scalar(@$t0), 0, 'no interface shells';
139
is scalar(@$t1), 0, 'no interface shells';
142
$config->set('interface_shells', 1);
143
my ($t0, $t1) = $test->();
144
is scalar(@$t0), $lower_config->top_solid_layers, 'top interface shells';
145
is scalar(@$t1), $upper_config->bottom_solid_layers, 'bottom interface shells';
150
my $model = stacked_cubes();
152
my $config = Slic3r::Config->new_from_defaults;
153
$config->set('skirts', 0);
154
my $print = Slic3r::Test::init_print($model, config => $config);
156
is $model->get_material('lower')->config->extruder, 1, 'auto_assign_extruders() assigned correct extruder to first volume';
157
is $model->get_material('upper')->config->extruder, 2, 'auto_assign_extruders() assigned correct extruder to second volume';
160
my %T0 = my %T1 = (); # Z => 1
161
Slic3r::GCode::Reader->new->parse(my $gcode = Slic3r::Test::gcode($print), sub {
162
my ($self, $cmd, $args, $info) = @_;
164
if ($cmd =~ /^T(\d+)/) {
166
} elsif ($cmd eq 'G1' && $info->{extruding} && $info->{dist_XY} > 0) {
169
} elsif ($tool == 1) {
175
ok !(defined first { $_ > 20 } keys %T0), 'T0 is never used for upper object';
176
ok !(defined first { $_ < 20 } keys %T1), 'T1 is never used for lower object';
180
my $model = Slic3r::Model->new;
181
my $object = $model->add_object;
182
$object->add_volume(mesh => Slic3r::Test::mesh('20mm_cube'), material_id => 'lower');
183
$object->add_volume(mesh => Slic3r::Test::mesh('20mm_cube', translate => [0,0,20]), material_id => 'upper');
184
$object->add_instance(offset => Slic3r::Pointf->new(0,0));