Fixed an issue, where the output G-code file name was not always updated

from the current Model/ModelObjects.
Fixed a possible race condition in updating Print::m_placeholder_parser
with the proposed filename / filename base.
Improved documentation (source code comments).
This commit is contained in:
bubnikv 2019-02-03 10:41:14 +01:00
parent e59a10e0c2
commit a56f7d60e5
12 changed files with 80 additions and 70 deletions

View file

@ -717,6 +717,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());
// 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

@ -252,8 +252,10 @@ float new_feedrate_to_reach_time_stretch(
for (size_t i = 0; i < (*it)->n_lines_adjustable; ++i) {
const CoolingLine &line = (*it)->lines[i];
if (line.feedrate > min_feedrate && line.feedrate < new_feedrate)
// Some of the line segments taken into account in the calculation of nomin / denom are now slower than new_feedrate.
// Re-run the calculation with a new min_feedrate limit.
// Some of the line segments taken into account in the calculation of nomin / denom are now slower than new_feedrate,
// which makes the new_feedrate lower than it should be.
// Re-run the calculation with a new min_feedrate limit, so that the segments with current feedrate lower than new_feedrate
// are not taken into account.
goto not_finished_yet;
}
goto finished;

View file

@ -547,13 +547,26 @@ void Model::reset_auto_extruder_id()
s_auto_extruder_id = 1;
}
std::string Model::propose_export_file_name() const
// Propose a filename including path derived from the ModelObject's input path.
// If object's name is filled in, use the object name, otherwise use the input name.
std::string Model::propose_export_file_name_and_path() const
{
std::string input_file;
for (const ModelObject *model_object : this->objects)
for (ModelInstance *model_instance : model_object->instances)
if (model_instance->is_printable()) {
input_file = model_object->name.empty() ? model_object->input_file : model_object->name;
input_file = model_object->input_file;
if (! model_object->name.empty()) {
if (input_file.empty())
// model_object->input_file was empty, just use model_object->name
input_file = model_object->name;
else {
// Replace file name in input_file with model_object->name, but keep the path and file extension.
input_file = (boost::filesystem::path(model_object->name).parent_path().empty()) ?
(boost::filesystem::path(input_file).parent_path() / model_object->name).make_preferred().string() :
model_object->name;
}
}
if (! input_file.empty())
goto end;
// Other instances will produce the same name, skip them.

View file

@ -607,8 +607,8 @@ public:
static std::string get_auto_extruder_id_as_string(unsigned int max_extruders);
static void reset_auto_extruder_id();
// Propose an output file name based on the first printable object's name.
std::string propose_export_file_name() const;
// Propose an output file name & path based on the first printable object's name and source input file's path.
std::string propose_export_file_name_and_path() const;
private:
MODELBASE_DERIVED_PRIVATE_COPY_MOVE(Model)

View file

@ -32,7 +32,8 @@ public:
void set(const std::string &key, double value) { this->set(key, new ConfigOptionFloat(value)); }
void set(const std::string &key, const std::vector<std::string> &values) { this->set(key, new ConfigOptionStrings(values)); }
void set(const std::string &key, ConfigOption *opt) { m_config.set_key_value(key, opt); }
const DynamicConfig& config() const { return m_config; }
DynamicConfig& config_writable() { return m_config; }
const DynamicConfig& config() const { return m_config; }
const ConfigOption* option(const std::string &key) const { return m_config.option(key); }
// Fill in the template using a macro processing language.

View file

@ -421,8 +421,6 @@ void Print::add_model_object(ModelObject* model_object, int idx)
src_normalized.normalize();
object->config_apply(src_normalized, true);
}
this->update_object_placeholders();
}
bool Print::apply_config(DynamicPrintConfig config)
@ -1096,9 +1094,6 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
}
}
//FIXME there may be a race condition with the G-code export running at the background thread.
this->update_object_placeholders();
#ifdef _DEBUG
check_model_ids_equal(m_model, model);
#endif /* _DEBUG */
@ -1855,6 +1850,9 @@ int Print::get_extruder(const ExtrusionEntityCollection& fill, const PrintRegion
std::max<int>(region.config().perimeter_extruder.value - 1, 0);
}
// 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
{
// Set the placeholders for the data know first after the G-code export is finished.

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()
void PrintBase::update_object_placeholders(DynamicConfig &config) const
{
// get the first input file name
std::string input_file;
@ -33,27 +33,29 @@ void PrintBase::update_object_placeholders()
"% y:" + boost::lexical_cast<std::string>(printable->get_scaling_factor(Y) * 100) +
"% z:" + boost::lexical_cast<std::string>(printable->get_scaling_factor(Z) * 100) + "%");
if (input_file.empty())
input_file = model_object->input_file;
input_file = model_object->name.empty() ? model_object->input_file : model_object->name;
}
}
PlaceholderParser &pp = m_placeholder_parser;
pp.set("scale", v_scale);
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();
pp.set("input_filename", input_basename);
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("."));
pp.set("input_filename_base", input_basename_base);
config.set_key_value("input_filename_base", new ConfigOptionString(input_basename_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
{
DynamicConfig cfg;
if (config_override != nullptr)
cfg = *config_override;
PlaceholderParser::update_timestamp(cfg);
this->update_object_placeholders(cfg);
try {
boost::filesystem::path filename = this->placeholder_parser().process(format, 0, &cfg);
if (filename.extension().empty())
@ -69,7 +71,7 @@ std::string PrintBase::output_filepath(const std::string &path) 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()).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()).make_preferred().string();
// if we were supplied a directory, use it and append our automatically generated filename
boost::filesystem::path p(path);

View file

@ -309,7 +309,7 @@ protected:
// 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;
// Update "scale", "input_filename", "input_filename_base" placeholders from the current printable ModelObjects.
void update_object_placeholders();
void update_object_placeholders(DynamicConfig &config) const;
Model m_model;

View file

@ -387,8 +387,6 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf
update_apply_status(false);
}
this->update_object_placeholders();
#ifdef _DEBUG
check_model_ids_equal(m_model, model);
#endif /* _DEBUG */