Implemented inheritance of profiles inside a config bundle.
Updated the Prusa's presets to match the initial flat config bundle.
This commit is contained in:
parent
77e142553a
commit
f0fde26295
@ -32,6 +32,7 @@ gap_fill_speed = 40
|
||||
gcode_comments = 0
|
||||
infill_every_layers = 1
|
||||
infill_extruder = 1
|
||||
infill_extrusion_width = 0.45
|
||||
infill_first = 0
|
||||
infill_only_where_needed = 0
|
||||
infill_overlap = 25%
|
||||
@ -81,6 +82,7 @@ support_material_with_sheath = 0
|
||||
support_material_xy_spacing = 60%
|
||||
thin_walls = 0
|
||||
top_infill_extrusion_width = 0.45
|
||||
top_solid_infill_speed = 40
|
||||
travel_speed = 180
|
||||
wipe_tower = 0
|
||||
wipe_tower_per_color_wipe = 15
|
||||
@ -132,6 +134,7 @@ inherits = *0.05mm*
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.25 and num_extruders==1
|
||||
external_perimeter_extrusion_width = 0
|
||||
extrusion_width = 0.28
|
||||
fill_density = 20%
|
||||
first_layer_extrusion_width = 0.3
|
||||
infill_extrusion_width = 0
|
||||
infill_speed = 20
|
||||
@ -171,10 +174,10 @@ infill_speed = 60
|
||||
perimeter_speed = 50
|
||||
perimeters = 3
|
||||
solid_infill_speed = 50
|
||||
top_solid_infill_speed = 40
|
||||
|
||||
[print:0.10mm DETAIL MK3]
|
||||
inherits = *0.10mm*
|
||||
bridge_flow_ratio = 0.8
|
||||
bridge_speed = 30
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/
|
||||
external_perimeter_speed = 35
|
||||
@ -190,35 +193,30 @@ top_solid_infill_speed = 50
|
||||
|
||||
[print:0.10mm DETAIL 0.25 nozzle]
|
||||
inherits = *0.10mm*
|
||||
bottom_solid_layers = 10
|
||||
bridge_acceleration = 300
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.25 and num_extruders==1
|
||||
default_acceleration = 500
|
||||
external_perimeter_extrusion_width = 0
|
||||
bridge_acceleration = 600
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.25
|
||||
external_perimeter_speed = 20
|
||||
extrusion_width = 0.28
|
||||
first_layer_acceleration = 500
|
||||
first_layer_extrusion_width = 0.3
|
||||
gap_fill_speed = 20
|
||||
infill_acceleration = 800
|
||||
infill_extrusion_width = 0
|
||||
infill_speed = 20
|
||||
perimeter_acceleration = 300
|
||||
perimeter_extrusion_width = 0
|
||||
perimeter_speed = 20
|
||||
external_perimeter_extrusion_width = 0.25
|
||||
extrusion_width = 0.25
|
||||
fill_density = 15%
|
||||
first_layer_extrusion_width = 0.25
|
||||
infill_acceleration = 1600
|
||||
infill_extrusion_width = 0.25
|
||||
infill_speed = 40
|
||||
perimeter_acceleration = 600
|
||||
perimeter_extrusion_width = 0.25
|
||||
perimeter_speed = 25
|
||||
perimeters = 4
|
||||
small_perimeter_speed = 10
|
||||
solid_infill_extrusion_width = 0
|
||||
solid_infill_speed = 20
|
||||
solid_infill_extrusion_width = 0.25
|
||||
solid_infill_speed = 40
|
||||
support_material_extrusion_width = 0.18
|
||||
support_material_interface_layers = 0
|
||||
support_material_interface_spacing = 0.15
|
||||
support_material_spacing = 1
|
||||
support_material_speed = 20
|
||||
support_material_xy_spacing = 150%
|
||||
top_infill_extrusion_width = 0
|
||||
top_solid_infill_speed = 20
|
||||
top_solid_layers = 15
|
||||
top_infill_extrusion_width = 0.25
|
||||
top_solid_infill_speed = 30
|
||||
|
||||
[print:*0.15mm*]
|
||||
inherits = *common*
|
||||
@ -235,7 +233,6 @@ support_material_contact_distance = 0.15
|
||||
support_material_interface_spacing = 0.2
|
||||
support_material_spacing = 2
|
||||
top_infill_extrusion_width = 0.4
|
||||
top_solid_infill_speed = 40
|
||||
top_solid_layers = 7
|
||||
|
||||
[print:0.15mm 100mms Linear Advance]
|
||||
@ -257,6 +254,7 @@ top_solid_layers = 5
|
||||
[print:0.15mm OPTIMAL]
|
||||
inherits = *0.15mm*
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.4
|
||||
top_infill_extrusion_width = 0.45
|
||||
|
||||
[print:0.15mm OPTIMAL 0.25 nozzle]
|
||||
inherits = *0.15mm*
|
||||
@ -315,14 +313,12 @@ wipe_tower = 1
|
||||
|
||||
[print:0.15mm OPTIMAL SOLUBLE FULL]
|
||||
inherits = *0.15mm*
|
||||
bottom_solid_layers = 4
|
||||
bridge_flow_ratio = 0.95
|
||||
bottom_solid_layers = 5
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.4 and num_extruders>1
|
||||
external_perimeter_speed = 30
|
||||
external_perimeter_speed = 25
|
||||
notes = Set your solluble extruder in Multiple Extruders > Support material/raft/skirt extruder & Support material/raft interface extruder
|
||||
overhangs = 1
|
||||
perimeter_speed = 40
|
||||
perimeters = 2
|
||||
skirts = 0
|
||||
solid_infill_speed = 40
|
||||
support_material = 1
|
||||
@ -334,10 +330,11 @@ support_material_interface_spacing = 0.1
|
||||
support_material_synchronize_layers = 1
|
||||
support_material_threshold = 80
|
||||
support_material_with_sheath = 1
|
||||
support_material_xy_spacing = 120%
|
||||
support_material_xy_spacing = 60%
|
||||
top_infill_extrusion_width = 0.45
|
||||
top_solid_infill_speed = 30
|
||||
top_solid_layers = 5
|
||||
wipe_tower = 1
|
||||
wipe_tower_per_color_wipe = 20
|
||||
|
||||
[print:0.15mm OPTIMAL SOLUBLE INTERFACE]
|
||||
inherits = 0.15mm OPTIMAL SOLUBLE FULL
|
||||
@ -345,7 +342,7 @@ notes = Set your solluble extruder in Multiple Extruders > Support material/raf
|
||||
support_material_extruder = 0
|
||||
support_material_interface_layers = 3
|
||||
support_material_with_sheath = 0
|
||||
wipe_tower_per_color_wipe = 20
|
||||
support_material_xy_spacing = 120%
|
||||
|
||||
[print:*0.20mm*]
|
||||
inherits = *common*
|
||||
@ -436,6 +433,7 @@ inherits = 0.20mm NORMAL SOLUBLE FULL
|
||||
notes = Set your solluble extruder in Multiple Extruders > Support material/raft interface extruder
|
||||
support_material_extruder = 0
|
||||
support_material_interface_layers = 3
|
||||
support_material_with_sheath = 0
|
||||
|
||||
[print:*0.35mm*]
|
||||
inherits = *common*
|
||||
@ -448,10 +446,10 @@ infill_extrusion_width = 0.75
|
||||
infill_speed = 60
|
||||
layer_height = 0.35
|
||||
perimeter_acceleration = 800
|
||||
perimeter_extrusion_width = 0.43
|
||||
perimeter_extrusion_width = 0.65
|
||||
perimeter_speed = 50
|
||||
perimeters = 2
|
||||
solid_infill_extrusion_width = 0.7
|
||||
solid_infill_extrusion_width = 0.65
|
||||
solid_infill_speed = 60
|
||||
support_material_contact_distance = 0.15
|
||||
support_material_interface_spacing = 0.2
|
||||
@ -461,27 +459,28 @@ top_solid_layers = 4
|
||||
wipe_tower = 1
|
||||
|
||||
[print:0.35mm FAST]
|
||||
inherits = *common*
|
||||
inherits = *0.35mm*
|
||||
bridge_flow_ratio = 0.95
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.4
|
||||
first_layer_extrusion_width = 0.42
|
||||
infill_extrusion_width = 0.7
|
||||
perimeter_extrusion_width = 0.65
|
||||
perimeter_extrusion_width = 0.43
|
||||
solid_infill_extrusion_width = 0.7
|
||||
top_infill_extrusion_width = 0.43
|
||||
|
||||
[print:0.35mm FAST 0.6 nozzle]
|
||||
inherits = *common*
|
||||
inherits = *0.35mm*
|
||||
bottom_solid_layers = 7
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.61
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.6
|
||||
external_perimeter_extrusion_width = 0.61
|
||||
extrusion_width = 0.67
|
||||
first_layer_extrusion_width = 0.65
|
||||
perimeters = 3
|
||||
solid_infill_extrusion_width = 0.65
|
||||
top_infill_extrusion_width = 0.6
|
||||
top_solid_layers = 9
|
||||
|
||||
[print:0.35mm FAST sol full 0.6 nozzle]
|
||||
inherits = *common*
|
||||
inherits = *0.35mm*
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.6 and num_extruders>1
|
||||
external_perimeter_speed = 30
|
||||
extrusion_width = 0.67
|
||||
@ -500,11 +499,12 @@ support_material_synchronize_layers = 1
|
||||
support_material_threshold = 80
|
||||
support_material_xy_spacing = 120%
|
||||
top_infill_extrusion_width = 0.57
|
||||
wipe_tower_per_color_wipe = 20
|
||||
|
||||
[print:0.35mm FAST sol int 0.6 nozzle]
|
||||
inherits = 0.35mm FAST sol full 0.6 nozzle
|
||||
support_material_extruder = 0
|
||||
support_material_interface_layers = 0
|
||||
support_material_interface_layers = 2
|
||||
support_material_xy_spacing = 150%
|
||||
|
||||
[filament:*common*]
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/locale.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include <wx/dcmemory.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);
|
||||
}
|
||||
|
||||
// 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
|
||||
// of the local configuration directory.
|
||||
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;
|
||||
boost::nowide::ifstream ifs(path);
|
||||
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.
|
||||
std::vector<std::string> loaded_prints;
|
||||
|
Loading…
Reference in New Issue
Block a user