Fix of "MM incorrect extruder temperature"
https://github.com/prusa3d/Slic3r/issues/443 Change of the PlaceholderParser: All vector configuration values stored into the PlaceholderParser are expected to be addressed by the extruder ID, therefore if a vector configuration value is addressed without an index, a current extruder ID is used. Also a small fix of fan handling: The fan speed is set to zero at the start of the G-code if the cooling for the initial extruder is disabled.
This commit is contained in:
parent
7181f5d163
commit
75c72bc59b
@ -469,7 +469,7 @@ bool GCode::do_export(FILE *file, Print &print)
|
||||
m_cooling_buffer->set_current_extruder(initial_extruder_id);
|
||||
|
||||
// Disable fan.
|
||||
if (print.config.cooling.get_at(initial_extruder_id) && print.config.disable_fan_first_layers.get_at(initial_extruder_id))
|
||||
if (! print.config.cooling.get_at(initial_extruder_id) || print.config.disable_fan_first_layers.get_at(initial_extruder_id))
|
||||
write(file, m_writer.set_fan(0, true));
|
||||
|
||||
// Set bed temperature if the start G-code does not contain any bed temp control G-codes.
|
||||
@ -487,10 +487,12 @@ bool GCode::do_export(FILE *file, Print &print)
|
||||
this->_print_first_layer_extruder_temperatures(file, print, initial_extruder_id, false);
|
||||
// Let the start-up script prime the 1st printing tool.
|
||||
m_placeholder_parser.set("initial_tool", initial_extruder_id);
|
||||
writeln(file, m_placeholder_parser.process(print.config.start_gcode.value));
|
||||
m_placeholder_parser.set("initial_extruder", initial_extruder_id);
|
||||
m_placeholder_parser.set("current_extruder", initial_extruder_id);
|
||||
writeln(file, m_placeholder_parser.process(print.config.start_gcode.value, initial_extruder_id));
|
||||
// Process filament-specific gcode in extruder order.
|
||||
for (const std::string &start_gcode : print.config.start_filament_gcode.values)
|
||||
writeln(file, m_placeholder_parser.process(start_gcode));
|
||||
writeln(file, m_placeholder_parser.process(start_gcode, &start_gcode - &print.config.start_filament_gcode.values.front()));
|
||||
this->_print_first_layer_extruder_temperatures(file, print, initial_extruder_id, true);
|
||||
|
||||
// Set other general things.
|
||||
@ -636,8 +638,8 @@ bool GCode::do_export(FILE *file, Print &print)
|
||||
write(file, m_writer.set_fan(false));
|
||||
// Process filament-specific gcode in extruder order.
|
||||
for (const std::string &end_gcode : print.config.end_filament_gcode.values)
|
||||
writeln(file, m_placeholder_parser.process(end_gcode));
|
||||
writeln(file, m_placeholder_parser.process(print.config.end_gcode));
|
||||
writeln(file, m_placeholder_parser.process(end_gcode, &end_gcode - &print.config.end_filament_gcode.values.front()));
|
||||
writeln(file, m_placeholder_parser.process(print.config.end_gcode, m_writer.extruder()->id()));
|
||||
write(file, m_writer.update_progress(m_layer_count, m_layer_count, true)); // 100%
|
||||
write(file, m_writer.postamble());
|
||||
|
||||
@ -800,7 +802,7 @@ void GCode::process_layer(
|
||||
PlaceholderParser pp(m_placeholder_parser);
|
||||
pp.set("layer_num", m_layer_index + 1);
|
||||
pp.set("layer_z", print_z);
|
||||
gcode += pp.process(print.config.before_layer_gcode.value) + "\n";
|
||||
gcode += pp.process(print.config.before_layer_gcode.value, m_writer.extruder()->id()) + "\n";
|
||||
}
|
||||
gcode += this->change_layer(print_z); // this will increase m_layer_index
|
||||
m_layer = &layer;
|
||||
@ -808,7 +810,7 @@ void GCode::process_layer(
|
||||
PlaceholderParser pp(m_placeholder_parser);
|
||||
pp.set("layer_num", m_layer_index);
|
||||
pp.set("layer_z", print_z);
|
||||
gcode += pp.process(print.config.layer_gcode.value) + "\n";
|
||||
gcode += pp.process(print.config.layer_gcode.value, m_writer.extruder()->id()) + "\n";
|
||||
}
|
||||
|
||||
if (! first_layer && ! m_second_layer_things_done) {
|
||||
@ -2004,7 +2006,7 @@ std::string GCode::set_extruder(unsigned int extruder_id)
|
||||
PlaceholderParser pp = m_placeholder_parser;
|
||||
pp.set("previous_extruder", m_writer.extruder()->id());
|
||||
pp.set("next_extruder", extruder_id);
|
||||
gcode += pp.process(m_config.toolchange_gcode.value) + '\n';
|
||||
gcode += pp.process(m_config.toolchange_gcode.value, extruder_id) + '\n';
|
||||
}
|
||||
|
||||
// if ooze prevention is enabled, park current extruder in the nearest
|
||||
|
@ -30,8 +30,7 @@ PlaceholderParser::PlaceholderParser()
|
||||
this->update_timestamp();
|
||||
}
|
||||
|
||||
void
|
||||
PlaceholderParser::update_timestamp()
|
||||
void PlaceholderParser::update_timestamp()
|
||||
{
|
||||
time_t rawtime;
|
||||
time(&rawtime);
|
||||
@ -56,22 +55,26 @@ PlaceholderParser::update_timestamp()
|
||||
this->set("second", timeinfo->tm_sec);
|
||||
}
|
||||
|
||||
// Scalar configuration values are stored into m_single,
|
||||
// vector configuration values are stored into m_multiple.
|
||||
// All vector configuration values stored into the PlaceholderParser
|
||||
// are expected to be addressed by the extruder ID, therefore
|
||||
// if a vector configuration value is addressed without an index,
|
||||
// a current extruder ID is used.
|
||||
void PlaceholderParser::apply_config(const DynamicPrintConfig &config)
|
||||
{
|
||||
t_config_option_keys opt_keys = config.keys();
|
||||
for (t_config_option_keys::const_iterator i = opt_keys.begin(); i != opt_keys.end(); ++i) {
|
||||
const t_config_option_key &opt_key = *i;
|
||||
for (const t_config_option_key &opt_key : config.keys()) {
|
||||
const ConfigOptionDef* def = config.def->get(opt_key);
|
||||
if (def->multiline) continue;
|
||||
|
||||
if (def->multiline || opt_key == "post_process")
|
||||
continue;
|
||||
|
||||
const ConfigOption* opt = config.option(opt_key);
|
||||
if (const ConfigOptionVectorBase* optv = dynamic_cast<const ConfigOptionVectorBase*>(opt)) {
|
||||
const ConfigOptionVectorBase* optv = dynamic_cast<const ConfigOptionVectorBase*>(opt);
|
||||
if (optv != nullptr && opt_key != "bed_shape") {
|
||||
// set placeholders for options with multiple values
|
||||
// TODO: treat [bed_shape] as single, not multiple
|
||||
this->set(opt_key, optv->vserialize());
|
||||
} else if (const ConfigOptionPoint* optp = dynamic_cast<const ConfigOptionPoint*>(opt)) {
|
||||
this->set(opt_key, optp->serialize());
|
||||
|
||||
Pointf val = *optp;
|
||||
this->set(opt_key + "_X", val.x);
|
||||
this->set(opt_key + "_Y", val.y);
|
||||
@ -82,8 +85,7 @@ void PlaceholderParser::apply_config(const DynamicPrintConfig &config)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PlaceholderParser::apply_env_variables()
|
||||
void PlaceholderParser::apply_env_variables()
|
||||
{
|
||||
for (char** env = environ; *env; env++) {
|
||||
if (strncmp(*env, "SLIC3R_", 7) == 0) {
|
||||
@ -99,8 +101,8 @@ PlaceholderParser::apply_env_variables()
|
||||
|
||||
void PlaceholderParser::set(const std::string &key, const std::string &value)
|
||||
{
|
||||
this->_single[key] = value;
|
||||
this->_multiple.erase(key);
|
||||
m_single[key] = value;
|
||||
m_multiple.erase(key);
|
||||
}
|
||||
|
||||
void PlaceholderParser::set(const std::string &key, int value)
|
||||
@ -126,53 +128,63 @@ void PlaceholderParser::set(const std::string &key, double value)
|
||||
|
||||
void PlaceholderParser::set(const std::string &key, std::vector<std::string> values)
|
||||
{
|
||||
if (values.empty()) {
|
||||
this->_multiple.erase(key);
|
||||
this->_single.erase(key);
|
||||
} else {
|
||||
this->_multiple[key] = values;
|
||||
this->_single[key] = values.front();
|
||||
}
|
||||
m_single.erase(key);
|
||||
if (values.empty())
|
||||
m_multiple.erase(key);
|
||||
else
|
||||
m_multiple[key] = values;
|
||||
}
|
||||
|
||||
std::string PlaceholderParser::process(std::string str) const
|
||||
std::string PlaceholderParser::process(std::string str, unsigned int current_extruder_id) const
|
||||
{
|
||||
// replace single options, like [foo]
|
||||
for (t_strstr_map::const_iterator it = this->_single.begin(); it != this->_single.end(); ++it) {
|
||||
std::stringstream ss;
|
||||
ss << '[' << it->first << ']';
|
||||
this->find_and_replace(str, ss.str(), it->second);
|
||||
char key[2048];
|
||||
|
||||
// Replace extruder independent single options, like [foo].
|
||||
for (const auto &key_value : m_single) {
|
||||
sprintf(key, "[%s]", key_value.first.c_str());
|
||||
const std::string &replace = key_value.second;
|
||||
for (size_t i = 0; (i = str.find(key, i)) != std::string::npos;) {
|
||||
str.replace(i, key_value.first.size() + 2, replace);
|
||||
i += replace.size();
|
||||
}
|
||||
}
|
||||
|
||||
// replace multiple options like [foo_0] by looping until we have enough values
|
||||
// or until a previous match was found (this handles non-existing indices reasonably
|
||||
// without a regex)
|
||||
for (t_strstrs_map::const_iterator it = this->_multiple.begin(); it != this->_multiple.end(); ++it) {
|
||||
const std::vector<std::string> &values = it->second;
|
||||
bool found = false;
|
||||
for (size_t i = 0; (i < values.size()) || found; ++i) {
|
||||
std::stringstream ss;
|
||||
ss << '[' << it->first << '_' << i << ']';
|
||||
if (i < values.size()) {
|
||||
found = this->find_and_replace(str, ss.str(), values[i]);
|
||||
} else {
|
||||
found = this->find_and_replace(str, ss.str(), values.front());
|
||||
|
||||
// Replace extruder dependent single options with the value for the active extruder.
|
||||
// For example, [temperature] will be replaced with the current extruder temperature.
|
||||
for (const auto &key_value : m_multiple) {
|
||||
sprintf(key, "[%s]", key_value.first.c_str());
|
||||
const std::string &replace = key_value.second[(current_extruder_id < key_value.second.size()) ? current_extruder_id : 0];
|
||||
for (size_t i = 0; (i = str.find(key, i)) != std::string::npos;) {
|
||||
str.replace(i, key_value.first.size() + 2, replace);
|
||||
i += replace.size();
|
||||
}
|
||||
}
|
||||
|
||||
// Replace multiple options like [foo_0].
|
||||
for (const auto &key_value : m_multiple) {
|
||||
sprintf(key, "[%s_", key_value.first.c_str());
|
||||
const std::vector<std::string> &values = key_value.second;
|
||||
for (size_t i = 0; (i = str.find(key, i)) != std::string::npos;) {
|
||||
size_t k = str.find(']', i + key_value.first.size() + 2);
|
||||
if (k != std::string::npos) {
|
||||
// Parse the key index and the closing bracket.
|
||||
++ k;
|
||||
int idx = 0;
|
||||
if (sscanf(str.c_str() + i + key_value.first.size() + 2, "%d]", &idx) == 1 && idx >= 0) {
|
||||
if (idx >= int(values.size()))
|
||||
idx = 0;
|
||||
str.replace(i, k - i, values[idx]);
|
||||
i += values[idx].size();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// The key does not match the pattern [foo_%d]. Skip just [foo_.] with the hope that there was a missing ']',
|
||||
// so an opening '[' may be found somewhere before the position k.
|
||||
i += key_value.first.size() + 3;
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
bool PlaceholderParser::find_and_replace(std::string &source, std::string const &find, std::string const &replace) const
|
||||
{
|
||||
bool found = false;
|
||||
for (std::string::size_type i = 0; (i = source.find(find, i)) != std::string::npos; ) {
|
||||
source.replace(i, find.length(), replace);
|
||||
i += replace.length();
|
||||
found = true;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,17 +7,13 @@
|
||||
#include <vector>
|
||||
#include "PrintConfig.hpp"
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
typedef std::map<std::string, std::string> t_strstr_map;
|
||||
typedef std::map<std::string, std::vector<std::string> > t_strstrs_map;
|
||||
|
||||
class PlaceholderParser
|
||||
{
|
||||
public:
|
||||
t_strstr_map _single;
|
||||
t_strstrs_map _multiple;
|
||||
std::map<std::string, std::string> m_single;
|
||||
std::map<std::string, std::vector<std::string>> m_multiple;
|
||||
|
||||
PlaceholderParser();
|
||||
void update_timestamp();
|
||||
@ -28,7 +24,7 @@ public:
|
||||
void set(const std::string &key, unsigned int value);
|
||||
void set(const std::string &key, double value);
|
||||
void set(const std::string &key, std::vector<std::string> values);
|
||||
std::string process(std::string str) const;
|
||||
std::string process(std::string str, unsigned int current_extruder_id) const;
|
||||
|
||||
private:
|
||||
bool find_and_replace(std::string &source, std::string const &find, std::string const &replace) const;
|
||||
|
@ -1052,7 +1052,7 @@ void Print::_make_wipe_tower()
|
||||
std::string Print::output_filename()
|
||||
{
|
||||
this->placeholder_parser.update_timestamp();
|
||||
return this->placeholder_parser.process(this->config.output_filename_format.value);
|
||||
return this->placeholder_parser.process(this->config.output_filename_format.value, 0);
|
||||
}
|
||||
|
||||
std::string Print::output_filepath(const std::string &path)
|
||||
|
@ -18,5 +18,6 @@
|
||||
%code%{ THIS->apply_config(*config); %};
|
||||
void set(std::string key, std::string value);
|
||||
%name{set_multiple} void set(std::string key, std::vector<std::string> values);
|
||||
std::string process(std::string str) const;
|
||||
std::string process(std::string str) const
|
||||
%code%{ RETVAL = THIS->process(str, 0); %};
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user