1use Test::More tests => 38; 2use strict; 3use warnings; 4 5BEGIN { 6 use FindBin; 7 use lib "$FindBin::Bin/../lib"; 8 use local::lib "$FindBin::Bin/../local-lib"; 9} 10 11use List::Util qw(first); 12use Slic3r; 13use Slic3r::Test; 14 15{ 16 my $config = Slic3r::Config::new_from_defaults; 17 18 my $test = sub { 19 my ($conf) = @_; 20 $conf ||= $config; 21 22 my $print = Slic3r::Test::init_print('2x20x10', config => $conf); 23 24 my $last_move_was_z_change = 0; 25 Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub { 26 my ($self, $cmd, $args, $info) = @_; 27 28 if ($last_move_was_z_change && $cmd ne $config->layer_gcode) { 29 fail 'custom layer G-code was not applied after Z change'; 30 } 31 if (!$last_move_was_z_change && $cmd eq $config->layer_gcode) { 32 fail 'custom layer G-code was not applied after Z change'; 33 } 34 35 $last_move_was_z_change = (defined $info->{dist_Z} && $info->{dist_Z} > 0); 36 }); 37 38 1; 39 }; 40 41 $config->set('start_gcode', '_MY_CUSTOM_START_GCODE_'); # to avoid dealing with the nozzle lift in start G-code 42 $config->set('layer_gcode', '_MY_CUSTOM_LAYER_GCODE_'); 43 ok $test->(), "custom layer G-code is applied after Z move and before other moves"; 44} 45 46#========================================================== 47 48{ 49 my $config = Slic3r::Config::new_from_defaults; 50 $config->set('output_filename_format', 'ts_[travel_speed]_lh_[layer_height].gcode'); 51 $config->set('start_gcode', "TRAVEL:[travel_speed] HEIGHT:[layer_height]\n"); 52 my $print = Slic3r::Test::init_print('20mm_cube', config => $config); 53 54 my $output_file = $print->print->output_filepath; 55 my ($t, $h) = map $config->$_, qw(travel_speed layer_height); 56 ok $output_file =~ /ts_${t}_/, 'print config options are replaced in output filename'; 57 ok $output_file =~ /lh_$h\./, 'region config options are replaced in output filename'; 58 59 my $gcode = Slic3r::Test::gcode($print); 60 ok $gcode =~ /TRAVEL:$t/, 'print config options are replaced in custom G-code'; 61 ok $gcode =~ /HEIGHT:$h/, 'region config options are replaced in custom G-code'; 62} 63 64{ 65 my $config = Slic3r::Config->new; 66 $config->set('nozzle_diameter', [0.6,0.6,0.6,0.6]); 67 $config->set('extruder', 2); 68 $config->set('first_layer_temperature', [200,205]); 69 70 { 71 my $print = Slic3r::Test::init_print('20mm_cube', config => $config); 72 my $gcode = Slic3r::Test::gcode($print); 73 ok $gcode =~ /M104 S205 T1/, 'temperature set correctly for non-zero yet single extruder'; 74 ok $gcode !~ /M104 S\d+ T0/, 'unused extruder correctly ignored'; 75 } 76 77 $config->set('infill_extruder', 1); 78 { 79 my $print = Slic3r::Test::init_print('20mm_cube', config => $config); 80 my $gcode = Slic3r::Test::gcode($print); 81 ok $gcode =~ /M104 S200 T0/, 'temperature set correctly for first extruder'; 82 ok $gcode =~ /M104 S205 T1/, 'temperature set correctly for second extruder'; 83 } 84 85 my @start_gcode = (qq! 86;__temp0:[first_layer_temperature_0]__ 87;__temp1:[first_layer_temperature_1]__ 88;__temp2:[first_layer_temperature_2]__ 89 !, qq! 90;__temp0:{first_layer_temperature[0]}__ 91;__temp1:{first_layer_temperature[1]}__ 92;__temp2:{first_layer_temperature[2]}__ 93 !); 94 my @syntax_description = (' (legacy syntax)', ' (new syntax)'); 95 for my $i (0, 1) { 96 $config->set('start_gcode', $start_gcode[$i]); 97 { 98 my $print = Slic3r::Test::init_print('20mm_cube', config => $config); 99 my $gcode = Slic3r::Test::gcode($print); 100 # we use the [infill_extruder] placeholder to make sure this test doesn't 101 # catch a false positive caused by the unparsed start G-code option itself 102 # being embedded in the G-code 103 ok $gcode =~ /temp0:200/, 'temperature placeholder for first extruder correctly populated' . $syntax_description[$i]; 104 ok $gcode =~ /temp1:205/, 'temperature placeholder for second extruder correctly populated' . $syntax_description[$i]; 105 ok $gcode =~ /temp2:200/, 'temperature placeholder for unused extruder populated with first value' . $syntax_description[$i]; 106 } 107 } 108 109 $config->set('start_gcode', qq! 110;substitution:{if infill_extruder==1}extruder1 111 {elsif infill_extruder==2}extruder2 112 {else}extruder3{endif} 113 !); 114 { 115 my $print = Slic3r::Test::init_print('20mm_cube', config => $config); 116 my $gcode = Slic3r::Test::gcode($print); 117 ok $gcode =~ /substitution:extruder1/, 'if / else / endif - first block returned'; 118 } 119} 120 121{ 122 my $config = Slic3r::Config::new_from_defaults; 123 $config->set('before_layer_gcode', ';BEFORE [layer_num]'); 124 $config->set('layer_gcode', ';CHANGE [layer_num]'); 125 $config->set('support_material', 1); 126 $config->set('layer_height', 0.2); 127 my $print = Slic3r::Test::init_print('overhang', config => $config); 128 my $gcode = Slic3r::Test::gcode($print); 129 130 my @before = (); 131 my @change = (); 132 foreach my $line (split /\R+/, $gcode) { 133 if ($line =~ /;BEFORE (\d+)/) { 134 push @before, $1; 135 } elsif ($line =~ /;CHANGE (\d+)/) { 136 push @change, $1; 137 fail 'inconsistent layer_num before and after layer change' 138 if $1 != $before[-1]; 139 } 140 } 141 is_deeply \@before, \@change, 'layer_num is consistent before and after layer changes'; 142 ok !defined(first { $change[$_] != $change[$_-1]+1 } 1..$#change), 143 'layer_num grows continously'; # i.e. no duplicates or regressions 144} 145 146{ 147 my $config = Slic3r::Config->new; 148 $config->set('nozzle_diameter', [0.6,0.6,0.6,0.6,0.6]); 149 $config->set('start_gcode', qq! 150;substitution:{if infill_extruder==1}if block 151 {elsif infill_extruder==2}elsif block 1 152 {elsif infill_extruder==3}elsif block 2 153 {elsif infill_extruder==4}elsif block 3 154 {else}endif block{endif} 155 !); 156 my @returned = ('', 'if block', 'elsif block 1', 'elsif block 2', 'elsif block 3', 'endif block'); 157 for my $i (1,2,3,4,5) { 158 $config->set('infill_extruder', $i); 159 my $print = Slic3r::Test::init_print('20mm_cube', config => $config); 160 my $gcode = Slic3r::Test::gcode($print); 161 my $found_other = 0; 162 for my $j (1,2,3,4,5) { 163 next if $i == $j; 164 $found_other = 1 if $gcode =~ /substitution:$returned[$j]/; 165 } 166 ok $gcode =~ /substitution:$returned[$i]/, 'if / else / endif - ' . $returned[$i] . ' returned'; 167 ok !$found_other, 'if / else / endif - only ' . $returned[$i] . ' returned'; 168 } 169} 170 171{ 172 my $config = Slic3r::Config->new; 173 $config->set('nozzle_diameter', [0.6,0.6,0.6,0.6]); 174 $config->set('start_gcode', 175 ';substitution:{if infill_extruder==1}{if perimeter_extruder==1}block11{else}block12{endif}' . 176 '{elsif infill_extruder==2}{if perimeter_extruder==1}block21{else}block22{endif}' . 177 '{else}{if perimeter_extruder==1}block31{else}block32{endif}{endif}:end'); 178 for my $i (1,2,3) { 179 $config->set('infill_extruder', $i); 180 for my $j (1,2) { 181 $config->set('perimeter_extruder', $j); 182 my $print = Slic3r::Test::init_print('20mm_cube', config => $config); 183 my $gcode = Slic3r::Test::gcode($print); 184 ok $gcode =~ /substitution:block$i$j:end/, "two level if / else / endif - block$i$j returned"; 185 } 186 } 187} 188 189{ 190 my $config = Slic3r::Config->new; 191 $config->set('start_gcode', 192 ';substitution:{if notes=="MK2"}MK2{elsif notes=="MK3"}MK3{else}MK1{endif}:end'); 193 for my $printer_name ("MK2", "MK3", "MK1") { 194 $config->set('notes', $printer_name); 195 my $print = Slic3r::Test::init_print('20mm_cube', config => $config); 196 my $gcode = Slic3r::Test::gcode($print); 197 ok $gcode =~ /substitution:$printer_name:end/, "printer name $printer_name matched"; 198 } 199} 200 201{ 202 my $config = Slic3r::Config::new_from_defaults; 203 $config->set('complete_objects', 1); 204 $config->set('between_objects_gcode', '_MY_CUSTOM_GCODE_'); 205 my $print = Slic3r::Test::init_print('20mm_cube', config => $config, duplicate => 3); 206 my $gcode = Slic3r::Test::gcode($print); 207 is scalar(() = $gcode =~ /^_MY_CUSTOM_GCODE_/gm), 2, 'between_objects_gcode is applied correctly'; 208} 209 210__END__ 211