Refactoring: new Slic3r::Print::Simple class for non-interactive slicing (used in CLI and Quick Slice)
This commit is contained in:
parent
5bf0942f45
commit
385e0e0974
5 changed files with 151 additions and 88 deletions
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
112
lib/Slic3r/Print/Simple.pm
Normal file
112
lib/Slic3r/Print/Simple.pm
Normal file
|
@ -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;
|
|
@ -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.
|
||||
|
|
52
slic3r.pl
52
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 {
|
||||
|
|
Loading…
Reference in a new issue