diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index 69a63ed5d..eff8ae4b2 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -440,7 +440,7 @@ sub quick_slice { if ($params{reslice}) { $output_file = $qs_last_output_file if defined $qs_last_output_file; } elsif ($params{save_as}) { - $output_file = $sprint->expanded_output_filepath; + $output_file = $sprint->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:', wxTheApp->output_path(dirname($output_file)), diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 967d0f1e9..a1ef237d4 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -1298,9 +1298,9 @@ sub export_gcode { # select output file if ($output_file) { - $self->{export_gcode_output_file} = $self->{print}->expanded_output_filepath($output_file); + $self->{export_gcode_output_file} = $self->{print}->output_filepath($output_file); } else { - my $default_output_file = $self->{print}->expanded_output_filepath($main::opt{output}); + my $default_output_file = $self->{print}->output_filepath($main::opt{output}); my $dlg = Wx::FileDialog->new($self, 'Save G-code file as:', wxTheApp->output_path(dirname($default_output_file)), basename($default_output_file), &Slic3r::GUI::FILE_WILDCARDS->{gcode}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if ($dlg->ShowModal != wxID_OK) { @@ -1571,7 +1571,7 @@ sub _get_export_file { my $output_file = $main::opt{output}; { - $output_file = $self->{print}->expanded_output_filepath($output_file); + $output_file = $self->{print}->output_filepath($output_file); $output_file =~ s/\.gcode$/$suffix/i; my $dlg = Wx::FileDialog->new($self, "Save $format file as:", dirname($output_file), basename($output_file), &Slic3r::GUI::MODEL_WILDCARD, wxFD_SAVE | wxFD_OVERWRITE_PROMPT); diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index e18fa6abf..adef54113 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -77,7 +77,7 @@ sub export_gcode { $self->process; # output everything to a G-code file - my $output_file = $self->expanded_output_filepath($params{output_file}); + my $output_file = $self->output_filepath($params{output_file} // ''); $self->status_cb->(90, "Exporting G-code" . ($output_file ? " to $output_file" : "")); $self->write_gcode($params{output_fh} || $output_file); @@ -105,7 +105,7 @@ sub export_svg { my $fh = $params{output_fh}; if (!$fh) { - my $output_file = $self->expanded_output_filepath($params{output_file}); + my $output_file = $self->output_filepath($params{output_file}); $output_file =~ s/\.gcode$/.svg/i; Slic3r::open(\$fh, ">", $output_file) or die "Failed to open $output_file for writing\n"; print "Exporting to $output_file..." unless $params{quiet}; @@ -326,45 +326,6 @@ sub write_gcode { } } -# this method will return the supplied input file path after expanding its -# format variables with their values -sub expanded_output_filepath { - my $self = shift; - my ($path) = @_; - - return undef if !@{$self->objects}; - my $input_file = first { defined $_ } map $_->model_object->input_file, @{$self->objects}; - return undef if !defined $input_file; - - my $filename = my $filename_base = basename($input_file); - $filename_base =~ s/\.[^.]+$//; # without suffix - - # set filename in placeholder parser so that it's available also in custom G-code - $self->placeholder_parser->set(input_filename => $filename); - $self->placeholder_parser->set(input_filename_base => $filename_base); - - # set other variables from model object - $self->placeholder_parser->set_multiple( - scale => [ map $_->model_object->instances->[0]->scaling_factor * 100 . "%", @{$self->objects} ], - ); - - if ($path && -d $path) { - # if output path is an existing directory, we take that and append - # the specified filename format - $path = File::Spec->join($path, $self->config->output_filename_format); - } elsif (!$path) { - # if no explicit output file was defined, we take the input - # file directory and append the specified filename format - $path = (fileparse($input_file))[1] . $self->config->output_filename_format; - } else { - # path is a full path to a file so we use it as it is - } - - # make sure we use an up-to-date timestamp - $self->placeholder_parser->update_timestamp; - return $self->placeholder_parser->process($path); -} - # Wrapper around the C++ Slic3r::Print::validate() # to produce a Perl exception without a hang-up on some Strawberry perls. sub validate diff --git a/lib/Slic3r/Print/Simple.pm b/lib/Slic3r/Print/Simple.pm index 3771bfe4a..4fe3eb820 100644 --- a/lib/Slic3r/Print/Simple.pm +++ b/lib/Slic3r/Print/Simple.pm @@ -13,7 +13,7 @@ use Slic3r::Geometry qw(X Y); has '_print' => ( is => 'ro', default => sub { Slic3r::Print->new }, - handles => [qw(apply_config extruders expanded_output_filepath + handles => [qw(apply_config extruders output_filepath total_used_filament total_extruded_volume placeholder_parser process)], ); diff --git a/t/custom_gcode.t b/t/custom_gcode.t index 9d68d1eed..f6bfd366f 100644 --- a/t/custom_gcode.t +++ b/t/custom_gcode.t @@ -59,7 +59,7 @@ use Slic3r::Test; $config->set('start_gcode', "TRAVEL:[travel_speed] HEIGHT:[layer_height]\n"); my $print = Slic3r::Test::init_print('20mm_cube', config => $config); - my $output_file = $print->print->expanded_output_filepath; + my $output_file = $print->print->output_filepath; my ($t, $h) = map $config->$_, qw(travel_speed layer_height); ok $output_file =~ /ts_${t}_/, 'print config options are replaced in output filename'; ok $output_file =~ /lh_$h\./, 'region config options are replaced in output filename'; diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 434535ac9..4c14599c9 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -998,4 +998,34 @@ void Print::_make_skirt() this->skirt.reverse(); } +std::string +Print::output_filename() +{ + this->placeholder_parser.update_timestamp(); + return this->placeholder_parser.process(this->config.output_filename_format.value); +} + +std::string +Print::output_filepath(const std::string &path) +{ + // if we were supplied no path, generate an automatic one based on our first object's input file + if (path.empty()) { + // get the first input file name + std::string input_file; + FOREACH_OBJECT(this, object) { + input_file = (*object)->model_object()->input_file; + if (!input_file.empty()) break; + } + return (boost::filesystem::path(input_file).parent_path() / this->output_filename()).string(); + } + + // if we were supplied a directory, use it and append our automatically generated filename + boost::filesystem::path p(path); + if (boost::filesystem::is_directory(p)) + return (p / this->output_filename()).string(); + + // if we were supplied a file which is not a directory, use it + return path; +} + } diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp index f18432da6..233290854 100644 --- a/xs/src/libslic3r/Print.hpp +++ b/xs/src/libslic3r/Print.hpp @@ -253,6 +253,8 @@ class Print void auto_assign_extruders(ModelObject* model_object) const; void _make_skirt(); + std::string output_filename(); + std::string output_filepath(const std::string &path); private: void clear_regions(); diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index 8651469cd..1931243e1 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -257,6 +257,8 @@ _constant() double max_allowed_layer_height() const; bool has_support_material() const; void auto_assign_extruders(ModelObject* model_object); + std::string output_filename(); + std::string output_filepath(std::string path = ""); void add_model_object(ModelObject* model_object, int idx = -1); bool apply_config(DynamicPrintConfig* config)