Changed the G-code export and send to OctoPrint GUI code

to store the G-code next to the project file if it exists,
and to process the project name with the PlaceholderParser.
This commit is contained in:
bubnikv 2019-05-17 16:27:00 +02:00
parent e358dd9c01
commit 04397c7948
10 changed files with 55 additions and 31 deletions

View File

@ -729,7 +729,7 @@ void GCode::_do_export(Print &print, FILE *file)
// Prepare the helper object for replacing placeholders in custom G-code and output filename.
m_placeholder_parser = print.placeholder_parser();
m_placeholder_parser.update_timestamp();
print.update_object_placeholders(m_placeholder_parser.config_writable());
print.update_object_placeholders(m_placeholder_parser.config_writable(), ".gcode");
// Get optimal tool ordering to minimize tool switches of a multi-exruder print.
// For a print by objects, find the 1st printing object.

View File

@ -1875,12 +1875,12 @@ int Print::get_extruder(const ExtrusionEntityCollection& fill, const PrintRegion
// Generate a recommended G-code output file name based on the format template, default extension, and template parameters
// (timestamps, object placeholders derived from the model, current placeholder prameters and print statistics.
// Use the final print statistics if available, or just keep the print statistics placeholders if not available yet (before G-code is finalized).
std::string Print::output_filename() const
std::string Print::output_filename(const std::string &filename_base) const
{
// Set the placeholders for the data know first after the G-code export is finished.
// These values will be just propagated into the output file name.
DynamicConfig config = this->finished() ? this->print_statistics().config() : this->print_statistics().placeholders();
return this->PrintBase::output_filename(m_config.output_filename_format.value, "gcode", &config);
return this->PrintBase::output_filename(m_config.output_filename_format.value, ".gcode", filename_base, &config);
}
/*
// Shorten the dhms time by removing the seconds, rounding the dhm to full minutes

View File

@ -351,7 +351,7 @@ public:
bool has_wipe_tower() const;
const WipeTowerData& wipe_tower_data() const { return m_wipe_tower_data; }
std::string output_filename() const override;
std::string output_filename(const std::string &filename_base = std::string()) const override;
// Accessed by SupportMaterial
const PrintRegion* get_region(size_t idx) const { return m_regions[idx]; }

View File

@ -15,7 +15,7 @@ namespace Slic3r
size_t PrintStateBase::g_last_timestamp = 0;
// Update "scale", "input_filename", "input_filename_base" placeholders from the current m_objects.
void PrintBase::update_object_placeholders(DynamicConfig &config) const
void PrintBase::update_object_placeholders(DynamicConfig &config, const std::string &default_ext) const
{
// get the first input file name
std::string input_file;
@ -40,25 +40,29 @@ void PrintBase::update_object_placeholders(DynamicConfig &config) const
config.set_key_value("year", new ConfigOptionStrings(v_scale));
if (! input_file.empty()) {
// get basename with and without suffix
const std::string input_basename = boost::filesystem::path(input_file).filename().string();
config.set_key_value("input_filename", new ConfigOptionString(input_basename));
const std::string input_basename_base = input_basename.substr(0, input_basename.find_last_of("."));
config.set_key_value("input_filename_base", new ConfigOptionString(input_basename_base));
const std::string input_filename = boost::filesystem::path(input_file).filename().string();
const std::string input_filename_base = input_filename.substr(0, input_filename.find_last_of("."));
config.set_key_value("input_filename", new ConfigOptionString(input_filename_base + default_ext));
config.set_key_value("input_filename_base", new ConfigOptionString(input_filename_base));
}
}
// Generate an output file name based on the format template, default extension, and template parameters
// (timestamps, object placeholders derived from the model, current placeholder prameters, print statistics - config_override)
std::string PrintBase::output_filename(const std::string &format, const std::string &default_ext, const DynamicConfig *config_override) const
std::string PrintBase::output_filename(const std::string &format, const std::string &default_ext, const std::string &filename_base, const DynamicConfig *config_override) const
{
DynamicConfig cfg;
if (config_override != nullptr)
cfg = *config_override;
PlaceholderParser::update_timestamp(cfg);
this->update_object_placeholders(cfg);
this->update_object_placeholders(cfg, default_ext);
if (! filename_base.empty()) {
cfg.set_key_value("input_filename", new ConfigOptionString(filename_base + default_ext));
cfg.set_key_value("input_filename_base", new ConfigOptionString(filename_base));
}
try {
boost::filesystem::path filename = format.empty() ?
cfg.opt_string("input_filename_base") + "." + default_ext :
cfg.opt_string("input_filename_base") + default_ext :
this->placeholder_parser().process(format, 0, &cfg);
if (filename.extension().empty())
filename = boost::filesystem::change_extension(filename, default_ext);
@ -68,17 +72,17 @@ std::string PrintBase::output_filename(const std::string &format, const std::str
}
}
std::string PrintBase::output_filepath(const std::string &path) const
std::string PrintBase::output_filepath(const std::string &path, const std::string &filename_base) const
{
// 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
return (boost::filesystem::path(m_model.propose_export_file_name_and_path()).parent_path() / this->output_filename()).make_preferred().string();
return (boost::filesystem::path(m_model.propose_export_file_name_and_path()).parent_path() / this->output_filename(filename_base)).make_preferred().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()).make_preferred().string();
return (p / this->output_filename(filename_base)).make_preferred().string();
// if we were supplied a file which is not a directory, use it
return path;

View File

@ -318,8 +318,10 @@ public:
const PlaceholderParser& placeholder_parser() const { return m_placeholder_parser; }
PlaceholderParser& placeholder_parser() { return m_placeholder_parser; }
virtual std::string output_filename() const = 0;
std::string output_filepath(const std::string &path) const;
virtual std::string output_filename(const std::string &filename_base = std::string()) const = 0;
// If the filename_base is set, it is used as the input for the template processing. In that case the path is expected to be the directory (may be empty).
// If filename_set is empty, than the path may be a file or directory. If it is a file, then the macro will not be processed.
std::string output_filepath(const std::string &path, const std::string &filename_base = std::string()) const;
protected:
friend class PrintObjectBase;
@ -334,9 +336,9 @@ protected:
void throw_if_canceled() const { if (m_cancel_status) throw CanceledException(); }
// To be called by this->output_filename() with the format string pulled from the configuration layer.
std::string output_filename(const std::string &format, const std::string &default_ext, const DynamicConfig *config_override = nullptr) const;
std::string output_filename(const std::string &format, const std::string &default_ext, const std::string &filename_base, const DynamicConfig *config_override = nullptr) const;
// Update "scale", "input_filename", "input_filename_base" placeholders from the current printable ModelObjects.
void update_object_placeholders(DynamicConfig &config) const;
void update_object_placeholders(DynamicConfig &config, const std::string &default_ext) const;
Model m_model;

View File

@ -561,10 +561,10 @@ void SLAPrint::finalize()
// Generate a recommended output file name based on the format template, default extension, and template parameters
// (timestamps, object placeholders derived from the model, current placeholder prameters and print statistics.
// Use the final print statistics if available, or just keep the print statistics placeholders if not available yet (before the output is finalized).
std::string SLAPrint::output_filename() const
std::string SLAPrint::output_filename(const std::string &filename_base) const
{
DynamicConfig config = this->finished() ? this->print_statistics().config() : this->print_statistics().placeholders();
return this->PrintBase::output_filename(m_print_config.output_filename_format.value, "sl1", &config);
return this->PrintBase::output_filename(m_print_config.output_filename_format.value, ".sl1", filename_base, &config);
}
namespace {

View File

@ -402,9 +402,9 @@ public:
// Extracted value from the configuration objects
Vec3d relative_correction() const;
std::string output_filename() const override;
std::string output_filename(const std::string &filename_base = std::string()) const override;
const SLAPrintStatistics& print_statistics() const { return m_print_statistics; }
const SLAPrintStatistics& print_statistics() const { return m_print_statistics; }
std::string validate() const override;

View File

@ -67,6 +67,14 @@ PrinterTechnology BackgroundSlicingProcess::current_printer_technology() const
return m_print->technology();
}
std::string BackgroundSlicingProcess::output_filepath_for_project(const boost::filesystem::path &project_path)
{
assert(m_print != nullptr);
if (project_path.empty())
return m_print->output_filepath("");
return m_print->output_filepath(project_path.parent_path().string(), project_path.stem().string());
}
// This function may one day be merged into the Print, but historically the print was separated
// from the G-code generator.
void BackgroundSlicingProcess::process_fff()

View File

@ -6,6 +6,8 @@
#include <mutex>
#include <thread>
#include <boost/filesystem.hpp>
#include <wx/event.h>
#include "libslic3r/Print.hpp"
@ -65,6 +67,9 @@ public:
const PrintBase* current_print() const { return m_print; }
const Print* fff_print() const { return m_fff_print; }
const SLAPrint* sla_print() const { return m_sla_print; }
// Take the project path (if provided), extract the name of the project, run it through the macro processor and save it next to the project file.
// If the project_path is empty, just run output_filepath().
std::string output_filepath_for_project(const boost::filesystem::path &project_path);
// Start the background processing. Returns false if the background processing was already running.
bool start();

View File

@ -5,9 +5,7 @@
#include <vector>
#include <string>
#include <regex>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/optional.hpp>
#include <boost/filesystem/path.hpp>
@ -2971,9 +2969,16 @@ wxString Plater::priv::get_project_filename(const wxString& extension) const
void Plater::priv::set_project_filename(const wxString& filename)
{
boost::filesystem::path full_path = into_path(filename);
// remove extension
while (full_path.has_extension())
{
boost::filesystem::path ext = full_path.extension();
if (boost::iequals(ext.string(), ".amf")) {
// Remove the first extension.
full_path.replace_extension("");
// It may be ".zip.amf".
if (boost::iequals(full_path.extension().string(), ".zip"))
// Remove the 2nd extension.
full_path.replace_extension("");
} else {
// Remove just one extension.
full_path.replace_extension("");
}
@ -3492,7 +3497,7 @@ void Plater::export_gcode()
unsigned int state = this->p->update_restart_background_process(false, false);
if (state & priv::UPDATE_BACKGROUND_PROCESS_INVALID)
return;
default_output_file = this->p->background_process.current_print()->output_filepath(into_path(get_project_filename()).string());
default_output_file = this->p->background_process.output_filepath_for_project(into_path(get_project_filename(".3mf")));
}
catch (const std::exception &ex) {
show_error(this, ex.what());
@ -3737,7 +3742,7 @@ void Plater::send_gcode()
unsigned int state = this->p->update_restart_background_process(false, false);
if (state & priv::UPDATE_BACKGROUND_PROCESS_INVALID)
return;
default_output_file = this->p->background_process.current_print()->output_filepath(into_path(get_project_filename(".3mf")).string());
default_output_file = this->p->background_process.output_filepath_for_project(into_path(get_project_filename(".3mf")));
}
catch (const std::exception &ex) {
show_error(this, ex.what());