mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 20:21:12 -06:00 
			
		
		
		
	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
					
				
					 5 changed files with 80 additions and 69 deletions
				
			
		|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 bubnikv
						bubnikv