diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index 8ab34ca3..1c5ffa74 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -68,6 +68,7 @@ use Slic3r::Polyline; use Slic3r::Print; use Slic3r::Print::Object; use Slic3r::Print::Region; +use Slic3r::Print::Simple; use Slic3r::Print::SupportMaterial; use Slic3r::Surface; use Slic3r::TriangleMesh; diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index 7750794c..371698e0 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -88,25 +88,15 @@ sub quick_slice { my $self = shift; my %params = @_; - my $process_dialog; + my $progress_dialog; eval { # validate configuration my $config = $self->config; $config->validate; - - # confirm slicing of more than one copies - my $copies = $config->duplicate_grid->[X] * $config->duplicate_grid->[Y]; - $copies = $config->duplicate if $config->duplicate > 1; - if ($copies > 1) { - my $confirmation = Wx::MessageDialog->new($self, "Are you sure you want to slice $copies copies?", - 'Multiple Copies', wxICON_QUESTION | wxOK | wxCANCEL); - return unless $confirmation->ShowModal == wxID_OK; - } # select input file - my $dir = $Slic3r::GUI::Settings->{recent}{skein_directory} || $Slic3r::GUI::Settings->{recent}{config_directory} || ''; - my $input_file; + my $dir = $Slic3r::GUI::Settings->{recent}{skein_directory} || $Slic3r::GUI::Settings->{recent}{config_directory} || ''; if (!$params{reslice}) { my $dialog = Wx::FileDialog->new($self, 'Choose a file to slice (STL/OBJ/AMF):', $dir, "", MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST); if ($dialog->ShowModal != wxID_OK) { @@ -133,31 +123,23 @@ sub quick_slice { $Slic3r::GUI::Settings->{recent}{skein_directory} = dirname($input_file); Slic3r::GUI->save_settings; - my $print = $self->init_print; - my $model = eval { Slic3r::Model->read_from_file($input_file) }; - Slic3r::GUI::show_error($self, $@) if $@; + my $sprint = Slic3r::Print::Simple->new( + status_cb => sub { + my ($percent, $message) = @_; + return if &Wx::wxVERSION_STRING !~ / 2\.(8\.|9\.[2-9])/; + $progress_dialog->Update($percent, "$message…"); + }, + ); - if ($model->has_objects_with_no_instances) { - # apply a default position to all objects not having one - foreach my $object (@{$model->objects}) { - $object->add_instance(offset => [0,0]) if !defined $object->instances; - } - $model->arrange_objects($config->min_object_distance); - } - $model->center_instances_around_point($config->print_center); + $sprint->apply_config($config); + $sprint->set_model(Slic3r::Model->read_from_file($input_file)); - foreach my $model_object (@{$model->objects}) { - $print->auto_assign_extruders($model_object); - $print->add_model_object($model_object); - } - $print->validate; - # select output file - my $output_file = $main::opt{output}; + my $output_file; if ($params{reslice}) { $output_file = $last_output_file if defined $last_output_file; } elsif ($params{save_as}) { - $output_file = $print->expanded_output_filepath($output_file); + $output_file = $sprint->expanded_output_filepath; $output_file =~ s/\.gcode$/.svg/i if $params{export_svg}; my $dlg = Wx::FileDialog->new($self, 'Save ' . ($params{export_svg} ? 'SVG' : 'G-code') . ' file as:', Slic3r::GUI->output_path(dirname($output_file)), @@ -174,40 +156,32 @@ sub quick_slice { } # show processbar dialog - $process_dialog = Wx::ProgressDialog->new('Slicing…', "Processing $input_file_basename…", + $progress_dialog = Wx::ProgressDialog->new('Slicing…', "Processing $input_file_basename…", 100, $self, 0); - $process_dialog->Pulse; + $progress_dialog->Pulse; { my @warnings = (); local $SIG{__WARN__} = sub { push @warnings, $_[0] }; - my %export_params = ( - output_file => $output_file, - ); - $print->status_cb(sub { - my ($percent, $message) = @_; - if (&Wx::wxVERSION_STRING =~ / 2\.(8\.|9\.[2-9])/) { - $process_dialog->Update($percent, "$message…"); - } - }); + + $sprint->output_file($output_file); if ($params{export_svg}) { - $print->export_svg(%export_params); + $sprint->export_svg; } else { - $print->process; - $print->export_gcode(%export_params); + $sprint->export_gcode; } - $print->status_cb(undef); + $sprint->status_cb(undef); Slic3r::GUI::warning_catcher($self)->($_) for @warnings; } - $process_dialog->Destroy; - undef $process_dialog; + $progress_dialog->Destroy; + undef $progress_dialog; my $message = "$input_file_basename was successfully sliced."; &Wx::wxTheApp->notify($message); Wx::MessageDialog->new($self, $message, 'Slicing Done!', wxOK | wxICON_INFORMATION)->ShowModal; }; - Slic3r::GUI::catch_error($self, sub { $process_dialog->Destroy if $process_dialog }); + Slic3r::GUI::catch_error($self, sub { $progress_dialog->Destroy if $progress_dialog }); } sub repair_stl { diff --git a/lib/Slic3r/Print/Simple.pm b/lib/Slic3r/Print/Simple.pm new file mode 100644 index 00000000..0bf497b7 --- /dev/null +++ b/lib/Slic3r/Print/Simple.pm @@ -0,0 +1,112 @@ +package Slic3r::Print::Simple; +use Moo; + +use Slic3r::Geometry qw(X Y); + +has '_print' => ( + is => 'ro', + default => sub { Slic3r::Print->new }, + handles => [qw(apply_config extruders expanded_output_filepath)], +); + +has 'duplicate' => ( + is => 'rw', + default => sub { 1 }, +); + +has 'scale' => ( + is => 'rw', + default => sub { 1 }, +); + +has 'rotate' => ( + is => 'rw', + default => sub { 0 }, +); + +has 'duplicate_grid' => ( + is => 'rw', + default => sub { [1,1] }, +); + +has 'status_cb' => ( + is => 'rw', + default => sub { sub {} }, +); + +has 'output_file' => ( + is => 'rw', +); + +sub set_model { + my ($self, $model) = @_; + + # make method idempotent so that the object is reusable + $self->_print->delete_all_objects; + + my $need_arrange = $model->has_objects_with_no_instances; + if ($need_arrange) { + # apply a default position to all objects not having one + foreach my $object (@{$model->objects}) { + $object->add_instance(offset => [0,0]) if !defined $object->instances; + } + } + + # apply scaling and rotation supplied from command line if any + foreach my $instance (map @{$_->instances}, @{$model->objects}) { + $instance->scaling_factor($instance->scaling_factor * $self->scale); + $instance->rotation($instance->rotation + $self->rotate); + } + # TODO: --scale --rotate, --duplicate* shouldn't be stored in config + + if ($self->duplicate_grid->[X] > 1 || $self->duplicate_grid->[Y] > 1) { + $model->duplicate_objects_grid($self->duplicate_grid, $self->_print->config->duplicate_distance); + } elsif ($need_arrange) { + $model->duplicate_objects($self->duplicate, $self->_print->config->min_object_distance); + } elsif ($self->duplicate > 1) { + # if all input objects have defined position(s) apply duplication to the whole model + $model->duplicate($self->duplicate, $self->_print->config->min_object_distance); + } + $model->center_instances_around_point($self->_print->config->print_center); + + foreach my $model_object (@{$model->objects}) { + $self->_print->auto_assign_extruders($model_object); + $self->_print->add_model_object($model_object); + } +} + +sub _before_export { + my ($self) = @_; + + $self->_print->status_cb($self->status_cb); + $self->_print->validate; +} + +sub _after_export { + my ($self) = @_; + + $self->_print->status_cb(undef); +} + +sub export_gcode { + my ($self) = @_; + + $self->_before_export; + + $self->_print->process; + $self->_print->export_gcode(output_file => $self->output_file); + + $self->_after_export; +} + +sub export_svg { + my ($self) = @_; + + $self->_before_export; + + $self->_print->export_svg(output_file => $self->output_file); + + $self->_after_export; +} + +1; diff --git a/lib/Slic3r/Print/SupportMaterial.pm b/lib/Slic3r/Print/SupportMaterial.pm index 38949d22..0dae19e1 100644 --- a/lib/Slic3r/Print/SupportMaterial.pm +++ b/lib/Slic3r/Print/SupportMaterial.pm @@ -107,7 +107,7 @@ sub contact_area { } else { my $lower_layer = $object->layers->[$layer_id-1]; foreach my $layerm (@{$layer->regions}) { - my $fw = $layerm->perimeter_flow->scaled_width; + my $fw = $layerm->flow(FLOW_ROLE_PERIMETER)->scaled_width; my $diff; # If a threshold angle was specified, use a different logic for detecting overhangs. diff --git a/slic3r.pl b/slic3r.pl index beea8037..e62c22b3 100755 --- a/slic3r.pl +++ b/slic3r.pl @@ -12,7 +12,6 @@ use Getopt::Long qw(:config no_auto_abbrev); use List::Util qw(first); use POSIX qw(setlocale LC_NUMERIC); use Slic3r; -use Slic3r::Geometry qw(X Y); use Time::HiRes qw(gettimeofday tv_interval); $|++; @@ -122,55 +121,32 @@ if (@ARGV) { # slicing from command line $model = Slic3r::Model->read_from_file($input_file); } - my $need_arrange = $model->has_objects_with_no_instances; - if ($need_arrange) { - # apply a default position to all objects not having one - foreach my $object (@{$model->objects}) { - $object->add_instance(offset => [0,0]) if !defined $object->instances; - } - } - - # apply scaling and rotation supplied from command line if any - foreach my $instance (map @{$_->instances}, @{$model->objects}) { - $instance->scaling_factor($instance->scaling_factor * $config->scale); - $instance->rotation($instance->rotation + $config->rotate); - } - # TODO: --scale --rotate, --duplicate* shouldn't be stored in config - - if ($config->duplicate_grid->[X] > 1 || $config->duplicate_grid->[Y] > 1) { - $model->duplicate_objects_grid($config->duplicate_grid, $config->duplicate_distance); - } elsif ($need_arrange) { - $model->duplicate_objects($config->duplicate, $config->min_object_distance); - } elsif ($config->duplicate > 1) { - # if all input objects have defined position(s) apply duplication to the whole model - $model->duplicate($config->duplicate, $config->min_object_distance); - } - $model->center_instances_around_point($config->print_center); - if ($opt{info}) { $model->print_info; next; } - my $print = Slic3r::Print->new( - status_cb => sub { + my $sprint = Slic3r::Print::Simple->new( + scale => $config->scale, + rotate => $config->rotate, + duplicate => $config->duplicate, + duplicate_grid => $config->duplicate_grid, + status_cb => sub { my ($percent, $message) = @_; printf "=> %s\n", $message; }, + output_file => $opt{output}, ); - $print->apply_config($config); - foreach my $model_object (@{$model->objects}) { - $print->auto_assign_extruders($model_object); - $print->add_model_object($model_object); - } + + $sprint->apply_config($config); + $sprint->set_model($model); undef $model; # free memory - $print->validate; + if ($opt{export_svg}) { - $print->export_svg(output_file => $opt{output}); + $sprint->export_svg; } else { my $t0 = [gettimeofday]; - $print->process; - $print->export_gcode(output_file => $opt{output}); + $sprint->export_gcode; # output some statistics { @@ -180,7 +156,7 @@ if (@ARGV) { # slicing from command line } print map sprintf("Filament required: %.1fmm (%.1fcm3)\n", $_->absolute_E, $_->extruded_volume/1000), - @{$print->extruders}; + @{$sprint->extruders}; } } } else {