mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	Merge branch 'master' of https://github.com/prusa3d/Slic3r into time_estimate
This commit is contained in:
		
						commit
						00381988bf
					
				
					 2 changed files with 452 additions and 2910 deletions
				
			
		
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -14,6 +14,7 @@ | ||||||
| #include <boost/property_tree/ini_parser.hpp> | #include <boost/property_tree/ini_parser.hpp> | ||||||
| #include <boost/property_tree/ptree.hpp> | #include <boost/property_tree/ptree.hpp> | ||||||
| #include <boost/locale.hpp> | #include <boost/locale.hpp> | ||||||
|  | #include <boost/log/trivial.hpp> | ||||||
| 
 | 
 | ||||||
| #include <wx/dcmemory.h> | #include <wx/dcmemory.h> | ||||||
| #include <wx/image.h> | #include <wx/image.h> | ||||||
|  | @ -474,6 +475,125 @@ void PresetBundle::load_config_file_config_bundle(const std::string &path, const | ||||||
|     this->update_compatible_with_printer(false); |     this->update_compatible_with_printer(false); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Process the Config Bundle loaded as a Boost property tree.
 | ||||||
|  | // For each print, filament and printer preset (group defined by group_name), apply the inherited presets.
 | ||||||
|  | // The presets starting with '*' are considered non-terminal and they are
 | ||||||
|  | // removed through the flattening process by this function.
 | ||||||
|  | // This function will never fail, but it will produce error messages through boost::log.
 | ||||||
|  | static void flatten_configbundle_hierarchy(boost::property_tree::ptree &tree, const std::string &group_name) | ||||||
|  | { | ||||||
|  |     namespace pt = boost::property_tree; | ||||||
|  | 
 | ||||||
|  |     typedef std::pair<pt::ptree::key_type, pt::ptree> ptree_child_type; | ||||||
|  | 
 | ||||||
|  |     // 1) For the group given by group_name, initialize the presets.
 | ||||||
|  |     struct Prst { | ||||||
|  |         Prst(const std::string &name, pt::ptree *node) : name(name), node(node) {} | ||||||
|  |         // Name of this preset. If the name starts with '*', it is an intermediate preset,
 | ||||||
|  |         // which will not make it into the result.
 | ||||||
|  |         const std::string           name; | ||||||
|  |         // Link to the source boost property tree node, owned by tree.
 | ||||||
|  |         pt::ptree                  *node; | ||||||
|  |         // Link to the presets, from which this preset inherits.
 | ||||||
|  |         std::vector<Prst*>          inherits; | ||||||
|  |         // Link to the presets, for which this preset is a direct parent.
 | ||||||
|  |         std::vector<Prst*>          parent_of; | ||||||
|  |         // When running the Kahn's Topological sorting algorithm, this counter is decreased from inherits.size() to zero.
 | ||||||
|  |         // A cycle is indicated, if the number does not drop to zero after the Kahn's algorithm finishes.
 | ||||||
|  |         size_t                      num_incoming_edges_left = 0; | ||||||
|  |         // Sorting by the name, to be used when inserted into std::set.
 | ||||||
|  |         bool operator==(const Prst &rhs) const { return this->name == rhs.name; } | ||||||
|  |         bool operator< (const Prst &rhs) const { return this->name < rhs.name; } | ||||||
|  |     }; | ||||||
|  |     // Find the presets, store them into a std::map, addressed by their names.
 | ||||||
|  |     std::set<Prst> presets; | ||||||
|  |     std::string group_name_preset = group_name + ":"; | ||||||
|  |     for (auto §ion : tree) | ||||||
|  |         if (boost::starts_with(section.first, group_name_preset) && section.first.size() > group_name_preset.size()) | ||||||
|  |             presets.emplace(section.first.substr(group_name_preset.size()), §ion.second); | ||||||
|  |     // Fill in the "inherits" and "parent_of" members, report invalid inheritance fields.
 | ||||||
|  |     for (const Prst &prst : presets) { | ||||||
|  |         // Parse the list of comma separated values, possibly enclosed in quotes.
 | ||||||
|  |         std::vector<std::string> inherits_names; | ||||||
|  |         if (Slic3r::unescape_strings_cstyle(prst.node->get<std::string>("inherits", ""), inherits_names)) { | ||||||
|  |             // Resolve the inheritance by name.
 | ||||||
|  |             std::vector<Prst*> &inherits_nodes = const_cast<Prst&>(prst).inherits; | ||||||
|  |             for (const std::string &node_name : inherits_names) { | ||||||
|  |                 auto it = presets.find(Prst(node_name, nullptr)); | ||||||
|  |                 if (it == presets.end()) | ||||||
|  |                     BOOST_LOG_TRIVIAL(error) << "flatten_configbundle_hierarchy: The preset " << prst.name << " inherits an unknown preset \"" << node_name << "\""; | ||||||
|  |                 else { | ||||||
|  |                     inherits_nodes.emplace_back(const_cast<Prst*>(&(*it))); | ||||||
|  |                     inherits_nodes.back()->parent_of.emplace_back(const_cast<Prst*>(&prst)); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             BOOST_LOG_TRIVIAL(error) << "flatten_configbundle_hierarchy: The preset " << prst.name << " has an invalid \"inherits\" field"; | ||||||
|  |         } | ||||||
|  |         // Remove the "inherits" key, it has no meaning outside the config bundle.
 | ||||||
|  |         const_cast<pt::ptree*>(prst.node)->erase("inherits"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // 2) Create a linear ordering for the directed acyclic graph of preset inheritance.
 | ||||||
|  |     // https://en.wikipedia.org/wiki/Topological_sorting
 | ||||||
|  |     // Kahn's algorithm.
 | ||||||
|  |     std::vector<Prst*> sorted; | ||||||
|  |     { | ||||||
|  |         // Initialize S with the set of all nodes with no incoming edge.
 | ||||||
|  |         std::deque<Prst*> S; | ||||||
|  |         for (const Prst &prst : presets) | ||||||
|  |             if (prst.inherits.empty()) | ||||||
|  |                 S.emplace_back(const_cast<Prst*>(&prst)); | ||||||
|  |             else | ||||||
|  |                 const_cast<Prst*>(&prst)->num_incoming_edges_left = prst.inherits.size(); | ||||||
|  |         while (! S.empty()) { | ||||||
|  |             Prst *n = S.front(); | ||||||
|  |             S.pop_front(); | ||||||
|  |             sorted.emplace_back(n); | ||||||
|  |             for (Prst *m : n->parent_of) { | ||||||
|  |                 assert(m->num_incoming_edges_left > 0); | ||||||
|  |                 if (-- m->num_incoming_edges_left == 0) { | ||||||
|  |                     // We have visited all parents of m.
 | ||||||
|  |                     S.emplace_back(m); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if (sorted.size() < presets.size()) { | ||||||
|  |             for (const Prst &prst : presets) | ||||||
|  |                 if (prst.num_incoming_edges_left) | ||||||
|  |                     BOOST_LOG_TRIVIAL(error) << "flatten_configbundle_hierarchy: The preset " << prst.name << " has cyclic dependencies"; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Apply the dependencies in their topological ordering.
 | ||||||
|  |     for (Prst *prst : sorted) { | ||||||
|  |         // Merge the preset nodes in their order of application.
 | ||||||
|  |         // Iterate in a reverse order, so the last change will be placed first in merged.
 | ||||||
|  |         for (auto it_inherits = prst->inherits.rbegin(); it_inherits != prst->inherits.rend(); ++ it_inherits) | ||||||
|  |             for (auto it = (*it_inherits)->node->begin(); it != (*it_inherits)->node->end(); ++ it) | ||||||
|  |                 if (prst->node->find(it->first) == prst->node->not_found()) | ||||||
|  |                     prst->node->add_child(it->first, it->second); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Remove the "internal" presets from the ptree. These presets are marked with '*'.
 | ||||||
|  |     group_name_preset += '*'; | ||||||
|  |     for (auto it_section = tree.begin(); it_section != tree.end(); ) { | ||||||
|  |         if (boost::starts_with(it_section->first, group_name_preset) && it_section->first.size() > group_name_preset.size()) | ||||||
|  |             // Remove the "internal" preset from the ptree.
 | ||||||
|  |             it_section = tree.erase(it_section); | ||||||
|  |         else | ||||||
|  |             // Keep the preset.
 | ||||||
|  |             ++ it_section; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void flatten_configbundle_hierarchy(boost::property_tree::ptree &tree) | ||||||
|  | { | ||||||
|  |     flatten_configbundle_hierarchy(tree, "print"); | ||||||
|  |     flatten_configbundle_hierarchy(tree, "filament"); | ||||||
|  |     flatten_configbundle_hierarchy(tree, "printer"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // Load a config bundle file, into presets and store the loaded presets into separate files
 | // Load a config bundle file, into presets and store the loaded presets into separate files
 | ||||||
| // of the local configuration directory.
 | // of the local configuration directory.
 | ||||||
| size_t PresetBundle::load_configbundle(const std::string &path, unsigned int flags) | size_t PresetBundle::load_configbundle(const std::string &path, unsigned int flags) | ||||||
|  | @ -486,6 +606,8 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla | ||||||
|     pt::ptree tree; |     pt::ptree tree; | ||||||
|     boost::nowide::ifstream ifs(path); |     boost::nowide::ifstream ifs(path); | ||||||
|     pt::read_ini(ifs, tree); |     pt::read_ini(ifs, tree); | ||||||
|  |     // Flatten the config bundle by applying the inheritance rules. Internal profiles (with names starting with '*') are removed.
 | ||||||
|  |     flatten_configbundle_hierarchy(tree); | ||||||
| 
 | 
 | ||||||
|     // 2) Parse the property_tree, extract the active preset names and the profiles, save them into local config files.
 |     // 2) Parse the property_tree, extract the active preset names and the profiles, save them into local config files.
 | ||||||
|     std::vector<std::string> loaded_prints; |     std::vector<std::string> loaded_prints; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Enrico Turri
						Enrico Turri