GUI
This commit is contained in:
parent
a311220c19
commit
f2f9178e07
4
Build.PL
4
Build.PL
@ -8,11 +8,13 @@ my $build = Module::Build->new(
|
|||||||
license => 'perl',
|
license => 'perl',
|
||||||
requires => {
|
requires => {
|
||||||
'CAD::Format::STL' => '0',
|
'CAD::Format::STL' => '0',
|
||||||
|
'File::Basename' => '0',
|
||||||
'Getopt::Long' => '0',
|
'Getopt::Long' => '0',
|
||||||
'Math::Clipper' => '1.00',
|
'Math::Clipper' => '1.01',
|
||||||
'Math::Geometry::Planar' => '0',
|
'Math::Geometry::Planar' => '0',
|
||||||
'Moo' => '0',
|
'Moo' => '0',
|
||||||
'Time::HiRes' => '0',
|
'Time::HiRes' => '0',
|
||||||
|
'XXX' => '0',
|
||||||
},
|
},
|
||||||
build_requires => {
|
build_requires => {
|
||||||
'Test::More' => '0.10',
|
'Test::More' => '0.10',
|
||||||
|
@ -63,8 +63,12 @@ Download the package, open a terminal and cd to its directory. Then type:
|
|||||||
|
|
||||||
perl Build.PL
|
perl Build.PL
|
||||||
|
|
||||||
This will install any required dependency. If you want to install slic3r.pl
|
This will install any required dependency. If you want the GUI, you should
|
||||||
in your system path, type this as root:
|
also install Wx using the following command (as root):
|
||||||
|
|
||||||
|
cpan Wx
|
||||||
|
|
||||||
|
If you want to install slic3r.pl in your system path, type this as root:
|
||||||
|
|
||||||
./Build install
|
./Build install
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ sub debugf {
|
|||||||
printf @_ if $debug;
|
printf @_ if $debug;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use Slic3r::Config;
|
||||||
use Slic3r::Extruder;
|
use Slic3r::Extruder;
|
||||||
use Slic3r::ExtrusionLoop;
|
use Slic3r::ExtrusionLoop;
|
||||||
use Slic3r::ExtrusionPath;
|
use Slic3r::ExtrusionPath;
|
||||||
@ -21,6 +22,7 @@ use Slic3r::Point;
|
|||||||
use Slic3r::Polyline;
|
use Slic3r::Polyline;
|
||||||
use Slic3r::Polyline::Closed;
|
use Slic3r::Polyline::Closed;
|
||||||
use Slic3r::Print;
|
use Slic3r::Print;
|
||||||
|
use Slic3r::Skein;
|
||||||
use Slic3r::STL;
|
use Slic3r::STL;
|
||||||
use Slic3r::Surface;
|
use Slic3r::Surface;
|
||||||
use Slic3r::Surface::Collection;
|
use Slic3r::Surface::Collection;
|
||||||
|
72
lib/Slic3r/Config.pm
Normal file
72
lib/Slic3r/Config.pm
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package Slic3r::Config;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use constant PI => 4 * atan2(1, 1);
|
||||||
|
|
||||||
|
sub validate {
|
||||||
|
my $class = shift;
|
||||||
|
|
||||||
|
# --layer-height
|
||||||
|
die "Invalid value for --layer-height\n"
|
||||||
|
if $Slic3r::layer_height <= 0;
|
||||||
|
die "--layer-height must be a multiple of print resolution\n"
|
||||||
|
if $Slic3r::layer_height / $Slic3r::resolution % 1 != 0;
|
||||||
|
|
||||||
|
# --filament-diameter
|
||||||
|
die "Invalid value for --filament-diameter\n"
|
||||||
|
if $Slic3r::filament_diameter < 1;
|
||||||
|
|
||||||
|
# --nozzle-diameter
|
||||||
|
die "Invalid value for --nozzle-diameter\n"
|
||||||
|
if $Slic3r::nozzle_diameter < 0;
|
||||||
|
die "--layer-height can't be greater than --nozzle-diameter\n"
|
||||||
|
if $Slic3r::layer_height > $Slic3r::nozzle_diameter;
|
||||||
|
$Slic3r::flow_width = ($Slic3r::nozzle_diameter**2)
|
||||||
|
* $Slic3r::thickness_ratio * PI / (4 * $Slic3r::layer_height);
|
||||||
|
|
||||||
|
my $max_flow_width = $Slic3r::layer_height + $Slic3r::nozzle_diameter;
|
||||||
|
if ($Slic3r::flow_width > $max_flow_width) {
|
||||||
|
$Slic3r::thickness_ratio = $max_flow_width / $Slic3r::flow_width;
|
||||||
|
$Slic3r::flow_width = $max_flow_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
Slic3r::debugf "Flow width = $Slic3r::flow_width\n";
|
||||||
|
|
||||||
|
# --perimeters
|
||||||
|
die "Invalid value for --perimeters\n"
|
||||||
|
if $Slic3r::perimeter_offsets < 1;
|
||||||
|
|
||||||
|
# --solid-layers
|
||||||
|
die "Invalid value for --solid-layers\n"
|
||||||
|
if $Slic3r::solid_layers < 1;
|
||||||
|
|
||||||
|
# --print-center
|
||||||
|
die "Invalid value for --print-center\n"
|
||||||
|
if !ref $Slic3r::print_center
|
||||||
|
&& (!$Slic3r::print_center || $Slic3r::print_center !~ /^\d+,\d+$/);
|
||||||
|
$Slic3r::print_center = [ split /,/, $Slic3r::print_center ]
|
||||||
|
if !ref $Slic3r::print_center;
|
||||||
|
|
||||||
|
# --fill-density
|
||||||
|
die "Invalid value for --fill-density\n"
|
||||||
|
if $Slic3r::fill_density < 0 || $Slic3r::fill_density > 1;
|
||||||
|
|
||||||
|
# --scale
|
||||||
|
die "Invalid value for --scale\n"
|
||||||
|
if $Slic3r::scale <= 0;
|
||||||
|
|
||||||
|
# --multiply-x
|
||||||
|
die "Invalid value for --multiply-x\n"
|
||||||
|
if $Slic3r::multiply_x < 1;
|
||||||
|
|
||||||
|
# --multiply-y
|
||||||
|
die "Invalid value for --multiply-y\n"
|
||||||
|
if $Slic3r::multiply_y < 1;
|
||||||
|
|
||||||
|
# --multiply-distance
|
||||||
|
die "Invalid value for --multiply-distance\n"
|
||||||
|
if $Slic3r::multiply_distance < 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
44
lib/Slic3r/GUI.pm
Normal file
44
lib/Slic3r/GUI.pm
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package Slic3r::GUI;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use Slic3r::GUI::OptionsGroup;
|
||||||
|
use Slic3r::GUI::SkeinPanel;
|
||||||
|
|
||||||
|
use Wx qw(:sizer :frame wxID_EXIT wxID_ABOUT);
|
||||||
|
use Wx::Event qw(EVT_MENU);
|
||||||
|
use base 'Wx::App';
|
||||||
|
|
||||||
|
sub OnInit {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
#$self->SetIcon(Wx::Icon->new("path/to/my/icon.gif", wxBITMAP_TYPE_GIF) );
|
||||||
|
|
||||||
|
my $frame = Wx::Frame->new( undef, -1, 'Slic3r', [-1, -1], Wx::wxDefaultSize,
|
||||||
|
wxDEFAULT_FRAME_STYLE ^ (wxRESIZE_BORDER | wxMAXIMIZE_BOX) );
|
||||||
|
|
||||||
|
# menubar
|
||||||
|
my $menubar = Wx::MenuBar->new;
|
||||||
|
$frame->SetMenuBar($menubar);
|
||||||
|
EVT_MENU($frame, wxID_EXIT, sub {$_[0]->Close(1)});
|
||||||
|
EVT_MENU($frame, wxID_ABOUT, \&About);
|
||||||
|
|
||||||
|
my $panel = Slic3r::GUI::SkeinPanel->new($frame);
|
||||||
|
my $box = Wx::BoxSizer->new(wxVERTICAL);
|
||||||
|
$box->Add($panel, 0, wxALL, 20);
|
||||||
|
|
||||||
|
$frame->SetSizerAndFit($box);
|
||||||
|
$frame->Show;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub About {
|
||||||
|
my $frame = shift;
|
||||||
|
|
||||||
|
my $info = Wx::AboutDialogInfo->new;
|
||||||
|
$info->SetName('Slic3r');
|
||||||
|
$info->AddDeveloper('Alessandro Ranellucci');
|
||||||
|
|
||||||
|
Wx::AboutBox($info);
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
50
lib/Slic3r/GUI/OptionsGroup.pm
Normal file
50
lib/Slic3r/GUI/OptionsGroup.pm
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package Slic3r::GUI::OptionsGroup;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use Wx qw(:sizer);
|
||||||
|
use Wx::Event qw(EVT_TEXT EVT_CHECKBOX);
|
||||||
|
use base 'Wx::StaticBoxSizer';
|
||||||
|
|
||||||
|
sub new {
|
||||||
|
my $class = shift;
|
||||||
|
my ($parent, %p) = @_;
|
||||||
|
|
||||||
|
my $box = Wx::StaticBox->new($parent, -1, $p{title});
|
||||||
|
my $self = $class->SUPER::new($box, wxVERTICAL);
|
||||||
|
|
||||||
|
my $grid_sizer = Wx::FlexGridSizer->new(scalar(@{$p{options}}), 2, 2, 0);
|
||||||
|
|
||||||
|
foreach my $opt (@{$p{options}}) {
|
||||||
|
my $label = Wx::StaticText->new($parent, -1, "$opt->{label}:", Wx::wxDefaultPosition, [180,-1]);
|
||||||
|
my $field;
|
||||||
|
if ($opt->{type} =~ /^(i|f)$/) {
|
||||||
|
$field = Wx::TextCtrl->new($parent, -1, ${$opt->{value}});
|
||||||
|
EVT_TEXT($parent, $field, sub { ${$opt->{value}} = $field->GetValue });
|
||||||
|
} elsif ($opt->{type} eq 'bool') {
|
||||||
|
$field = Wx::CheckBox->new($parent, -1, "");
|
||||||
|
$field->SetValue(${$opt->{value}});
|
||||||
|
EVT_TEXT($parent, $field, sub { ${$opt->{value}} = $field->GetValue });
|
||||||
|
} elsif ($opt->{type} eq 'point') {
|
||||||
|
$field = Wx::BoxSizer->new(wxHORIZONTAL);
|
||||||
|
my $field_size = Wx::Size->new(40, -1);
|
||||||
|
$field->Add($_) for (
|
||||||
|
Wx::StaticText->new($parent, -1, "x:"),
|
||||||
|
my $x_field = Wx::TextCtrl->new($parent, -1, ${$opt->{value}}->[0], Wx::wxDefaultPosition, $field_size),
|
||||||
|
Wx::StaticText->new($parent, -1, " y:"),
|
||||||
|
my $y_field = Wx::TextCtrl->new($parent, -1, ${$opt->{value}}->[1], Wx::wxDefaultPosition, $field_size),
|
||||||
|
);
|
||||||
|
EVT_TEXT($parent, $x_field, sub { ${$opt->{value}}->[0] = $x_field->GetValue });
|
||||||
|
EVT_TEXT($parent, $y_field, sub { ${$opt->{value}}->[1] = $y_field->GetValue });
|
||||||
|
} else {
|
||||||
|
die "Unsupported option type: " . $opt->{type};
|
||||||
|
}
|
||||||
|
$grid_sizer->Add($_) for $label, $field;
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->Add($grid_sizer, 0, wxEXPAND);
|
||||||
|
|
||||||
|
return $self;
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
255
lib/Slic3r/GUI/SkeinPanel.pm
Normal file
255
lib/Slic3r/GUI/SkeinPanel.pm
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
package Slic3r::GUI::SkeinPanel;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use File::Basename qw(basename);
|
||||||
|
use Wx qw(:sizer :progressdialog wxOK wxICON_INFORMATION wxICON_ERROR wxID_OK wxFD_OPEN);
|
||||||
|
use Wx::Event qw(EVT_BUTTON);
|
||||||
|
use base 'Wx::Panel';
|
||||||
|
|
||||||
|
sub new {
|
||||||
|
my $class = shift;
|
||||||
|
my ($parent) = @_;
|
||||||
|
my $self = $class->SUPER::new($parent, -1);
|
||||||
|
|
||||||
|
my %panels = (
|
||||||
|
printer => Slic3r::GUI::OptionsGroup->new($self,
|
||||||
|
title => 'Printer',
|
||||||
|
options => [
|
||||||
|
{
|
||||||
|
label => 'Nozzle diameter',
|
||||||
|
value => \$Slic3r::nozzle_diameter,
|
||||||
|
type => 'f',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label => 'Print center',
|
||||||
|
value => \$Slic3r::print_center,
|
||||||
|
type => 'point',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label => 'Use relative E distances',
|
||||||
|
value => \$Slic3r::use_relative_e_distances,
|
||||||
|
type => 'bool',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label => 'Z offset',
|
||||||
|
value => \$Slic3r::z_offset,
|
||||||
|
type => 'f',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
filament => Slic3r::GUI::OptionsGroup->new($self,
|
||||||
|
title => 'Filament',
|
||||||
|
options => [
|
||||||
|
{
|
||||||
|
label => 'Diameter (mm)',
|
||||||
|
value => \$Slic3r::filament_diameter,
|
||||||
|
type => 'f',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label => 'Packing density (mm)',
|
||||||
|
value => \$Slic3r::filament_packing_density,
|
||||||
|
type => 'f',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
speed => Slic3r::GUI::OptionsGroup->new($self,
|
||||||
|
title => 'Speed',
|
||||||
|
options => [
|
||||||
|
{
|
||||||
|
label => 'Print feed rate (mm/s)',
|
||||||
|
value => \$Slic3r::print_feed_rate,
|
||||||
|
type => 'f',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label => 'Travel feed rate (mm/s)',
|
||||||
|
value => \$Slic3r::travel_feed_rate,
|
||||||
|
type => 'f',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label => 'Perimeter feed rate (mm/s)',
|
||||||
|
value => \$Slic3r::perimeter_feed_rate,
|
||||||
|
type => 'f',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label => 'Bottom layer ratio',
|
||||||
|
value => \$Slic3r::bottom_layer_speed_ratio,
|
||||||
|
type => 'f',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
accuracy => Slic3r::GUI::OptionsGroup->new($self,
|
||||||
|
title => 'Accuracy',
|
||||||
|
options => [
|
||||||
|
{
|
||||||
|
label => 'Layer height (mm)',
|
||||||
|
value => \$Slic3r::layer_height,
|
||||||
|
type => 'f',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
print => Slic3r::GUI::OptionsGroup->new($self,
|
||||||
|
title => 'Print settings',
|
||||||
|
options => [
|
||||||
|
{
|
||||||
|
label => 'Perimeters',
|
||||||
|
value => \$Slic3r::perimeter_offsets,
|
||||||
|
type => 'i',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label => 'Solid layers',
|
||||||
|
value => \$Slic3r::solid_layers,
|
||||||
|
type => 'i',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label => 'Fill density',
|
||||||
|
value => \$Slic3r::fill_density,
|
||||||
|
type => 'f',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label => 'Fill angle (°)',
|
||||||
|
value => \$Slic3r::fill_angle,
|
||||||
|
type => 'i',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label => 'Temperature (°C)',
|
||||||
|
value => \$Slic3r::temperature,
|
||||||
|
type => 'i',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
retract => Slic3r::GUI::OptionsGroup->new($self,
|
||||||
|
title => 'Retraction',
|
||||||
|
options => [
|
||||||
|
{
|
||||||
|
label => 'Length (mm)',
|
||||||
|
value => \$Slic3r::retract_length,
|
||||||
|
type => 'f',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label => 'Speed (mm/s)',
|
||||||
|
value => \$Slic3r::retract_speed,
|
||||||
|
type => 'i',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label => 'Extra length on restart (mm)',
|
||||||
|
value => \$Slic3r::retract_restart_extra,
|
||||||
|
type => 'f',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label => 'Minimum travel after retraction (mm)',
|
||||||
|
value => \$Slic3r::retract_before_travel,
|
||||||
|
type => 'f',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
skirt => Slic3r::GUI::OptionsGroup->new($self,
|
||||||
|
title => 'Skirt',
|
||||||
|
options => [
|
||||||
|
{
|
||||||
|
label => 'Loops',
|
||||||
|
value => \$Slic3r::skirts,
|
||||||
|
type => 'i',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label => 'Distance from object (mm)',
|
||||||
|
value => \$Slic3r::skirt_distance,
|
||||||
|
type => 'i',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
transform => Slic3r::GUI::OptionsGroup->new($self,
|
||||||
|
title => 'Transform',
|
||||||
|
options => [
|
||||||
|
{
|
||||||
|
label => 'Scale',
|
||||||
|
value => \$Slic3r::scale,
|
||||||
|
type => 'f',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label => 'Rotate (°)',
|
||||||
|
value => \$Slic3r::rotate,
|
||||||
|
type => 'i',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label => 'Multiply along X',
|
||||||
|
value => \$Slic3r::multiply_x,
|
||||||
|
type => 'i',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label => 'Multiply along Y',
|
||||||
|
value => \$Slic3r::multiply_y,
|
||||||
|
type => 'i',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label => 'Multiply distance',
|
||||||
|
value => \$Slic3r::multiply_distance,
|
||||||
|
type => 'i',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$panels{slice} = Wx::BoxSizer->new(wxVERTICAL);
|
||||||
|
$panels{slice}->Add(-1, 20); # empty space before button
|
||||||
|
my $slice_button = Wx::Button->new($self, -1, "Slice...");
|
||||||
|
$panels{slice}->Add($slice_button, 0, wxALIGN_CENTER);
|
||||||
|
EVT_BUTTON($self, $slice_button, \&do_slice);
|
||||||
|
|
||||||
|
my @cols = (
|
||||||
|
[qw(printer filament speed transform)], [qw(accuracy print retract skirt slice)],
|
||||||
|
);
|
||||||
|
|
||||||
|
my $sizer = Wx::BoxSizer->new(wxHORIZONTAL);
|
||||||
|
foreach my $col (@cols) {
|
||||||
|
my $vertical_sizer = Wx::BoxSizer->new(wxVERTICAL);
|
||||||
|
$vertical_sizer->Add($panels{$_}, 0, wxEXPAND | wxRIGHT, 10) for @$col;
|
||||||
|
$sizer->Add($vertical_sizer);
|
||||||
|
}
|
||||||
|
|
||||||
|
$sizer->SetSizeHints($self);
|
||||||
|
$self->SetSizer($sizer);
|
||||||
|
|
||||||
|
return $self;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub do_slice {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
eval {
|
||||||
|
# validate configuration
|
||||||
|
Slic3r::Config->validate;
|
||||||
|
|
||||||
|
# select input file
|
||||||
|
my $dialog = Wx::FileDialog->new($self, 'Choose a STL file to slice:', "", "", "*.stl", wxFD_OPEN);
|
||||||
|
return unless $dialog->ShowModal == wxID_OK;
|
||||||
|
my ($input_file) = $dialog->GetPaths;
|
||||||
|
my $input_file_basename = basename($input_file);
|
||||||
|
|
||||||
|
# show processbar dialog
|
||||||
|
my $process_dialog = Wx::ProgressDialog->new('Slicing...', "Processing $input_file_basename...",
|
||||||
|
100, $self, wxPD_APP_MODAL);
|
||||||
|
$process_dialog->Pulse;
|
||||||
|
my $skein = Slic3r::Skein->new(
|
||||||
|
input_file => $input_file,
|
||||||
|
);
|
||||||
|
$skein->go;
|
||||||
|
$process_dialog->Destroy;
|
||||||
|
|
||||||
|
Wx::MessageDialog->new($self, "$input_file_basename was successfully sliced.", 'Done!',
|
||||||
|
wxOK | wxICON_INFORMATION)->ShowModal;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (my $err = $@) {
|
||||||
|
Wx::MessageDialog->new($self, $err, 'Error', wxOK | wxICON_ERROR)->ShowModal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
34
lib/Slic3r/Skein.pm
Normal file
34
lib/Slic3r/Skein.pm
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package Slic3r::Skein;
|
||||||
|
use Moo;
|
||||||
|
|
||||||
|
use Time::HiRes qw(gettimeofday tv_interval);
|
||||||
|
|
||||||
|
has 'input_file' => (is => 'ro', required => 1);
|
||||||
|
has 'output_file' => (is => 'rw', required => 0);
|
||||||
|
|
||||||
|
sub go {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
die "Input file must have .stl extension\n"
|
||||||
|
if $self->input_file !~ /\.stl$/i;
|
||||||
|
|
||||||
|
my $t0 = [gettimeofday];
|
||||||
|
my $print = Slic3r::Print->new_from_stl($self->input_file);
|
||||||
|
$print->extrude_perimeters;
|
||||||
|
$print->remove_small_features;
|
||||||
|
$print->extrude_fills;
|
||||||
|
|
||||||
|
|
||||||
|
if (!$self->output_file) {
|
||||||
|
my $output_file = $self->input_file;
|
||||||
|
$output_file =~ s/\.stl$/.gcode/i;
|
||||||
|
$self->output_file($output_file);
|
||||||
|
}
|
||||||
|
$print->export_gcode($self->output_file);
|
||||||
|
|
||||||
|
my $processing_time = tv_interval($t0);
|
||||||
|
printf "Done. Process took %d minutes and %.3f seconds\n",
|
||||||
|
int($processing_time/60), $processing_time - int($processing_time/60)*60;
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
92
slic3r.pl
92
slic3r.pl
@ -10,11 +10,8 @@ BEGIN {
|
|||||||
|
|
||||||
use Getopt::Long;
|
use Getopt::Long;
|
||||||
use Slic3r;
|
use Slic3r;
|
||||||
use Time::HiRes qw(gettimeofday tv_interval);
|
|
||||||
use XXX;
|
use XXX;
|
||||||
|
|
||||||
use constant PI => 4 * atan2(1, 1);
|
|
||||||
|
|
||||||
my %opt;
|
my %opt;
|
||||||
GetOptions(
|
GetOptions(
|
||||||
'help' => sub { usage() },
|
'help' => sub { usage() },
|
||||||
@ -59,7 +56,7 @@ GetOptions(
|
|||||||
'skirt-distance=i' => \$Slic3r::skirt_distance,
|
'skirt-distance=i' => \$Slic3r::skirt_distance,
|
||||||
|
|
||||||
# transform options
|
# transform options
|
||||||
'scale=i' => \$Slic3r::scale,
|
'scale=f' => \$Slic3r::scale,
|
||||||
'rotate=i' => \$Slic3r::rotate,
|
'rotate=i' => \$Slic3r::rotate,
|
||||||
'multiply-x=i' => \$Slic3r::multiply_x,
|
'multiply-x=i' => \$Slic3r::multiply_x,
|
||||||
'multiply-y=i' => \$Slic3r::multiply_y,
|
'multiply-y=i' => \$Slic3r::multiply_y,
|
||||||
@ -67,89 +64,24 @@ GetOptions(
|
|||||||
);
|
);
|
||||||
|
|
||||||
# validate configuration
|
# validate configuration
|
||||||
{
|
Slic3r::Config->validate;
|
||||||
# --layer-height
|
|
||||||
die "Invalid value for --layer-height\n"
|
# start GUI
|
||||||
if $Slic3r::layer_height < 0;
|
if (!@ARGV && eval "require Slic3r::GUI; 1") {
|
||||||
die "--layer-height must be a multiple of print resolution\n"
|
Slic3r::GUI->new->MainLoop;
|
||||||
if $Slic3r::layer_height / $Slic3r::resolution % 1 != 0;
|
exit;
|
||||||
|
|
||||||
# --filament-diameter
|
|
||||||
die "Invalid value for --filament-diameter\n"
|
|
||||||
if $Slic3r::filament_diameter < 1;
|
|
||||||
|
|
||||||
# --nozzle-diameter
|
|
||||||
die "Invalid value for --nozzle-diameter\n"
|
|
||||||
if $Slic3r::nozzle_diameter < 0;
|
|
||||||
die "--layer-height can't be greater than --nozzle-diameter\n"
|
|
||||||
if $Slic3r::layer_height > $Slic3r::nozzle_diameter;
|
|
||||||
$Slic3r::flow_width = ($Slic3r::nozzle_diameter**2)
|
|
||||||
* $Slic3r::thickness_ratio * PI / (4 * $Slic3r::layer_height);
|
|
||||||
|
|
||||||
my $max_flow_width = $Slic3r::layer_height + $Slic3r::nozzle_diameter;
|
|
||||||
if ($Slic3r::flow_width > $max_flow_width) {
|
|
||||||
$Slic3r::thickness_ratio = $max_flow_width / $Slic3r::flow_width;
|
|
||||||
$Slic3r::flow_width = $max_flow_width;
|
|
||||||
}
|
|
||||||
|
|
||||||
Slic3r::debugf "Flow width = $Slic3r::flow_width\n";
|
|
||||||
|
|
||||||
# --perimeters
|
|
||||||
die "Invalid value for --perimeters\n"
|
|
||||||
if $Slic3r::perimeter_offsets < 1;
|
|
||||||
|
|
||||||
# --solid-layers
|
|
||||||
die "Invalid value for --solid-layers\n"
|
|
||||||
if $Slic3r::solid_layers < 1;
|
|
||||||
|
|
||||||
# --print-center
|
|
||||||
die "Invalid value for --print-center\n"
|
|
||||||
if !ref $Slic3r::print_center
|
|
||||||
&& (!$Slic3r::print_center || $Slic3r::print_center !~ /^\d+,\d+$/);
|
|
||||||
$Slic3r::print_center = [ split /,/, $Slic3r::print_center ]
|
|
||||||
if !ref $Slic3r::print_center;
|
|
||||||
|
|
||||||
# --fill-density
|
|
||||||
die "Invalid value for --fill-density\n"
|
|
||||||
if $Slic3r::fill_density < 0 || $Slic3r::fill_density > 1;
|
|
||||||
|
|
||||||
# --scale
|
|
||||||
die "Invalid value for --scale\n"
|
|
||||||
if $Slic3r::scale <= 0;
|
|
||||||
|
|
||||||
# --multiply-x
|
|
||||||
die "Invalid value for --multiply-x\n"
|
|
||||||
if $Slic3r::multiply_x < 1;
|
|
||||||
|
|
||||||
# --multiply-y
|
|
||||||
die "Invalid value for --multiply-y\n"
|
|
||||||
if $Slic3r::multiply_y < 1;
|
|
||||||
|
|
||||||
# --multiply-distance
|
|
||||||
die "Invalid value for --multiply-distance\n"
|
|
||||||
if $Slic3r::multiply_distance < 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
my $action = 'skein';
|
my $action = 'skein';
|
||||||
|
|
||||||
if ($action eq 'skein') {
|
if ($action eq 'skein') {
|
||||||
my $input_file = $ARGV[0] or usage(1);
|
my $input_file = $ARGV[0] or usage(1);
|
||||||
die "Input file must have .stl extension\n"
|
|
||||||
if $input_file !~ /\.stl$/i;
|
|
||||||
|
|
||||||
my $t0 = [gettimeofday];
|
my $skein = Slic3r::Skein->new(
|
||||||
my $print = Slic3r::Print->new_from_stl($input_file);
|
input_file => $input_file,
|
||||||
$print->extrude_perimeters;
|
output_file => $opt{output},
|
||||||
$print->remove_small_features;
|
);
|
||||||
$print->extrude_fills;
|
$skein->go;
|
||||||
|
|
||||||
my $output_file = $input_file;
|
|
||||||
$output_file =~ s/\.stl$/.gcode/i;
|
|
||||||
$print->export_gcode($opt{output} || $output_file);
|
|
||||||
|
|
||||||
my $processing_time = tv_interval($t0);
|
|
||||||
printf "Done. Process took %d minutes and %.3f seconds\n",
|
|
||||||
int($processing_time/60), $processing_time - int($processing_time/60)*60;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub usage {
|
sub usage {
|
||||||
|
Loading…
Reference in New Issue
Block a user