From f9446b9c6e7b9269b7bebc5af79b1b732387f16f Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 26 Dec 2011 17:20:26 +0100 Subject: [PATCH] Cleanup the --output-filename-format implementation. #53 #137 --- README.markdown | 36 ++++++++++++++++++++------ lib/Slic3r/Config.pm | 10 +++++++- lib/Slic3r/GUI/SkeinPanel.pm | 6 ++--- lib/Slic3r/Skein.pm | 50 ++++++++++++++++++++++-------------- slic3r.pl | 17 ++++++------ 5 files changed, 79 insertions(+), 40 deletions(-) diff --git a/README.markdown b/README.markdown index 2d9fb5bc..ba9b4134 100644 --- a/README.markdown +++ b/README.markdown @@ -81,13 +81,15 @@ The author is Alessandro Ranellucci (me). --help Output this usage screen and exit --save Save configuration to the specified file --load Load configuration from the specified file - -o File name to output gcode to (default: --output) - + -o, --output File to output gcode to (by default, the file will be saved + into the same directory as the input file using the + --output-filename-format to generate the filename) + Output options: - --output Output file name format (default: [input_filename_base].gcode) - examples: - [input_filename_base]_h[layer_height]_p[perimeters]_s[solid_layers].gcode - [input_filename]_center[print_center]_layer[layer_height].gcode + --output-filament-format + Output file name format; all config options enclosed in brackets + will be replaced by their values, as well as [input_filename_base] + and [input_filename] (default: [input_filename_base].gcode) Printer options: --nozzle-diameter Diameter of nozzle in mm (default: 0.5) @@ -160,10 +162,10 @@ The author is Alessandro Ranellucci (me). --retract-lift Lift Z by the given distance in mm when retracting (default: 0) Skirt options: - --skirts Number of skirts to draw (default: 1) + --skirts Number of skirts to draw (0+, default: 1) --skirt-distance Distance in mm between innermost skirt and object (default: 6) - --skirt-height Height of skirts to draw (expressed in layers, default: 1) + --skirt-height Height of skirts to draw (expressed in layers, 0+, default: 1) Transform options: --scale Factor for scaling input object (default: 1) @@ -202,3 +204,21 @@ you like). On Mac, the executable has a path like this: /Applications/Slic3r.app/Contents/MacOS/slic3r + +## How can I specify a custom filename format for output G-code files? + +You can specify a filename format by using any of the config options. +Just enclose them in square brackets, and Slic3r will replace them upon +exporting. +The additional `[input_filename]` and `[input_filename_base]` options will +be replaced by the input file name (in the second case, the .stl extension +is stripped). + +The default format is `[input_filename_base].gcode`, meaning that if you slice +a *foo.stl* file, the output will be saved to *foo.gcode*. + +See below for more complex examples: + + [input_filename_base]_h[layer_height]_p[perimeters]_s[solid_layers].gcode + [input_filename]_center[print_center]_[layer_height]layers.gcode + diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index d984c422..eecd4e83 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -10,7 +10,7 @@ our $Options = { # output options 'output_filename_format' => { label => 'Output filename format', - cli => 'output=s', + cli => 'output-filename-format=s', type => 's', }, @@ -296,6 +296,14 @@ sub set { ${"Slic3r::$opt_key"} = $value; } +sub serialize { + my $class = @_ == 2 ? shift : undef; + my ($opt_key) = @_; + return $Options->{$opt_key}{serialize} + ? $Options->{$opt_key}{serialize}->(get($opt_key)) + : get($opt_key); +} + sub save { my $class = shift; my ($file) = @_; diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index d455b303..4411a6d5 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -154,6 +154,7 @@ sub do_slice { my $skein = Slic3r::Skein->new( input_file => $input_file, + output_file => $main::opt{output}, status_cb => sub { my ($percent, $message) = @_; if (&Wx::wxVERSION_STRING =~ / 2\.(8\.|9\.[2-9])/) { @@ -163,11 +164,8 @@ sub do_slice { ); # select output file - my $output_file = $main::opt{output_filename}; if ($params{save_as}) { - if (!$output_file) { - $output_file = $skein->get_output_filename($input_file); - } + my $output_file = $skein->expanded_output_filepath; my $dlg = Wx::FileDialog->new($self, 'Save gcode file as:', dirname($output_file), basename($output_file), $gcode_wildcard, wxFD_SAVE); return if $dlg->ShowModal != wxID_OK; diff --git a/lib/Slic3r/Skein.pm b/lib/Slic3r/Skein.pm index 919ba2c4..15da408e 100644 --- a/lib/Slic3r/Skein.pm +++ b/lib/Slic3r/Skein.pm @@ -1,12 +1,18 @@ package Slic3r::Skein; use Moo; +use File::Basename qw(basename fileparse); use Slic3r::Geometry qw(PI); use Time::HiRes qw(gettimeofday tv_interval); use XXX; +# full path (relative or absolute) to the input file has 'input_file' => (is => 'ro', required => 1); -has 'output_file' => (is => 'rw', required => 0); + +# full path (relative or absolute) to the output file; it may contain +# formatting variables like [layer_height] etc. +has 'output_file' => (is => 'rw', required => 0); + has 'status_cb' => (is => 'rw', required => 0, default => sub { sub {} }); has 'processing_time' => (is => 'rw', required => 0); @@ -83,11 +89,7 @@ sub go { # output everything to a GCODE file $self->status_cb->(90, "Exporting GCODE..."); - if ($self->output_file) { - $print->export_gcode($self->output_file); - } else { - $print->export_gcode($self->get_output_filename); - } + $print->export_gcode($self->expanded_output_filepath); # output some statistics $self->processing_time(tv_interval($t0)); @@ -100,20 +102,30 @@ sub go { $print->total_extrusion_length, $print->total_extrusion_volume; } -sub get_output_filename { +# this method will return the value of $self->output_file after expanding its +# format variables with their values +sub expanded_output_filepath { my $self = shift; - my $filename = Slic3r::Config->get('output_filename_format'); - my %opts = %$Slic3r::Config::Options; - my $input = $self->input_file; - # these pseudo-options are the path and filename, without and with extension, of the input file - $filename =~ s/\[input_filename\]/$input/g; - $input =~ s/\.stl$//i; - $filename =~ s/\[input_filename_base\]/$input/g; - # make a list of options - my $options = join '|', keys %$Slic3r::Config::Options; - # use that list to search and replace option names with option values - $filename =~ s/\[($options)\]/Slic3r::Config->get($1)/eg; - return $filename; + + my $path = $self->output_file; + + # if no explicit output file was defined, we take the input + # file directory and append the specified filename format + $path ||= (fileparse($self->input_file))[1] . $Slic3r::output_filename_format; + + my $input_basename = basename($self->input_file); + $path =~ s/\[input_filename\]/$input_basename/g; + $input_basename =~ s/\.stl$//i; + $path =~ s/\[input_filename_base\]/$input_basename/g; + + # build a regexp to match the available options + my $options = join '|', + grep !$Slic3r::Config::Options->{$_}{multiline}, + keys %$Slic3r::Config::Options; + + # use that regexp to search and replace option names with option values + $path =~ s/\[($options)\]/Slic3r::Config->serialize($1)/eg; + return $path; } 1; diff --git a/slic3r.pl b/slic3r.pl index c81cfbcb..e81b9592 100755 --- a/slic3r.pl +++ b/slic3r.pl @@ -20,8 +20,7 @@ my %cli_options = (); 'help' => sub { usage() }, 'debug' => \$Slic3r::debug, - - 'o=s' => \$opt{output_filename}, + 'o|output=s' => \$opt{output}, 'save=s' => \$opt{save}, 'load=s' => \$opt{load}, @@ -71,7 +70,7 @@ if ($ARGV[0]) { my $skein = Slic3r::Skein->new( input_file => $input_file, - output_file => $opt{output_filename}, + output_file => $opt{output}, ); $skein->go; @@ -91,13 +90,15 @@ Usage: slic3r.pl [ OPTIONS ] file.stl --help Output this usage screen and exit --save Save configuration to the specified file --load Load configuration from the specified file - -o File name to output gcode to (default: --output) + -o, --output File to output gcode to (by default, the file will be saved + into the same directory as the input file using the + --output-filename-format to generate the filename) Output options: - --output Output file name format (default: [input_filename_base].gcode) - examples: - [input_filename_base]_h[layer_height]_p[perimeters]_s[solid_layers].gcode - [input_filename]_center[print_center]_layer[layer_height].gcode + --output-filament-format + Output file name format; all config options enclosed in brackets + will be replaced by their values, as well as [input_filename_base] + and [input_filename] (default: $Slic3r::output_filename_format) Printer options: --nozzle-diameter Diameter of nozzle in mm (default: $Slic3r::nozzle_diameter)