diff --git a/Build.PL b/Build.PL index 53dccbbba..89af11ed8 100644 --- a/Build.PL +++ b/Build.PL @@ -8,10 +8,11 @@ my $build = Module::Build->new( license => 'perl', requires => { 'Boost::Geometry::Utils' => '0', + 'Encode::Locale' => '0', 'File::Basename' => '0', 'File::Spec' => '0', 'Getopt::Long' => '0', - 'Math::Clipper' => '1.15', + 'Math::Clipper' => '1.17', 'Math::ConvexHull::MonotoneChain' => '0.01', 'Math::Geometry::Voronoi' => '1.3', 'Math::PlanePath' => '53', diff --git a/README.markdown b/README.markdown index e804e51db..bc012abcf 100644 --- a/README.markdown +++ b/README.markdown @@ -108,7 +108,7 @@ The author of the Silk icon set is Mark James. (default: 100,100) --z-offset Additional height in mm to add to vertical coordinates (+/-, default: 0) - --gcode-flavor The type of G-code to generate (reprap/teacup/makerbot/mach3/no-extrusion, + --gcode-flavor The type of G-code to generate (reprap/teacup/makerbot/sailfish/mach3/no-extrusion, default: reprap) --use-relative-e-distances Enable this to get relative E values --gcode-arcs Use G2/G3 commands for native arcs (experimental, not supported @@ -275,7 +275,7 @@ The author of the Silk icon set is Mark James. (like 0.65) or a percentage over layer height (like 200%) --first-layer-extrusion-width Set a different extrusion width for first layer - --perimeters-extrusion-width + --perimeter-extrusion-width Set a different extrusion width for perimeters --infill-extrusion-width Set a different extrusion width for infill @@ -286,7 +286,7 @@ The author of the Silk icon set is Mark James. Multiple extruder options: --extruder-offset Offset of each extruder, if firmware doesn't handle the displacement (can be specified multiple times, default: 0x0) - --perimeters-extruder + --perimeter-extruder Extruder to use for perimeters (1+, default: 1) --infill-extruder Extruder to use for infill (1+, default: 1) --support-material-extruder diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index 1f291ac51..f6653ea4d 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -7,7 +7,7 @@ use strict; use warnings; require v5.10; -our $VERSION = "0.9.8-dev"; +our $VERSION = "0.9.9-dev"; our $debug = 0; sub debugf { @@ -27,7 +27,10 @@ warn "Running Slic3r under Perl >= 5.16 is not supported nor recommended\n" use FindBin; our $var = "$FindBin::Bin/var"; +use Encode; +use Encode::Locale; use Moo 0.091009; + use Slic3r::Config; use Slic3r::ExPolygon; use Slic3r::Extruder; @@ -89,4 +92,9 @@ sub parallelize { } } +sub open { + my ($fh, $mode, $filename) = @_; + return CORE::open $$fh, $mode, encode('locale_fs', $filename); +} + 1; diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index f8dd403af..a8653ab8c 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -64,8 +64,8 @@ our $Options = { tooltip => 'Some G/M-code commands, including temperature control and others, are not universal. Set this option to your printer\'s firmware to get a compatible output. The "No extrusion" flavor prevents Slic3r from exporting any extrusion value at all.', cli => 'gcode-flavor=s', type => 'select', - values => [qw(reprap teacup makerbot mach3 no-extrusion)], - labels => ['RepRap (Marlin/Sprinter)', 'Teacup', 'MakerBot', 'Mach3/EMC', 'No extrusion'], + values => [qw(reprap teacup makerbot sailfish mach3 no-extrusion)], + labels => ['RepRap (Marlin/Sprinter)', 'Teacup', 'MakerBot', 'Sailfish', 'Mach3/EMC', 'No extrusion'], default => 'reprap', }, 'use_relative_e_distances' => { @@ -158,7 +158,7 @@ our $Options = { sidetext => '°C', cli => 'temperature=i@', type => 'i', - max => 300, + max => 400, serialize => $serialize_comma, deserialize => sub { $_[0] ? [ split /,/, $_[0] ] : [0] }, default => [200], @@ -171,7 +171,7 @@ our $Options = { type => 'i', serialize => $serialize_comma, deserialize => sub { $_[0] ? [ split /,/, $_[0] ] : [0] }, - max => 300, + max => 400, default => [200], }, @@ -703,7 +703,7 @@ END type => 'f', serialize => $serialize_comma, deserialize => $deserialize_comma, - default => [3], + default => [10], }, 'retract_restart_extra_toolchange' => { label => 'Extra length on restart', @@ -722,7 +722,7 @@ END tooltip => 'This flag enables all the cooling features.', cli => 'cooling!', type => 'bool', - default => 0, + default => 1, }, 'min_fan_speed' => { label => 'Min', @@ -953,7 +953,7 @@ sub new_from_cli { if ($args{$opt_key}) { die "Invalid value for --${_}-gcode: file does not exist\n" if !-e $args{$opt_key}; - open my $fh, "<", $args{$opt_key} + Slic3r::open(\my $fh, "<", $args{$opt_key}) or die "Failed to open $args{$opt_key}\n"; binmode $fh, ':utf8'; $args{$opt_key} = do { local $/; <$fh> }; @@ -1031,6 +1031,17 @@ sub set { $value = 1; } + # For historical reasons, the world's full of configs having these very low values; + # to avoid unexpected behavior we need to ignore them. Banning these two hard-coded + # values is a dirty hack and will need to be removed sometime in the future, but it + # will avoid lots of complaints for now. + if ($opt_key eq 'perimeter_acceleration' && $value == '25') { + $value = 0; + } + if ($opt_key eq 'infill_acceleration' && $value == '50') { + $value = 0; + } + if (!exists $Options->{$opt_key}) { my @keys = grep { $Options->{$_}{aliases} && grep $_ eq $opt_key, @{$Options->{$_}{aliases}} } keys %$Options; if (!@keys) { @@ -1258,7 +1269,7 @@ sub write_ini { my $class = shift; my ($file, $ini) = @_; - open my $fh, '>', $file; + Slic3r::open(\my $fh, '>', $file); binmode $fh, ':utf8'; my $localtime = localtime; printf $fh "# generated by Slic3r $Slic3r::VERSION on %s\n", "$localtime"; @@ -1276,7 +1287,7 @@ sub read_ini { my ($file) = @_; local $/ = "\n"; - open my $fh, '<', $file; + Slic3r::open(\my $fh, '<', $file); binmode $fh, ':utf8'; my $ini = { _ => {} }; diff --git a/lib/Slic3r/Format/AMF.pm b/lib/Slic3r/Format/AMF.pm index 0e44353cf..0b3bbc1ed 100644 --- a/lib/Slic3r/Format/AMF.pm +++ b/lib/Slic3r/Format/AMF.pm @@ -13,7 +13,7 @@ sub read_file { 1; } or die "AMF parsing requires XML::SAX\n"; - open my $fh, '<', $file or die "Failed to open $file\n"; + Slic3r::open(\my $fh, '<', $file) or die "Failed to open $file\n"; my $model = Slic3r::Model->new; XML::SAX::ParserFactory @@ -30,7 +30,7 @@ sub write_file { my %vertices_offset = (); - open my $fh, '>', $file; + Slic3r::open(\my $fh, '>', $file); binmode $fh, ':utf8'; printf $fh qq{\n}; printf $fh qq{\n}; diff --git a/lib/Slic3r/Format/OBJ.pm b/lib/Slic3r/Format/OBJ.pm index d663cfb5a..c5cc08555 100644 --- a/lib/Slic3r/Format/OBJ.pm +++ b/lib/Slic3r/Format/OBJ.pm @@ -5,7 +5,7 @@ sub read_file { my $self = shift; my ($file) = @_; - open my $fh, '<', $file or die "Failed to open $file\n"; + Slic3r::open(\my $fh, '<', $file) or die "Failed to open $file\n"; my $vertices = []; my $facets = []; while (my $_ = <$fh>) { diff --git a/lib/Slic3r/Format/STL.pm b/lib/Slic3r/Format/STL.pm index 6e9665185..5c992230e 100644 --- a/lib/Slic3r/Format/STL.pm +++ b/lib/Slic3r/Format/STL.pm @@ -7,7 +7,7 @@ sub read_file { my $self = shift; my ($file) = @_; - open my $fh, '<', $file or die "Failed to open $file\n"; + Slic3r::open(\my $fh, '<', $file) or die "Failed to open $file\n"; # let's detect whether file is ASCII or binary my $mode; @@ -103,7 +103,7 @@ sub write_file { my $self = shift; my ($file, $model, %params) = @_; - open my $fh, '>', $file; + Slic3r::open(\my $fh, '>', $file); $params{binary} ? _write_binary($fh, $model->mesh) diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm index 69409c066..35a878ea2 100644 --- a/lib/Slic3r/GCode.pm +++ b/lib/Slic3r/GCode.pm @@ -7,6 +7,7 @@ use Slic3r::Geometry qw(scale unscale scaled_epsilon points_coincide PI X Y B); use Slic3r::Geometry::Clipper qw(union_ex); has 'multiple_extruders' => (is => 'ro', default => sub {0} ); +has 'layer_count' => (is => 'ro', required => 1 ); has 'layer' => (is => 'rw'); has 'move_z_callback' => (is => 'rw'); has 'shift_x' => (is => 'rw', default => sub {0} ); @@ -80,6 +81,14 @@ sub change_layer { islands => union_ex([ map @$_, @{$layer->slices} ], undef, 1), )); } + + my $gcode = ""; + if ($Slic3r::Config->gcode_flavor =~ /^(?:makerbot|sailfish)$/) { + $gcode .= sprintf "M73 P%s%s\n", + int(100 * ($layer->id / ($self->layer_count - 1))), + ($Slic3r::Config->gcode_comments ? ' ; update progress' : ''); + } + return $gcode; } # this method accepts Z in scaled coordinates @@ -502,8 +511,18 @@ sub set_extruder { # set the new extruder $self->extruder($extruder); - $gcode .= sprintf "T%d%s\n", $extruder->id, ($Slic3r::Config->gcode_comments ? ' ; change extruder' : ''); - $gcode .= $self->reset_e; + my $toolchange_gcode = sprintf "%s%d%s\n", + ($Slic3r::Config->gcode_flavor =~ /^(?:makerbot|sailfish)$/ ? 'M108 T' : 'T'), + $extruder->id, + ($Slic3r::Config->gcode_comments ? ' ; change extruder' : ''); + + if ($Slic3r::Config->gcode_flavor =~ /^(?:makerbot|sailfish)$/) { + $gcode .= $self->reset_e; + $gcode .= $toolchange_gcode; + } else { + $gcode .= $toolchange_gcode; + $gcode .= $self->reset_e; + } return $gcode; } @@ -517,11 +536,17 @@ sub set_fan { if ($speed == 0) { my $code = $Slic3r::Config->gcode_flavor eq 'teacup' ? 'M106 S0' - : 'M107'; + : $Slic3r::Config->gcode_flavor =~ /^(?:makerbot|sailfish)$/ + ? 'M127' + : 'M107'; return sprintf "$code%s\n", ($Slic3r::Config->gcode_comments ? ' ; disable fan' : ''); } else { - return sprintf "M106 %s%d%s\n", ($Slic3r::Config->gcode_flavor eq 'mach3' ? 'P' : 'S'), - (255 * $speed / 100), ($Slic3r::Config->gcode_comments ? ' ; enable fan' : ''); + if ($Slic3r::Config->gcode_flavor =~ /^(?:makerbot|sailfish)$/) { + return sprintf "M126%s\n", ($Slic3r::Config->gcode_comments ? ' ; enable fan' : ''); + } else { + return sprintf "M106 %s%d%s\n", ($Slic3r::Config->gcode_flavor eq 'mach3' ? 'P' : 'S'), + (255 * $speed / 100), ($Slic3r::Config->gcode_comments ? ' ; enable fan' : ''); + } } } return ""; @@ -531,14 +556,14 @@ sub set_temperature { my $self = shift; my ($temperature, $wait, $tool) = @_; - return "" if $wait && $Slic3r::Config->gcode_flavor eq 'makerbot'; + return "" if $wait && $Slic3r::Config->gcode_flavor =~ /^(?:makerbot|sailfish)$/; my ($code, $comment) = ($wait && $Slic3r::Config->gcode_flavor ne 'teacup') ? ('M109', 'wait for temperature to be reached') : ('M104', 'set temperature'); my $gcode = sprintf "$code %s%d %s; $comment\n", ($Slic3r::Config->gcode_flavor eq 'mach3' ? 'P' : 'S'), $temperature, - (defined $tool && $self->multiple_extruders) ? "T$tool " : ""; + (defined $tool && ($self->multiple_extruders || $Slic3r::Config->gcode_flavor =~ /^(?:makerbot|sailfish)$/)) ? "T$tool " : ""; $gcode .= "M116 ; wait for temperature to be reached\n" if $Slic3r::Config->gcode_flavor eq 'teacup' && $wait; @@ -551,8 +576,7 @@ sub set_bed_temperature { my ($temperature, $wait) = @_; my ($code, $comment) = ($wait && $Slic3r::Config->gcode_flavor ne 'teacup') - ? (($Slic3r::Config->gcode_flavor eq 'makerbot' ? 'M109' - : 'M190'), 'wait for bed temperature to be reached') + ? (($Slic3r::Config->gcode_flavor =~ /^(?:makerbot|sailfish)$/ ? 'M109' : 'M190'), 'wait for bed temperature to be reached') : ('M140', 'set bed temperature'); my $gcode = sprintf "$code %s%d ; $comment\n", ($Slic3r::Config->gcode_flavor eq 'mach3' ? 'P' : 'S'), $temperature; diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 737204926..fb53b5cb5 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -413,8 +413,9 @@ sub notify { my $notifier = $serv->get_object('/org/freedesktop/Notifications', 'org.freedesktop.Notifications'); $notifier->Notify('Slic3r', 0, $self->{icon}, $title, $message, [], {}, -1); - } - }; + undef $Net::DBus::bus_session; + }; + } } 1; diff --git a/lib/Slic3r/GUI/AboutDialog.pm b/lib/Slic3r/GUI/AboutDialog.pm index f8936338e..f2a390bb2 100644 --- a/lib/Slic3r/GUI/AboutDialog.pm +++ b/lib/Slic3r/GUI/AboutDialog.pm @@ -47,12 +47,12 @@ sub new { '' . '' . '' . - 'Copyright © 2011-2012 Alessandro Ranellucci. All rights reserved. ' . + 'Copyright © 2011-2013 Alessandro Ranellucci. All rights reserved. ' . 'Slic3r is licensed under the ' . 'GNU Affero General Public License, version 3.' . '


' . 'Slic3r logo designed by Corey Daniels, Silk Icon Set designed by Mark James. ' . - 'Contributions by Henrik Brix Andersen, Nicolas Dandrimont, Mark Hindess and numerous others.' . + 'Contributions by Henrik Brix Andersen, Nicolas Dandrimont, Mark Hindess, Mike Sheldrake and numerous others.' . '
' . '' . ''; diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index a8b30cba2..caa9dcb3f 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -62,7 +62,7 @@ sub new { Wx::ToolTip::Enable(1); $self->{htoolbar} = Wx::ToolBar->new($self, -1, wxDefaultPosition, wxDefaultSize, wxTB_HORIZONTAL | wxTB_TEXT | wxBORDER_SIMPLE | wxTAB_TRAVERSAL); $self->{htoolbar}->AddTool(TB_MORE, "More", Wx::Bitmap->new("$Slic3r::var/add.png", wxBITMAP_TYPE_PNG), ''); - $self->{htoolbar}->AddTool(TB_LESS, "Less", Wx::Bitmap->new("$Slic3r::var/delete.png", wxBITMAP_TYPE_PNG), ''); + $self->{htoolbar}->AddTool(TB_LESS, "Fewer", Wx::Bitmap->new("$Slic3r::var/delete.png", wxBITMAP_TYPE_PNG), ''); $self->{htoolbar}->AddSeparator; $self->{htoolbar}->AddTool(TB_45CCW, "45° ccw", Wx::Bitmap->new("$Slic3r::var/arrow_rotate_anticlockwise.png", wxBITMAP_TYPE_PNG), ''); $self->{htoolbar}->AddTool(TB_45CW, "45° cw", Wx::Bitmap->new("$Slic3r::var/arrow_rotate_clockwise.png", wxBITMAP_TYPE_PNG), ''); diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index 8cdc8d7b2..edb47a9fe 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -18,7 +18,7 @@ use constant FILE_WILDCARDS => { obj => 'OBJ files (*.obj)|*.obj;*.OBJ', amf => 'AMF files (*.amf)|*.amf;*.AMF;*.xml;*.XML', ini => 'INI files *.ini|*.ini;*.INI', - gcode => 'G-code files *.gcode|*.gcode;*.GCODE|G-code files *.g|*.g;*.G', + gcode => 'G-code files (*.gcode, *.gco, *.g)|*.gcode;*.GCODE;*.gco;*.GCO;*.g;*.G', svg => 'SVG files *.svg|*.svg;*.SVG', }; use constant MODEL_WILDCARD => join '|', @{&FILE_WILDCARDS}{qw(stl obj amf)}; diff --git a/lib/Slic3r/Geometry/Clipper.pm b/lib/Slic3r/Geometry/Clipper.pm index 9dedc7a96..292e88f27 100644 --- a/lib/Slic3r/Geometry/Clipper.pm +++ b/lib/Slic3r/Geometry/Clipper.pm @@ -8,7 +8,7 @@ our @EXPORT_OK = qw(safety_offset offset offset_ex diff_ex diff union_ex intersection_ex xor_ex PFT_EVENODD JT_MITER JT_ROUND JT_SQUARE is_counter_clockwise); -use Math::Clipper 1.15 qw(:cliptypes :polyfilltypes :jointypes is_counter_clockwise area); +use Math::Clipper 1.17 qw(:cliptypes :polyfilltypes :jointypes is_counter_clockwise area); use Slic3r::Geometry qw(scale); our $clipper = Math::Clipper->new; @@ -21,7 +21,7 @@ sub offset { my ($polygons, $distance, $scale, $joinType, $miterLimit) = @_; $scale ||= 100000; $joinType //= JT_MITER; - $miterLimit //= 10; + $miterLimit //= 3; my $offsets = Math::Clipper::offset($polygons, $distance, $scale, $joinType, $miterLimit); return @$offsets; diff --git a/lib/Slic3r/Layer/Region.pm b/lib/Slic3r/Layer/Region.pm index 238a8e98e..37d9b7723 100644 --- a/lib/Slic3r/Layer/Region.pm +++ b/lib/Slic3r/Layer/Region.pm @@ -252,7 +252,7 @@ sub make_perimeters { } # fill gaps - if ($Slic3r::Config->gap_fill_speed > 0) { + if ($Slic3r::Config->gap_fill_speed > 0 && $Slic3r::Config->fill_density > 0) { my $filler = Slic3r::Fill::Rectilinear->new(layer_id => $self->layer->id); my $w = $self->perimeter_flow->width; diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index 2947c41a8..0bfdeec07 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -242,11 +242,7 @@ sub object_copies { sub layer_count { my $self = shift; - my $count = 0; - foreach my $object (@{$self->objects}) { - $count = @{$object->layers} if @{$object->layers} > $count; - } - return $count; + return max(map { scalar @{$_->layers} } @{$self->objects}); } sub regions_count { @@ -472,7 +468,7 @@ sub export_svg { my $output_file = $self->expanded_output_filepath($params{output_file}); $output_file =~ s/\.gcode$/.svg/i; - open my $fh, ">", $output_file or die "Failed to open $output_file for writing\n"; + Slic3r::open(\my $fh, ">", $output_file) or die "Failed to open $output_file for writing\n"; print "Exporting to $output_file..."; my $print_size = $self->size; print $fh sprintf <<"EOF", unscale($print_size->[X]), unscale($print_size->[Y]); @@ -550,10 +546,10 @@ sub make_skirt { return unless $Slic3r::Config->skirts > 0; # collect points from all layers contained in skirt height - my $skirt_height = $Slic3r::Config->skirt_height; - $skirt_height = $self->layer_count if $skirt_height > $self->layer_count; my @points = (); foreach my $obj_idx (0 .. $#{$self->objects}) { + my $skirt_height = $Slic3r::Config->skirt_height; + $skirt_height = $self->objects->[$obj_idx]->layer_count if $skirt_height > $self->objects->[$obj_idx]->layer_count; my @layers = map $self->objects->[$obj_idx]->layers->[$_], 0..($skirt_height-1); my @layer_points = ( (map @$_, map @$_, map @{$_->slices}, @layers), @@ -647,7 +643,7 @@ sub write_gcode { if (ref $file eq 'IO::Scalar') { $fh = $file; } else { - open $fh, ">", $file + Slic3r::open(\$fh, ">", $file) or die "Failed to open $file for writing\n"; } @@ -675,7 +671,8 @@ sub write_gcode { # set up our extruder object my $gcodegen = Slic3r::GCode->new( - multiple_extruders => (@{$self->extruders} > 1), + multiple_extruders => (@{$self->extruders} > 1), + layer_count => $self->layer_count, ); my $min_print_speed = 60 * $Slic3r::Config->min_print_speed; my $dec = $gcodegen->dec; @@ -700,7 +697,7 @@ sub write_gcode { print $fh "G21 ; set units to millimeters\n"; if ($Slic3r::Config->gcode_flavor =~ /^(?:reprap|teacup)$/) { printf $fh $gcodegen->reset_e; - if ($Slic3r::Config->gcode_flavor =~ /^(?:reprap|makerbot)$/) { + if ($Slic3r::Config->gcode_flavor =~ /^(?:reprap|makerbot|sailfish)$/) { if ($Slic3r::Config->use_relative_e_distances) { print $fh "M83 ; use relative distances for extrusion\n"; } else { @@ -753,7 +750,7 @@ sub write_gcode { } # set new layer, but don't move Z as support material interfaces may need an intermediate one - $gcodegen->change_layer($self->objects->[$object_copies->[0][0]]->layers->[$layer_id]); + $gcode .= $gcodegen->change_layer($self->objects->[$object_copies->[0][0]]->layers->[$layer_id]); $gcodegen->elapsed_time(0); # prepare callback to call as soon as a Z command is generated diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index bf4f77aa0..1457a66ec 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -445,8 +445,8 @@ sub combine_infill { my $area_threshold = $Slic3r::flow->scaled_spacing ** 2; for my $region_id (0 .. ($self->print->regions_count-1)) { - # start from bottom, skip first layer - for (my $i = 1; $i < $self->layer_count; $i++) { + # start from top, skip lowest layer + for (my $i = $self->layer_count - 1; $i > 0; $i--) { my $layerm = $self->layers->[$i]->regions->[$region_id]; # skip layer if no internal fill surfaces @@ -506,6 +506,13 @@ sub combine_infill { { my @new_surfaces = (); push @new_surfaces, grep $_->surface_type != S_TYPE_INTERNAL, @{$lower_layerm->fill_surfaces}; + + # offset for the two different flow spacings + $intersection = [ map $_->offset_ex( + $lower_layerm->infill_flow->scaled_spacing / 2 + + $layerm->infill_flow->scaled_spacing / 2 + ), @$intersection]; + foreach my $depth (1..$Slic3r::Config->infill_every_layers) { push @new_surfaces, map Slic3r::Surface->new (expolygon => $_, surface_type => S_TYPE_INTERNAL, depth_layers => $depth), @@ -554,9 +561,14 @@ sub generate_support_material { my $layer = $self->layers->[$i]; my $lower_layer = $i > 0 ? $self->layers->[$i-1] : undef; + my @current_layer_offsetted_slices = map $_->offset_ex($distance_from_object), @{$layer->slices}; + # $queue[-1] contains the overhangs of the upper layer, regardless of any empty interface layers # $queue[0] contains the overhangs of the first upper layer above the empty interface layers - $layers_interfaces{$i} = [@{ $queue[-1] || [] }]; + $layers_interfaces{$i} = diff_ex( + [ map @$_, @{ $queue[-1] || [] } ], + [ map @$_, @current_layer_offsetted_slices ], + ); # step 1: generate support material in current layer (for upper layers) push @current_support_regions, @{ shift @queue } if @queue && $i < $#{$self->layers}; @@ -569,11 +581,11 @@ sub generate_support_material { $layers{$i} = diff_ex( [ map @$_, @current_support_regions ], [ - (map @$_, map $_->offset_ex($distance_from_object), @{$layer->slices}), + (map @$_, @current_layer_offsetted_slices), (map @$_, @{ $layers_interfaces{$i} }), ], ); - $_->simplify($flow->scaled_spacing * 2) for @{$layers{$i}}; + $_->simplify($flow->scaled_spacing) for @{$layers{$i}}; # step 2: get layer overhangs and put them into queue for adding support inside lower layers # we need an angle threshold for this @@ -667,6 +679,7 @@ sub generate_support_material { items => [ keys %layers ], thread_cb => sub { my $q = shift; + $Slic3r::Geometry::Clipper::clipper = Math::Clipper->new; my $result = {}; while (defined (my $layer_id = $q->dequeue)) { $result->{$layer_id} = [ $process_layer->($layer_id) ]; diff --git a/lib/Slic3r/SVG.pm b/lib/Slic3r/SVG.pm index 8621614b5..0179ea769 100644 --- a/lib/Slic3r/SVG.pm +++ b/lib/Slic3r/SVG.pm @@ -130,7 +130,7 @@ sub output_lines { sub write_svg { my ($svg, $filename) = @_; - open my $fh, '>', $filename; + Slic3r::open(\my $fh, '>', $filename); print $fh $svg->xmlify; close $fh; printf "SVG written to %s\n", $filename; diff --git a/lib/Slic3r/TriangleMesh.pm b/lib/Slic3r/TriangleMesh.pm index d830ba54c..0f5df9a4e 100644 --- a/lib/Slic3r/TriangleMesh.pm +++ b/lib/Slic3r/TriangleMesh.pm @@ -152,9 +152,9 @@ sub check_manifoldness { my ($first_bad_edge_id) = grep { @{ $self->edges_facets->[$_] } != 2 } 0..$#{$self->edges_facets}; if (defined $first_bad_edge_id) { - warn sprintf "Warning: The input file contains a hole near edge %f-%f (not manifold). " + warn sprintf "Warning: The input file contains a hole near edge %f,%f,%f-%f,%f,%f (not manifold). " . "You might want to repair it and retry, or to check the resulting G-code before printing anyway.\n", - @{$self->edges->[$first_bad_edge_id]}; + map @{$self->vertices->[$_]}, @{$self->edges->[$first_bad_edge_id]}; return 0; } return 1; diff --git a/slic3r.pl b/slic3r.pl index 1d4b88932..c66277c58 100755 --- a/slic3r.pl +++ b/slic3r.pl @@ -156,7 +156,7 @@ $j (default: $config->{print_center}->[0],$config->{print_center}->[1]) --z-offset Additional height in mm to add to vertical coordinates (+/-, default: $config->{z_offset}) - --gcode-flavor The type of G-code to generate (reprap/teacup/makerbot/mach3/no-extrusion, + --gcode-flavor The type of G-code to generate (reprap/teacup/makerbot/sailfish/mach3/no-extrusion, default: $config->{gcode_flavor}) --use-relative-e-distances Enable this to get relative E values --gcode-arcs Use G2/G3 commands for native arcs (experimental, not supported @@ -323,7 +323,7 @@ $j (like 0.65) or a percentage over layer height (like 200%) --first-layer-extrusion-width Set a different extrusion width for first layer - --perimeters-extrusion-width + --perimeter-extrusion-width Set a different extrusion width for perimeters --infill-extrusion-width Set a different extrusion width for infill @@ -334,7 +334,7 @@ $j Multiple extruder options: --extruder-offset Offset of each extruder, if firmware doesn't handle the displacement (can be specified multiple times, default: 0x0) - --perimeters-extruder + --perimeter-extruder Extruder to use for perimeters (1+, default: 1) --infill-extruder Extruder to use for infill (1+, default: 1) --support-material-extruder diff --git a/t/retraction.t b/t/retraction.t index 8ad1fbc79..3d1087656 100644 --- a/t/retraction.t +++ b/t/retraction.t @@ -21,6 +21,7 @@ my $test = sub { 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 my @retracted = (1); # ignore the first travel move from home to first point + my @retracted_length = (0); my $lifted = 0; my $changed_tool = 0; my $wait_for_toolchange = 0; @@ -52,21 +53,22 @@ my $test = sub { } } if ($info->{retracting}) { - if (_eq(-$info->{dist_E}, $print->extruders->[$tool]->retract_length)) { + $retracted[$tool] = 1; + $retracted_length[$tool] += -$info->{dist_E}; + if (_eq($retracted_length[$tool], $print->extruders->[$tool]->retract_length)) { # okay - } elsif (_eq(-$info->{dist_E}, $print->extruders->[$tool]->retract_length_toolchange)) { + } elsif (_eq($retracted_length[$tool], $print->extruders->[$tool]->retract_length_toolchange)) { $wait_for_toolchange = 1; } else { fail 'retracted by the correct amount'; } fail 'combining retraction and travel with G0' if $cmd ne 'G0' && $conf->g0 && ($info->{dist_Z} || $info->{dist_XY}); - $retracted[$tool] = 1; } if ($info->{extruding}) { fail 'only extruding while not lifted' if $lifted; if ($retracted[$tool]) { - my $expected_amount = $print->extruders->[$tool]->retract_length + $print->extruders->[$tool]->retract_restart_extra; + my $expected_amount = $retracted_length[$tool] + $print->extruders->[$tool]->retract_restart_extra; if ($changed_tool && $toolchange_count[$tool] > 1) { $expected_amount = $print->extruders->[$tool]->retract_length_toolchange + $print->extruders->[$tool]->retract_restart_extra_toolchange; $changed_tool = 0; @@ -74,6 +76,7 @@ my $test = sub { fail 'unretracted by the correct amount' if !_eq($info->{dist_E}, $expected_amount); $retracted[$tool] = 0; + $retracted_length[$tool] = 0; } } if ($info->{travel} && $info->{dist_XY} >= $print->extruders->[$tool]->retract_before_travel) { diff --git a/utils/zsh/functions/_slic3r b/utils/zsh/functions/_slic3r index 384c812a5..41b2594bd 100644 --- a/utils/zsh/functions/_slic3r +++ b/utils/zsh/functions/_slic3r @@ -22,7 +22,7 @@ _arguments -S \ '*--nozzle-diameter[specify nozzle diameter]:nozzle diameter in mm' \ '--print-center[specify print center coordinates]:print center coordinates in mm,mm' \ '--z-offset[specify Z-axis offset]:Z-axis offset in mm' \ - '--gcode-flavor[specify the type of G-code to generate]:G-code flavor:(reprap teacup makerbot mach3 no-extrusion)' \ + '--gcode-flavor[specify the type of G-code to generate]:G-code flavor:(reprap teacup makerbot sailfish mach3 no-extrusion)' \ '(--use-relative-e-distances --no-use-relative-e-distances)'--{no-,}use-relative-e-distances'[disable/enable relative E values]' \ '--extrusion-axis[specify letter associated with the extrusion axis]:extrusion axis letter' \ '(--gcode-arcs --no-gcode-arcs)'--{no-,}gcode-arcs'[disable/enable G2/G3 commands for native arcs]' \