1 // Configuration store of Slic3r.
2 //
3 // The configuration store is either static or dynamic.
4 // DynamicPrintConfig is used mainly at the user interface. while the StaticPrintConfig is used
5 // during the slicing and the g-code generation.
6 //
7 // The classes derived from StaticPrintConfig form a following hierarchy.
8 //
9 // FullPrintConfig
10 //    PrintObjectConfig
11 //    PrintRegionConfig
12 //    PrintConfig
13 //        GCodeConfig
14 //
15 
16 #ifndef slic3r_PrintConfig_hpp_
17 #define slic3r_PrintConfig_hpp_
18 
19 #include "libslic3r.h"
20 #include "Config.hpp"
21 
22 // #define HAS_PRESSURE_EQUALIZER
23 
24 namespace Slic3r {
25 
26 enum GCodeFlavor : unsigned char {
27     gcfRepRapSprinter, gcfRepRapFirmware, gcfRepetier, gcfTeacup, gcfMakerWare, gcfMarlin, gcfSailfish, gcfMach3, gcfMachinekit,
28     gcfSmoothie, gcfNoExtrusion,
29 };
30 
31 enum class MachineLimitsUsage {
32 	EmitToGCode,
33 	TimeEstimateOnly,
34 	Ignore,
35 	Count,
36 };
37 
38 enum PrintHostType {
39     htPrusaLink, htOctoPrint, htDuet, htFlashAir, htAstroBox, htRepetier
40 };
41 
42 enum AuthorizationType {
43     atKeyPassword, atUserPassword
44 };
45 
46 enum InfillPattern : int {
47     ipRectilinear, ipMonotonic, ipAlignedRectilinear, ipGrid, ipTriangles, ipStars, ipCubic, ipLine, ipConcentric, ipHoneycomb, ip3DHoneycomb,
48     ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipAdaptiveCubic, ipSupportCubic, ipCount,
49 };
50 
51 enum class IroningType {
52 	TopSurfaces,
53 	TopmostOnly,
54 	AllSolid,
55 	Count,
56 };
57 
58 enum SupportMaterialPattern {
59     smpRectilinear, smpRectilinearGrid, smpHoneycomb,
60 };
61 
62 enum SeamPosition {
63     spRandom, spNearest, spAligned, spRear
64 };
65 
66 enum SLAMaterial {
67     slamTough,
68     slamFlex,
69     slamCasting,
70     slamDental,
71     slamHeatResistant,
72 };
73 
74 enum SLADisplayOrientation {
75     sladoLandscape,
76     sladoPortrait
77 };
78 
79 enum SLAPillarConnectionMode {
80     slapcmZigZag,
81     slapcmCross,
82     slapcmDynamic
83 };
84 
get_enum_values()85 template<> inline const t_config_enum_values& ConfigOptionEnum<PrinterTechnology>::get_enum_values() {
86     static t_config_enum_values keys_map;
87     if (keys_map.empty()) {
88         keys_map["FFF"]             = ptFFF;
89         keys_map["SLA"]             = ptSLA;
90     }
91     return keys_map;
92 }
93 
get_enum_values()94 template<> inline const t_config_enum_values& ConfigOptionEnum<GCodeFlavor>::get_enum_values() {
95     static t_config_enum_values keys_map;
96     if (keys_map.empty()) {
97         keys_map["reprap"]          = gcfRepRapSprinter;
98         keys_map["reprapfirmware"]  = gcfRepRapFirmware;
99         keys_map["repetier"]        = gcfRepetier;
100         keys_map["teacup"]          = gcfTeacup;
101         keys_map["makerware"]       = gcfMakerWare;
102         keys_map["marlin"]          = gcfMarlin;
103         keys_map["sailfish"]        = gcfSailfish;
104         keys_map["smoothie"]        = gcfSmoothie;
105         keys_map["mach3"]           = gcfMach3;
106         keys_map["machinekit"]      = gcfMachinekit;
107         keys_map["no-extrusion"]    = gcfNoExtrusion;
108     }
109     return keys_map;
110 }
111 
get_enum_values()112 template<> inline const t_config_enum_values& ConfigOptionEnum<MachineLimitsUsage>::get_enum_values() {
113     static t_config_enum_values keys_map;
114     if (keys_map.empty()) {
115         keys_map["emit_to_gcode"]       = int(MachineLimitsUsage::EmitToGCode);
116         keys_map["time_estimate_only"]  = int(MachineLimitsUsage::TimeEstimateOnly);
117         keys_map["ignore"]            	= int(MachineLimitsUsage::Ignore);
118     }
119     return keys_map;
120 }
121 
get_enum_values()122 template<> inline const t_config_enum_values& ConfigOptionEnum<PrintHostType>::get_enum_values() {
123     static t_config_enum_values keys_map;
124     if (keys_map.empty()) {
125         keys_map["prusalink"]       = htPrusaLink;
126         keys_map["octoprint"]       = htOctoPrint;
127         keys_map["duet"]            = htDuet;
128         keys_map["flashair"]        = htFlashAir;
129         keys_map["astrobox"]        = htAstroBox;
130         keys_map["repetier"]        = htRepetier;
131 
132     }
133     return keys_map;
134 }
135 
get_enum_values()136 template<> inline const t_config_enum_values& ConfigOptionEnum<AuthorizationType>::get_enum_values() {
137     static t_config_enum_values keys_map;
138     if (keys_map.empty()) {
139         keys_map["key"]             = atKeyPassword;
140         keys_map["user"]            = atUserPassword;
141     }
142     return keys_map;
143 }
144 
get_enum_values()145 template<> inline const t_config_enum_values& ConfigOptionEnum<InfillPattern>::get_enum_values() {
146     static t_config_enum_values keys_map;
147     if (keys_map.empty()) {
148         keys_map["rectilinear"]         = ipRectilinear;
149         keys_map["monotonic"]           = ipMonotonic;
150         keys_map["alignedrectilinear"]  = ipAlignedRectilinear;
151         keys_map["grid"]                = ipGrid;
152         keys_map["triangles"]           = ipTriangles;
153         keys_map["stars"]               = ipStars;
154         keys_map["cubic"]               = ipCubic;
155         keys_map["line"]                = ipLine;
156         keys_map["concentric"]          = ipConcentric;
157         keys_map["honeycomb"]           = ipHoneycomb;
158         keys_map["3dhoneycomb"]         = ip3DHoneycomb;
159         keys_map["gyroid"]              = ipGyroid;
160         keys_map["hilbertcurve"]        = ipHilbertCurve;
161         keys_map["archimedeanchords"]   = ipArchimedeanChords;
162         keys_map["octagramspiral"]      = ipOctagramSpiral;
163         keys_map["adaptivecubic"]       = ipAdaptiveCubic;
164         keys_map["supportcubic"]        = ipSupportCubic;
165     }
166     return keys_map;
167 }
168 
get_enum_values()169 template<> inline const t_config_enum_values& ConfigOptionEnum<IroningType>::get_enum_values() {
170     static t_config_enum_values keys_map;
171     if (keys_map.empty()) {
172         keys_map["top"]                 = int(IroningType::TopSurfaces);
173         keys_map["topmost"]             = int(IroningType::TopmostOnly);
174         keys_map["solid"]               = int(IroningType::AllSolid);
175     }
176     return keys_map;
177 }
178 
get_enum_values()179 template<> inline const t_config_enum_values& ConfigOptionEnum<SupportMaterialPattern>::get_enum_values() {
180     static t_config_enum_values keys_map;
181     if (keys_map.empty()) {
182         keys_map["rectilinear"]         = smpRectilinear;
183         keys_map["rectilinear-grid"]    = smpRectilinearGrid;
184         keys_map["honeycomb"]           = smpHoneycomb;
185     }
186     return keys_map;
187 }
188 
get_enum_values()189 template<> inline const t_config_enum_values& ConfigOptionEnum<SeamPosition>::get_enum_values() {
190     static t_config_enum_values keys_map;
191     if (keys_map.empty()) {
192         keys_map["random"]              = spRandom;
193         keys_map["nearest"]             = spNearest;
194         keys_map["aligned"]             = spAligned;
195         keys_map["rear"]                = spRear;
196     }
197     return keys_map;
198 }
199 
get_enum_values()200 template<> inline const t_config_enum_values& ConfigOptionEnum<SLADisplayOrientation>::get_enum_values() {
201     static const t_config_enum_values keys_map = {
202         { "landscape", sladoLandscape},
203         { "portrait",  sladoPortrait}
204     };
205 
206     return keys_map;
207 }
208 
get_enum_values()209 template<> inline const t_config_enum_values& ConfigOptionEnum<SLAPillarConnectionMode>::get_enum_values() {
210     static const t_config_enum_values keys_map = {
211         {"zigzag", slapcmZigZag},
212         {"cross", slapcmCross},
213         {"dynamic", slapcmDynamic}
214     };
215 
216     return keys_map;
217 }
218 
get_enum_values()219 template<> inline const t_config_enum_values& ConfigOptionEnum<ForwardCompatibilitySubstitutionRule>::get_enum_values() {
220     static const t_config_enum_values keys_map = {
221         { "disable",        ForwardCompatibilitySubstitutionRule::Disable },
222         { "enable",         ForwardCompatibilitySubstitutionRule::Enable },
223         { "enable_silent",  ForwardCompatibilitySubstitutionRule::EnableSilent }
224     };
225 
226     return keys_map;
227 }
228 
229 // Defines each and every confiuration option of Slic3r, including the properties of the GUI dialogs.
230 // Does not store the actual values, but defines default values.
231 class PrintConfigDef : public ConfigDef
232 {
233 public:
234     PrintConfigDef();
235 
236     static void handle_legacy(t_config_option_key &opt_key, std::string &value);
237 
238     // Array options growing with the number of extruders
extruder_option_keys() const239     const std::vector<std::string>& extruder_option_keys() const { return m_extruder_option_keys; }
240     // Options defining the extruder retract properties. These keys are sorted lexicographically.
241     // The extruder retract keys could be overidden by the same values defined at the Filament level
242     // (then the key is further prefixed with the "filament_" prefix).
extruder_retract_keys() const243     const std::vector<std::string>& extruder_retract_keys() const { return m_extruder_retract_keys; }
244 
245 private:
246     void init_common_params();
247     void init_fff_params();
248     void init_extruder_option_keys();
249     void init_sla_params();
250 
251     std::vector<std::string> 	m_extruder_option_keys;
252     std::vector<std::string> 	m_extruder_retract_keys;
253 };
254 
255 // The one and only global definition of SLic3r configuration options.
256 // This definition is constant.
257 extern const PrintConfigDef print_config_def;
258 
259 class StaticPrintConfig;
260 
261 PrinterTechnology printer_technology(const ConfigBase &cfg);
262 double min_object_distance(const ConfigBase &cfg);
263 
264 // Slic3r dynamic configuration, used to override the configuration
265 // per object, per modification volume or per printing material.
266 // The dynamic configuration is also used to store user modifications of the print global parameters,
267 // so the modified configuration values may be diffed against the active configuration
268 // to invalidate the proper slicing resp. g-code generation processing steps.
269 // This object is mapped to Perl as Slic3r::Config.
270 class DynamicPrintConfig : public DynamicConfig
271 {
272 public:
DynamicPrintConfig()273     DynamicPrintConfig() {}
DynamicPrintConfig(const DynamicPrintConfig & rhs)274     DynamicPrintConfig(const DynamicPrintConfig &rhs) : DynamicConfig(rhs) {}
DynamicPrintConfig(DynamicPrintConfig && rhs)275     DynamicPrintConfig(DynamicPrintConfig &&rhs) noexcept : DynamicConfig(std::move(rhs)) {}
276     explicit DynamicPrintConfig(const StaticPrintConfig &rhs);
DynamicPrintConfig(const ConfigBase & rhs)277     explicit DynamicPrintConfig(const ConfigBase &rhs) : DynamicConfig(rhs) {}
278 
operator =(const DynamicPrintConfig & rhs)279     DynamicPrintConfig& operator=(const DynamicPrintConfig &rhs) { DynamicConfig::operator=(rhs); return *this; }
operator =(DynamicPrintConfig && rhs)280     DynamicPrintConfig& operator=(DynamicPrintConfig &&rhs) noexcept { DynamicConfig::operator=(std::move(rhs)); return *this; }
281 
282     static DynamicPrintConfig  full_print_config();
283     static DynamicPrintConfig* new_from_defaults_keys(const std::vector<std::string> &keys);
284 
285     // Overrides ConfigBase::def(). Static configuration definition. Any value stored into this ConfigBase shall have its definition here.
def() const286     const ConfigDef*    def() const override { return &print_config_def; }
287 
288     void                normalize_fdm();
289 
290     void 				set_num_extruders(unsigned int num_extruders);
291 
292     // Validate the PrintConfig. Returns an empty string on success, otherwise an error message is returned.
293     std::string         validate();
294 
295     // Verify whether the opt_key has not been obsoleted or renamed.
296     // Both opt_key and value may be modified by handle_legacy().
297     // If the opt_key is no more valid in this version of Slic3r, opt_key is cleared by handle_legacy().
298     // handle_legacy() is called internally by set_deserialize().
handle_legacy(t_config_option_key & opt_key,std::string & value) const299     void                handle_legacy(t_config_option_key &opt_key, std::string &value) const override
300         { PrintConfigDef::handle_legacy(opt_key, value); }
301 };
302 
303 class StaticPrintConfig : public StaticConfig
304 {
305 public:
StaticPrintConfig()306     StaticPrintConfig() {}
307 
308     // Overrides ConfigBase::def(). Static configuration definition. Any value stored into this ConfigBase shall have its definition here.
def() const309     const ConfigDef*    def() const override { return &print_config_def; }
310     // Reference to the cached list of keys.
311 	virtual const t_config_option_keys& keys_ref() const = 0;
312 
313 protected:
314     // Verify whether the opt_key has not been obsoleted or renamed.
315     // Both opt_key and value may be modified by handle_legacy().
316     // If the opt_key is no more valid in this version of Slic3r, opt_key is cleared by handle_legacy().
317     // handle_legacy() is called internally by set_deserialize().
handle_legacy(t_config_option_key & opt_key,std::string & value) const318     void                handle_legacy(t_config_option_key &opt_key, std::string &value) const override
319         { PrintConfigDef::handle_legacy(opt_key, value); }
320 
321     // Internal class for keeping a dynamic map to static options.
322     class StaticCacheBase
323     {
324     public:
325         // To be called during the StaticCache setup.
326         // Add one ConfigOption into m_map_name_to_offset.
327         template<typename T>
opt_add(const std::string & name,const char * base_ptr,const T & opt)328         void                opt_add(const std::string &name, const char *base_ptr, const T &opt)
329         {
330             assert(m_map_name_to_offset.find(name) == m_map_name_to_offset.end());
331             m_map_name_to_offset[name] = (const char*)&opt - base_ptr;
332         }
333 
334     protected:
335         std::map<std::string, ptrdiff_t>    m_map_name_to_offset;
336     };
337 
338     // Parametrized by the type of the topmost class owning the options.
339     template<typename T>
340     class StaticCache : public StaticCacheBase
341     {
342     public:
343         // Calling the constructor of m_defaults with 0 forces m_defaults to not run the initialization.
StaticCache()344         StaticCache() : m_defaults(nullptr) {}
~StaticCache()345         ~StaticCache() { delete m_defaults; m_defaults = nullptr; }
346 
initialized() const347         bool                initialized() const { return ! m_keys.empty(); }
348 
optptr(const std::string & name,T * owner) const349         ConfigOption*       optptr(const std::string &name, T *owner) const
350         {
351             const auto it = m_map_name_to_offset.find(name);
352             return (it == m_map_name_to_offset.end()) ? nullptr : reinterpret_cast<ConfigOption*>((char*)owner + it->second);
353         }
354 
optptr(const std::string & name,const T * owner) const355         const ConfigOption* optptr(const std::string &name, const T *owner) const
356         {
357             const auto it = m_map_name_to_offset.find(name);
358             return (it == m_map_name_to_offset.end()) ? nullptr : reinterpret_cast<const ConfigOption*>((const char*)owner + it->second);
359         }
360 
keys() const361         const std::vector<std::string>& keys()      const { return m_keys; }
defaults() const362         const T&                        defaults()  const { return *m_defaults; }
363 
364         // To be called during the StaticCache setup.
365         // Collect option keys from m_map_name_to_offset,
366         // assign default values to m_defaults.
finalize(T * defaults,const ConfigDef * defs)367         void                finalize(T *defaults, const ConfigDef *defs)
368         {
369             assert(defs != nullptr);
370             m_defaults = defaults;
371             m_keys.clear();
372             m_keys.reserve(m_map_name_to_offset.size());
373             for (const auto &kvp : defs->options) {
374                 // Find the option given the option name kvp.first by an offset from (char*)m_defaults.
375                 ConfigOption *opt = this->optptr(kvp.first, m_defaults);
376                 if (opt == nullptr)
377                     // This option is not defined by the ConfigBase of type T.
378                     continue;
379                 m_keys.emplace_back(kvp.first);
380                 const ConfigOptionDef *def = defs->get(kvp.first);
381                 assert(def != nullptr);
382                 if (def->default_value)
383                     opt->set(def->default_value.get());
384             }
385         }
386 
387     private:
388         T                                  *m_defaults;
389         std::vector<std::string>            m_keys;
390     };
391 };
392 
393 #define STATIC_PRINT_CONFIG_CACHE_BASE(CLASS_NAME) \
394 public: \
395     /* Overrides ConfigBase::optptr(). Find ando/or create a ConfigOption instance for a given name. */ \
396     const ConfigOption*      optptr(const t_config_option_key &opt_key) const override \
397         { return s_cache_##CLASS_NAME.optptr(opt_key, this); } \
398     /* Overrides ConfigBase::optptr(). Find ando/or create a ConfigOption instance for a given name. */ \
399     ConfigOption*            optptr(const t_config_option_key &opt_key, bool create = false) override \
400         { return s_cache_##CLASS_NAME.optptr(opt_key, this); } \
401     /* Overrides ConfigBase::keys(). Collect names of all configuration values maintained by this configuration store. */ \
402     t_config_option_keys     keys() const override { return s_cache_##CLASS_NAME.keys(); } \
403     const t_config_option_keys& keys_ref() const override { return s_cache_##CLASS_NAME.keys(); } \
404     static const CLASS_NAME& defaults() { initialize_cache(); return s_cache_##CLASS_NAME.defaults(); } \
405 private: \
406     static void initialize_cache() \
407     { \
408         if (! s_cache_##CLASS_NAME.initialized()) { \
409             CLASS_NAME *inst = new CLASS_NAME(1); \
410             inst->initialize(s_cache_##CLASS_NAME, (const char*)inst); \
411             s_cache_##CLASS_NAME.finalize(inst, inst->def()); \
412         } \
413     } \
414     /* Cache object holding a key/option map, a list of option keys and a copy of this static config initialized with the defaults. */ \
415     static StaticPrintConfig::StaticCache<CLASS_NAME> s_cache_##CLASS_NAME;
416 
417 #define STATIC_PRINT_CONFIG_CACHE(CLASS_NAME) \
418     STATIC_PRINT_CONFIG_CACHE_BASE(CLASS_NAME) \
419 public: \
420     /* Public default constructor will initialize the key/option cache and the default object copy if needed. */ \
421     CLASS_NAME() { initialize_cache(); *this = s_cache_##CLASS_NAME.defaults(); } \
422 protected: \
423     /* Protected constructor to be called when compounded. */ \
424     CLASS_NAME(int) {}
425 
426 #define STATIC_PRINT_CONFIG_CACHE_DERIVED(CLASS_NAME) \
427     STATIC_PRINT_CONFIG_CACHE_BASE(CLASS_NAME) \
428 public: \
429     /* Overrides ConfigBase::def(). Static configuration definition. Any value stored into this ConfigBase shall have its definition here. */ \
430     const ConfigDef*    def() const override { return &print_config_def; } \
431     /* Handle legacy and obsoleted config keys */ \
432     void                handle_legacy(t_config_option_key &opt_key, std::string &value) const override \
433         { PrintConfigDef::handle_legacy(opt_key, value); }
434 
435 #define OPT_PTR(KEY) cache.opt_add(#KEY, base_ptr, this->KEY)
436 
437 // This object is mapped to Perl as Slic3r::Config::PrintObject.
438 class PrintObjectConfig : public StaticPrintConfig
439 {
440     STATIC_PRINT_CONFIG_CACHE(PrintObjectConfig)
441 public:
442     ConfigOptionBool                clip_multipart_objects;
443     ConfigOptionBool                dont_support_bridges;
444     ConfigOptionFloat               elefant_foot_compensation;
445     ConfigOptionFloatOrPercent      extrusion_width;
446     ConfigOptionFloatOrPercent      first_layer_height;
447     ConfigOptionBool                infill_only_where_needed;
448     // Force the generation of solid shells between adjacent materials/volumes.
449     ConfigOptionBool                interface_shells;
450     ConfigOptionFloat               layer_height;
451     ConfigOptionInt                 raft_layers;
452     ConfigOptionEnum<SeamPosition>  seam_position;
453 //    ConfigOptionFloat               seam_preferred_direction;
454 //    ConfigOptionFloat               seam_preferred_direction_jitter;
455     ConfigOptionFloat               slice_closing_radius;
456     ConfigOptionBool                support_material;
457     // Automatic supports (generated based on support_material_threshold).
458     ConfigOptionBool                support_material_auto;
459     // Direction of the support pattern (in XY plane).
460     ConfigOptionFloat               support_material_angle;
461     ConfigOptionBool                support_material_buildplate_only;
462     ConfigOptionFloat               support_material_contact_distance;
463     ConfigOptionInt                 support_material_enforce_layers;
464     ConfigOptionInt                 support_material_extruder;
465     ConfigOptionFloatOrPercent      support_material_extrusion_width;
466     ConfigOptionBool                support_material_interface_contact_loops;
467     ConfigOptionInt                 support_material_interface_extruder;
468     ConfigOptionInt                 support_material_interface_layers;
469     // Spacing between interface lines (the hatching distance). Set zero to get a solid interface.
470     ConfigOptionFloat               support_material_interface_spacing;
471     ConfigOptionFloatOrPercent      support_material_interface_speed;
472     ConfigOptionEnum<SupportMaterialPattern> support_material_pattern;
473     // Spacing between support material lines (the hatching distance).
474     ConfigOptionFloat               support_material_spacing;
475     ConfigOptionFloat               support_material_speed;
476     ConfigOptionBool                support_material_synchronize_layers;
477     // Overhang angle threshold.
478     ConfigOptionInt                 support_material_threshold;
479     ConfigOptionBool                support_material_with_sheath;
480     ConfigOptionFloatOrPercent      support_material_xy_spacing;
481     ConfigOptionFloat               xy_size_compensation;
482     ConfigOptionBool                wipe_into_objects;
483 
484 protected:
initialize(StaticCacheBase & cache,const char * base_ptr)485     void initialize(StaticCacheBase &cache, const char *base_ptr)
486     {
487         OPT_PTR(clip_multipart_objects);
488         OPT_PTR(dont_support_bridges);
489         OPT_PTR(elefant_foot_compensation);
490         OPT_PTR(extrusion_width);
491         OPT_PTR(first_layer_height);
492         OPT_PTR(infill_only_where_needed);
493         OPT_PTR(interface_shells);
494         OPT_PTR(layer_height);
495         OPT_PTR(raft_layers);
496         OPT_PTR(seam_position);
497         OPT_PTR(slice_closing_radius);
498 //        OPT_PTR(seam_preferred_direction);
499 //        OPT_PTR(seam_preferred_direction_jitter);
500         OPT_PTR(support_material);
501         OPT_PTR(support_material_auto);
502         OPT_PTR(support_material_angle);
503         OPT_PTR(support_material_buildplate_only);
504         OPT_PTR(support_material_contact_distance);
505         OPT_PTR(support_material_enforce_layers);
506         OPT_PTR(support_material_interface_contact_loops);
507         OPT_PTR(support_material_extruder);
508         OPT_PTR(support_material_extrusion_width);
509         OPT_PTR(support_material_interface_extruder);
510         OPT_PTR(support_material_interface_layers);
511         OPT_PTR(support_material_interface_spacing);
512         OPT_PTR(support_material_interface_speed);
513         OPT_PTR(support_material_pattern);
514         OPT_PTR(support_material_spacing);
515         OPT_PTR(support_material_speed);
516         OPT_PTR(support_material_synchronize_layers);
517         OPT_PTR(support_material_xy_spacing);
518         OPT_PTR(support_material_threshold);
519         OPT_PTR(support_material_with_sheath);
520         OPT_PTR(xy_size_compensation);
521         OPT_PTR(wipe_into_objects);
522     }
523 };
524 
525 // This object is mapped to Perl as Slic3r::Config::PrintRegion.
526 class PrintRegionConfig : public StaticPrintConfig
527 {
528     STATIC_PRINT_CONFIG_CACHE(PrintRegionConfig)
529 public:
530     ConfigOptionFloat               bridge_angle;
531     ConfigOptionInt                 bottom_solid_layers;
532     ConfigOptionFloat               bottom_solid_min_thickness;
533     ConfigOptionFloat               bridge_flow_ratio;
534     ConfigOptionFloat               bridge_speed;
535     ConfigOptionBool                ensure_vertical_shell_thickness;
536     ConfigOptionEnum<InfillPattern> top_fill_pattern;
537     ConfigOptionEnum<InfillPattern> bottom_fill_pattern;
538     ConfigOptionFloatOrPercent      external_perimeter_extrusion_width;
539     ConfigOptionFloatOrPercent      external_perimeter_speed;
540     ConfigOptionBool                external_perimeters_first;
541     ConfigOptionBool                extra_perimeters;
542     ConfigOptionFloat               fill_angle;
543     ConfigOptionPercent             fill_density;
544     ConfigOptionEnum<InfillPattern> fill_pattern;
545     ConfigOptionFloat               gap_fill_speed;
546     ConfigOptionFloatOrPercent      infill_anchor;
547     ConfigOptionFloatOrPercent      infill_anchor_max;
548     ConfigOptionInt                 infill_extruder;
549     ConfigOptionFloatOrPercent      infill_extrusion_width;
550     ConfigOptionInt                 infill_every_layers;
551     ConfigOptionFloatOrPercent      infill_overlap;
552     ConfigOptionFloat               infill_speed;
553     // Ironing options
554     ConfigOptionBool 				ironing;
555     ConfigOptionEnum<IroningType> 	ironing_type;
556     ConfigOptionPercent 			ironing_flowrate;
557     ConfigOptionFloat 				ironing_spacing;
558     ConfigOptionFloat 				ironing_speed;
559     // Detect bridging perimeters
560     ConfigOptionBool                overhangs;
561     ConfigOptionInt                 perimeter_extruder;
562     ConfigOptionFloatOrPercent      perimeter_extrusion_width;
563     ConfigOptionFloat               perimeter_speed;
564     // Total number of perimeters.
565     ConfigOptionInt                 perimeters;
566     ConfigOptionFloatOrPercent      small_perimeter_speed;
567     ConfigOptionFloat               solid_infill_below_area;
568     ConfigOptionInt                 solid_infill_extruder;
569     ConfigOptionFloatOrPercent      solid_infill_extrusion_width;
570     ConfigOptionInt                 solid_infill_every_layers;
571     ConfigOptionFloatOrPercent      solid_infill_speed;
572     // Detect thin walls.
573     ConfigOptionBool                thin_walls;
574     ConfigOptionFloatOrPercent      top_infill_extrusion_width;
575     ConfigOptionInt                 top_solid_layers;
576     ConfigOptionFloat 				top_solid_min_thickness;
577     ConfigOptionFloatOrPercent      top_solid_infill_speed;
578     ConfigOptionBool                wipe_into_infill;
579 
580 protected:
initialize(StaticCacheBase & cache,const char * base_ptr)581     void initialize(StaticCacheBase &cache, const char *base_ptr)
582     {
583         OPT_PTR(bridge_angle);
584         OPT_PTR(bottom_solid_layers);
585         OPT_PTR(bottom_solid_min_thickness);
586         OPT_PTR(bridge_flow_ratio);
587         OPT_PTR(bridge_speed);
588         OPT_PTR(ensure_vertical_shell_thickness);
589         OPT_PTR(top_fill_pattern);
590         OPT_PTR(bottom_fill_pattern);
591         OPT_PTR(external_perimeter_extrusion_width);
592         OPT_PTR(external_perimeter_speed);
593         OPT_PTR(external_perimeters_first);
594         OPT_PTR(extra_perimeters);
595         OPT_PTR(fill_angle);
596         OPT_PTR(fill_density);
597         OPT_PTR(fill_pattern);
598         OPT_PTR(gap_fill_speed);
599         OPT_PTR(infill_anchor);
600         OPT_PTR(infill_anchor_max);
601         OPT_PTR(infill_extruder);
602         OPT_PTR(infill_extrusion_width);
603         OPT_PTR(infill_every_layers);
604         OPT_PTR(infill_overlap);
605         OPT_PTR(infill_speed);
606         OPT_PTR(ironing);
607         OPT_PTR(ironing_type);
608         OPT_PTR(ironing_flowrate);
609         OPT_PTR(ironing_spacing);
610         OPT_PTR(ironing_speed);
611         OPT_PTR(overhangs);
612         OPT_PTR(perimeter_extruder);
613         OPT_PTR(perimeter_extrusion_width);
614         OPT_PTR(perimeter_speed);
615         OPT_PTR(perimeters);
616         OPT_PTR(small_perimeter_speed);
617         OPT_PTR(solid_infill_below_area);
618         OPT_PTR(solid_infill_extruder);
619         OPT_PTR(solid_infill_extrusion_width);
620         OPT_PTR(solid_infill_every_layers);
621         OPT_PTR(solid_infill_speed);
622         OPT_PTR(thin_walls);
623         OPT_PTR(top_infill_extrusion_width);
624         OPT_PTR(top_solid_infill_speed);
625         OPT_PTR(top_solid_layers);
626         OPT_PTR(top_solid_min_thickness);
627         OPT_PTR(wipe_into_infill);
628     }
629 };
630 
631 class MachineEnvelopeConfig : public StaticPrintConfig
632 {
633     STATIC_PRINT_CONFIG_CACHE(MachineEnvelopeConfig)
634 public:
635 	// Allowing the machine limits to be completely ignored or used just for time estimator.
636     ConfigOptionEnum<MachineLimitsUsage> machine_limits_usage;
637     // M201 X... Y... Z... E... [mm/sec^2]
638     ConfigOptionFloats              machine_max_acceleration_x;
639     ConfigOptionFloats              machine_max_acceleration_y;
640     ConfigOptionFloats              machine_max_acceleration_z;
641     ConfigOptionFloats              machine_max_acceleration_e;
642     // M203 X... Y... Z... E... [mm/sec]
643     ConfigOptionFloats              machine_max_feedrate_x;
644     ConfigOptionFloats              machine_max_feedrate_y;
645     ConfigOptionFloats              machine_max_feedrate_z;
646     ConfigOptionFloats              machine_max_feedrate_e;
647     // M204 S... [mm/sec^2]
648     ConfigOptionFloats              machine_max_acceleration_extruding;
649     // M204 T... [mm/sec^2]
650     ConfigOptionFloats              machine_max_acceleration_retracting;
651     // M205 X... Y... Z... E... [mm/sec]
652     ConfigOptionFloats              machine_max_jerk_x;
653     ConfigOptionFloats              machine_max_jerk_y;
654     ConfigOptionFloats              machine_max_jerk_z;
655     ConfigOptionFloats              machine_max_jerk_e;
656     // M205 T... [mm/sec]
657     ConfigOptionFloats              machine_min_travel_rate;
658     // M205 S... [mm/sec]
659     ConfigOptionFloats              machine_min_extruding_rate;
660 
661 protected:
initialize(StaticCacheBase & cache,const char * base_ptr)662     void initialize(StaticCacheBase &cache, const char *base_ptr)
663     {
664         OPT_PTR(machine_limits_usage);
665         OPT_PTR(machine_max_acceleration_x);
666         OPT_PTR(machine_max_acceleration_y);
667         OPT_PTR(machine_max_acceleration_z);
668         OPT_PTR(machine_max_acceleration_e);
669         OPT_PTR(machine_max_feedrate_x);
670         OPT_PTR(machine_max_feedrate_y);
671         OPT_PTR(machine_max_feedrate_z);
672         OPT_PTR(machine_max_feedrate_e);
673         OPT_PTR(machine_max_acceleration_extruding);
674         OPT_PTR(machine_max_acceleration_retracting);
675         OPT_PTR(machine_max_jerk_x);
676         OPT_PTR(machine_max_jerk_y);
677         OPT_PTR(machine_max_jerk_z);
678         OPT_PTR(machine_max_jerk_e);
679         OPT_PTR(machine_min_travel_rate);
680         OPT_PTR(machine_min_extruding_rate);
681     }
682 };
683 
684 // This object is mapped to Perl as Slic3r::Config::GCode.
685 class GCodeConfig : public StaticPrintConfig
686 {
687     STATIC_PRINT_CONFIG_CACHE(GCodeConfig)
688 public:
689     ConfigOptionString              before_layer_gcode;
690     ConfigOptionString              between_objects_gcode;
691     ConfigOptionFloats              deretract_speed;
692     ConfigOptionString              end_gcode;
693     ConfigOptionStrings             end_filament_gcode;
694     ConfigOptionString              extrusion_axis;
695     ConfigOptionFloats              extrusion_multiplier;
696     ConfigOptionFloats              filament_diameter;
697     ConfigOptionFloats              filament_density;
698     ConfigOptionStrings             filament_type;
699     ConfigOptionBools               filament_soluble;
700     ConfigOptionFloats              filament_cost;
701     ConfigOptionFloats              filament_spool_weight;
702     ConfigOptionFloats              filament_max_volumetric_speed;
703     ConfigOptionFloats              filament_loading_speed;
704     ConfigOptionFloats              filament_loading_speed_start;
705     ConfigOptionFloats              filament_load_time;
706     ConfigOptionFloats              filament_unloading_speed;
707     ConfigOptionFloats              filament_unloading_speed_start;
708     ConfigOptionFloats              filament_toolchange_delay;
709     ConfigOptionFloats              filament_unload_time;
710     ConfigOptionInts                filament_cooling_moves;
711     ConfigOptionFloats              filament_cooling_initial_speed;
712     ConfigOptionFloats              filament_minimal_purge_on_wipe_tower;
713     ConfigOptionFloats              filament_cooling_final_speed;
714     ConfigOptionStrings             filament_ramming_parameters;
715     ConfigOptionBool                gcode_comments;
716     ConfigOptionEnum<GCodeFlavor>   gcode_flavor;
717     ConfigOptionBool                gcode_label_objects;
718     ConfigOptionString              layer_gcode;
719     ConfigOptionFloat               max_print_speed;
720     ConfigOptionFloat               max_volumetric_speed;
721 #ifdef HAS_PRESSURE_EQUALIZER
722     ConfigOptionFloat               max_volumetric_extrusion_rate_slope_positive;
723     ConfigOptionFloat               max_volumetric_extrusion_rate_slope_negative;
724 #endif
725     ConfigOptionPercents            retract_before_wipe;
726     ConfigOptionFloats              retract_length;
727     ConfigOptionFloats              retract_length_toolchange;
728     ConfigOptionFloats              retract_lift;
729     ConfigOptionFloats              retract_lift_above;
730     ConfigOptionFloats              retract_lift_below;
731     ConfigOptionFloats              retract_restart_extra;
732     ConfigOptionFloats              retract_restart_extra_toolchange;
733     ConfigOptionFloats              retract_speed;
734     ConfigOptionString              start_gcode;
735     ConfigOptionStrings             start_filament_gcode;
736     ConfigOptionBool                single_extruder_multi_material;
737     ConfigOptionBool                single_extruder_multi_material_priming;
738     ConfigOptionBool                wipe_tower_no_sparse_layers;
739     ConfigOptionString              toolchange_gcode;
740     ConfigOptionFloat               travel_speed;
741     ConfigOptionBool                use_firmware_retraction;
742     ConfigOptionBool                use_relative_e_distances;
743     ConfigOptionBool                use_volumetric_e;
744     ConfigOptionBool                variable_layer_height;
745     ConfigOptionFloat               cooling_tube_retraction;
746     ConfigOptionFloat               cooling_tube_length;
747     ConfigOptionBool                high_current_on_filament_swap;
748     ConfigOptionFloat               parking_pos_retraction;
749     ConfigOptionBool                remaining_times;
750     ConfigOptionBool                silent_mode;
751     ConfigOptionFloat               extra_loading_move;
752     ConfigOptionString              color_change_gcode;
753     ConfigOptionString              pause_print_gcode;
754     ConfigOptionString              template_custom_gcode;
755 
get_extrusion_axis() const756     std::string get_extrusion_axis() const
757     {
758         return
759             ((this->gcode_flavor.value == gcfMach3) || (this->gcode_flavor.value == gcfMachinekit)) ? "A" :
760             (this->gcode_flavor.value == gcfNoExtrusion) ? "" : this->extrusion_axis.value;
761     }
762 
763 protected:
initialize(StaticCacheBase & cache,const char * base_ptr)764     void initialize(StaticCacheBase &cache, const char *base_ptr)
765     {
766         OPT_PTR(before_layer_gcode);
767         OPT_PTR(between_objects_gcode);
768         OPT_PTR(deretract_speed);
769         OPT_PTR(end_gcode);
770         OPT_PTR(end_filament_gcode);
771         OPT_PTR(extrusion_axis);
772         OPT_PTR(extrusion_multiplier);
773         OPT_PTR(filament_diameter);
774         OPT_PTR(filament_density);
775         OPT_PTR(filament_type);
776         OPT_PTR(filament_soluble);
777         OPT_PTR(filament_cost);
778         OPT_PTR(filament_spool_weight);
779         OPT_PTR(filament_max_volumetric_speed);
780         OPT_PTR(filament_loading_speed);
781         OPT_PTR(filament_loading_speed_start);
782         OPT_PTR(filament_load_time);
783         OPT_PTR(filament_unloading_speed);
784         OPT_PTR(filament_unloading_speed_start);
785         OPT_PTR(filament_unload_time);
786         OPT_PTR(filament_toolchange_delay);
787         OPT_PTR(filament_cooling_moves);
788         OPT_PTR(filament_cooling_initial_speed);
789         OPT_PTR(filament_minimal_purge_on_wipe_tower);
790         OPT_PTR(filament_cooling_final_speed);
791         OPT_PTR(filament_ramming_parameters);
792         OPT_PTR(gcode_comments);
793         OPT_PTR(gcode_flavor);
794         OPT_PTR(gcode_label_objects);
795         OPT_PTR(layer_gcode);
796         OPT_PTR(max_print_speed);
797         OPT_PTR(max_volumetric_speed);
798 #ifdef HAS_PRESSURE_EQUALIZER
799         OPT_PTR(max_volumetric_extrusion_rate_slope_positive);
800         OPT_PTR(max_volumetric_extrusion_rate_slope_negative);
801 #endif /* HAS_PRESSURE_EQUALIZER */
802         OPT_PTR(retract_before_wipe);
803         OPT_PTR(retract_length);
804         OPT_PTR(retract_length_toolchange);
805         OPT_PTR(retract_lift);
806         OPT_PTR(retract_lift_above);
807         OPT_PTR(retract_lift_below);
808         OPT_PTR(retract_restart_extra);
809         OPT_PTR(retract_restart_extra_toolchange);
810         OPT_PTR(retract_speed);
811         OPT_PTR(single_extruder_multi_material);
812         OPT_PTR(single_extruder_multi_material_priming);
813         OPT_PTR(wipe_tower_no_sparse_layers);
814         OPT_PTR(start_gcode);
815         OPT_PTR(start_filament_gcode);
816         OPT_PTR(toolchange_gcode);
817         OPT_PTR(travel_speed);
818         OPT_PTR(use_firmware_retraction);
819         OPT_PTR(use_relative_e_distances);
820         OPT_PTR(use_volumetric_e);
821         OPT_PTR(variable_layer_height);
822         OPT_PTR(cooling_tube_retraction);
823         OPT_PTR(cooling_tube_length);
824         OPT_PTR(high_current_on_filament_swap);
825         OPT_PTR(parking_pos_retraction);
826         OPT_PTR(remaining_times);
827         OPT_PTR(silent_mode);
828         OPT_PTR(extra_loading_move);
829         OPT_PTR(color_change_gcode);
830         OPT_PTR(pause_print_gcode);
831         OPT_PTR(template_custom_gcode);
832     }
833 };
834 
835 // This object is mapped to Perl as Slic3r::Config::Print.
836 class PrintConfig : public MachineEnvelopeConfig, public GCodeConfig
837 {
838     STATIC_PRINT_CONFIG_CACHE_DERIVED(PrintConfig)
PrintConfig()839     PrintConfig() : MachineEnvelopeConfig(0), GCodeConfig(0) { initialize_cache(); *this = s_cache_PrintConfig.defaults(); }
840 public:
841 
842     ConfigOptionBool                avoid_crossing_perimeters;
843     ConfigOptionFloatOrPercent      avoid_crossing_perimeters_max_detour;
844     ConfigOptionPoints              bed_shape;
845     ConfigOptionInts                bed_temperature;
846     ConfigOptionFloat               bridge_acceleration;
847     ConfigOptionInts                bridge_fan_speed;
848     ConfigOptionFloat               brim_width;
849     ConfigOptionBool                complete_objects;
850     ConfigOptionFloats              colorprint_heights;
851     ConfigOptionBools               cooling;
852     ConfigOptionFloat               default_acceleration;
853     ConfigOptionInts                disable_fan_first_layers;
854     ConfigOptionFloat               duplicate_distance;
855     ConfigOptionFloat               extruder_clearance_height;
856     ConfigOptionFloat               extruder_clearance_radius;
857     ConfigOptionStrings             extruder_colour;
858     ConfigOptionPoints              extruder_offset;
859     ConfigOptionBools               fan_always_on;
860     ConfigOptionInts                fan_below_layer_time;
861     ConfigOptionStrings             filament_colour;
862     ConfigOptionStrings             filament_notes;
863     ConfigOptionFloat               first_layer_acceleration;
864     ConfigOptionInts                first_layer_bed_temperature;
865     ConfigOptionFloatOrPercent      first_layer_extrusion_width;
866     ConfigOptionFloatOrPercent      first_layer_speed;
867     ConfigOptionInts                first_layer_temperature;
868     ConfigOptionInts                full_fan_speed_layer;
869     ConfigOptionFloat               infill_acceleration;
870     ConfigOptionBool                infill_first;
871     ConfigOptionInts                max_fan_speed;
872     ConfigOptionFloats              max_layer_height;
873     ConfigOptionInts                min_fan_speed;
874     ConfigOptionFloats              min_layer_height;
875     ConfigOptionFloat               max_print_height;
876     ConfigOptionFloats              min_print_speed;
877     ConfigOptionFloat               min_skirt_length;
878     ConfigOptionString              notes;
879     ConfigOptionFloats              nozzle_diameter;
880     ConfigOptionBool                only_retract_when_crossing_perimeters;
881     ConfigOptionBool                ooze_prevention;
882     ConfigOptionString              output_filename_format;
883     ConfigOptionFloat               perimeter_acceleration;
884     ConfigOptionStrings             post_process;
885     ConfigOptionString              printer_model;
886     ConfigOptionString              printer_notes;
887     ConfigOptionFloat               resolution;
888     ConfigOptionFloats              retract_before_travel;
889     ConfigOptionBools               retract_layer_change;
890     ConfigOptionFloat               skirt_distance;
891     ConfigOptionInt                 skirt_height;
892     ConfigOptionBool                draft_shield;
893     ConfigOptionInt                 skirts;
894     ConfigOptionInts                slowdown_below_layer_time;
895     ConfigOptionBool                spiral_vase;
896     ConfigOptionInt                 standby_temperature_delta;
897     ConfigOptionInts                temperature;
898     ConfigOptionInt                 threads;
899     ConfigOptionBools               wipe;
900     ConfigOptionBool                wipe_tower;
901     ConfigOptionFloat               wipe_tower_x;
902     ConfigOptionFloat               wipe_tower_y;
903     ConfigOptionFloat               wipe_tower_width;
904     ConfigOptionFloat               wipe_tower_per_color_wipe;
905     ConfigOptionFloat               wipe_tower_rotation_angle;
906     ConfigOptionFloat               wipe_tower_bridging;
907     ConfigOptionFloats              wiping_volumes_matrix;
908     ConfigOptionFloats              wiping_volumes_extruders;
909     ConfigOptionFloat               z_offset;
910 
911 protected:
PrintConfig(int)912     PrintConfig(int) : MachineEnvelopeConfig(1), GCodeConfig(1) {}
initialize(StaticCacheBase & cache,const char * base_ptr)913     void initialize(StaticCacheBase &cache, const char *base_ptr)
914     {
915         this->MachineEnvelopeConfig::initialize(cache, base_ptr);
916         this->GCodeConfig::initialize(cache, base_ptr);
917         OPT_PTR(avoid_crossing_perimeters);
918         OPT_PTR(avoid_crossing_perimeters_max_detour);
919         OPT_PTR(bed_shape);
920         OPT_PTR(bed_temperature);
921         OPT_PTR(bridge_acceleration);
922         OPT_PTR(bridge_fan_speed);
923         OPT_PTR(brim_width);
924         OPT_PTR(complete_objects);
925         OPT_PTR(colorprint_heights);
926         OPT_PTR(cooling);
927         OPT_PTR(default_acceleration);
928         OPT_PTR(disable_fan_first_layers);
929         OPT_PTR(duplicate_distance);
930         OPT_PTR(extruder_clearance_height);
931         OPT_PTR(extruder_clearance_radius);
932         OPT_PTR(extruder_colour);
933         OPT_PTR(extruder_offset);
934         OPT_PTR(fan_always_on);
935         OPT_PTR(fan_below_layer_time);
936         OPT_PTR(filament_colour);
937         OPT_PTR(filament_notes);
938         OPT_PTR(first_layer_acceleration);
939         OPT_PTR(first_layer_bed_temperature);
940         OPT_PTR(first_layer_extrusion_width);
941         OPT_PTR(first_layer_speed);
942         OPT_PTR(first_layer_temperature);
943         OPT_PTR(full_fan_speed_layer);
944         OPT_PTR(infill_acceleration);
945         OPT_PTR(infill_first);
946         OPT_PTR(max_fan_speed);
947         OPT_PTR(max_layer_height);
948         OPT_PTR(min_fan_speed);
949         OPT_PTR(min_layer_height);
950         OPT_PTR(max_print_height);
951         OPT_PTR(min_print_speed);
952         OPT_PTR(min_skirt_length);
953         OPT_PTR(notes);
954         OPT_PTR(nozzle_diameter);
955         OPT_PTR(only_retract_when_crossing_perimeters);
956         OPT_PTR(ooze_prevention);
957         OPT_PTR(output_filename_format);
958         OPT_PTR(perimeter_acceleration);
959         OPT_PTR(post_process);
960         OPT_PTR(printer_model);
961         OPT_PTR(printer_notes);
962         OPT_PTR(resolution);
963         OPT_PTR(retract_before_travel);
964         OPT_PTR(retract_layer_change);
965         OPT_PTR(skirt_distance);
966         OPT_PTR(skirt_height);
967         OPT_PTR(draft_shield);
968         OPT_PTR(skirts);
969         OPT_PTR(slowdown_below_layer_time);
970         OPT_PTR(spiral_vase);
971         OPT_PTR(standby_temperature_delta);
972         OPT_PTR(temperature);
973         OPT_PTR(threads);
974         OPT_PTR(wipe);
975         OPT_PTR(wipe_tower);
976         OPT_PTR(wipe_tower_x);
977         OPT_PTR(wipe_tower_y);
978         OPT_PTR(wipe_tower_width);
979         OPT_PTR(wipe_tower_per_color_wipe);
980         OPT_PTR(wipe_tower_rotation_angle);
981         OPT_PTR(wipe_tower_bridging);
982         OPT_PTR(wiping_volumes_matrix);
983         OPT_PTR(wiping_volumes_extruders);
984         OPT_PTR(z_offset);
985     }
986 };
987 
988 // This object is mapped to Perl as Slic3r::Config::Full.
989 class FullPrintConfig :
990     public PrintObjectConfig,
991     public PrintRegionConfig,
992     public PrintConfig
993 {
994     STATIC_PRINT_CONFIG_CACHE_DERIVED(FullPrintConfig)
FullPrintConfig()995     FullPrintConfig() : PrintObjectConfig(0), PrintRegionConfig(0), PrintConfig(0) { initialize_cache(); *this = s_cache_FullPrintConfig.defaults(); }
996 
997 public:
998     // Validate the FullPrintConfig. Returns an empty string on success, otherwise an error message is returned.
999     std::string                 validate();
1000 
1001 protected:
1002     // Protected constructor to be called to initialize ConfigCache::m_default.
FullPrintConfig(int)1003     FullPrintConfig(int) : PrintObjectConfig(0), PrintRegionConfig(0), PrintConfig(0) {}
initialize(StaticCacheBase & cache,const char * base_ptr)1004     void initialize(StaticCacheBase &cache, const char *base_ptr)
1005     {
1006         this->PrintObjectConfig::initialize(cache, base_ptr);
1007         this->PrintRegionConfig::initialize(cache, base_ptr);
1008         this->PrintConfig      ::initialize(cache, base_ptr);
1009     }
1010 };
1011 
1012 // This object is mapped to Perl as Slic3r::Config::PrintRegion.
1013 class SLAPrintConfig : public StaticPrintConfig
1014 {
1015     STATIC_PRINT_CONFIG_CACHE(SLAPrintConfig)
1016 public:
1017     ConfigOptionString     output_filename_format;
1018 
1019 protected:
initialize(StaticCacheBase & cache,const char * base_ptr)1020     void initialize(StaticCacheBase &cache, const char *base_ptr)
1021     {
1022         OPT_PTR(output_filename_format);
1023     }
1024 };
1025 
1026 class SLAPrintObjectConfig : public StaticPrintConfig
1027 {
1028     STATIC_PRINT_CONFIG_CACHE(SLAPrintObjectConfig)
1029 public:
1030     ConfigOptionFloat layer_height;
1031 
1032     //Number of the layers needed for the exposure time fade [3;20]
1033     ConfigOptionInt  faded_layers /*= 10*/;
1034 
1035     ConfigOptionFloat slice_closing_radius;
1036 
1037     // Enabling or disabling support creation
1038     ConfigOptionBool  supports_enable;
1039 
1040     // Diameter in mm of the pointing side of the head.
1041     ConfigOptionFloat support_head_front_diameter /*= 0.2*/;
1042 
1043     // How much the pinhead has to penetrate the model surface
1044     ConfigOptionFloat support_head_penetration /*= 0.2*/;
1045 
1046     // Width in mm from the back sphere center to the front sphere center.
1047     ConfigOptionFloat support_head_width /*= 1.0*/;
1048 
1049     // Radius in mm of the support pillars.
1050     ConfigOptionFloat support_pillar_diameter /*= 0.8*/;
1051 
1052     // The percentage of smaller pillars compared to the normal pillar diameter
1053     // which are used in problematic areas where a normal pilla cannot fit.
1054     ConfigOptionPercent support_small_pillar_diameter_percent;
1055 
1056     // How much bridge (supporting another pinhead) can be placed on a pillar.
1057     ConfigOptionInt   support_max_bridges_on_pillar;
1058 
1059     // How the pillars are bridged together
1060     ConfigOptionEnum<SLAPillarConnectionMode> support_pillar_connection_mode;
1061 
1062     // Generate only ground facing supports
1063     ConfigOptionBool support_buildplate_only;
1064 
1065     // TODO: unimplemented at the moment. This coefficient will have an impact
1066     // when bridges and pillars are merged. The resulting pillar should be a bit
1067     // thicker than the ones merging into it. How much thicker? I don't know
1068     // but it will be derived from this value.
1069     ConfigOptionFloat support_pillar_widening_factor;
1070 
1071     // Radius in mm of the pillar base.
1072     ConfigOptionFloat support_base_diameter /*= 2.0*/;
1073 
1074     // The height of the pillar base cone in mm.
1075     ConfigOptionFloat support_base_height /*= 1.0*/;
1076 
1077     // The minimum distance of the pillar base from the model in mm.
1078     ConfigOptionFloat support_base_safety_distance; /*= 1.0*/
1079 
1080     // The default angle for connecting support sticks and junctions.
1081     ConfigOptionFloat support_critical_angle /*= 45*/;
1082 
1083     // The max length of a bridge in mm
1084     ConfigOptionFloat support_max_bridge_length /*= 15.0*/;
1085 
1086     // The max distance of two pillars to get cross linked.
1087     ConfigOptionFloat support_max_pillar_link_distance;
1088 
1089     // The elevation in Z direction upwards. This is the space between the pad
1090     // and the model object's bounding box bottom. Units in mm.
1091     ConfigOptionFloat support_object_elevation /*= 5.0*/;
1092 
1093     /////// Following options influence automatic support points placement:
1094     ConfigOptionInt support_points_density_relative;
1095     ConfigOptionFloat support_points_minimal_distance;
1096 
1097     // Now for the base pool (pad) /////////////////////////////////////////////
1098 
1099     // Enabling or disabling support creation
1100     ConfigOptionBool  pad_enable;
1101 
1102     // The thickness of the pad walls
1103     ConfigOptionFloat pad_wall_thickness /*= 2*/;
1104 
1105     // The height of the pad from the bottom to the top not considering the pit
1106     ConfigOptionFloat pad_wall_height /*= 5*/;
1107 
1108     // How far should the pad extend around the contained geometry
1109     ConfigOptionFloat pad_brim_size;
1110 
1111     // The greatest distance where two individual pads are merged into one. The
1112     // distance is measured roughly from the centroids of the pads.
1113     ConfigOptionFloat pad_max_merge_distance /*= 50*/;
1114 
1115     // The smoothing radius of the pad edges
1116     // ConfigOptionFloat pad_edge_radius /*= 1*/;
1117 
1118     // The slope of the pad wall...
1119     ConfigOptionFloat pad_wall_slope;
1120 
1121     // /////////////////////////////////////////////////////////////////////////
1122     // Zero elevation mode parameters:
1123     //    - The object pad will be derived from the model geometry.
1124     //    - There will be a gap between the object pad and the generated pad
1125     //      according to the support_base_safety_distance parameter.
1126     //    - The two pads will be connected with tiny connector sticks
1127     // /////////////////////////////////////////////////////////////////////////
1128 
1129     // Disable the elevation (ignore its value) and use the zero elevation mode
1130     ConfigOptionBool pad_around_object;
1131 
1132     ConfigOptionBool pad_around_object_everywhere;
1133 
1134     // This is the gap between the object bottom and the generated pad
1135     ConfigOptionFloat pad_object_gap;
1136 
1137     // How far to place the connector sticks on the object pad perimeter
1138     ConfigOptionFloat pad_object_connector_stride;
1139 
1140     // The width of the connectors sticks
1141     ConfigOptionFloat pad_object_connector_width;
1142 
1143     // How much should the tiny connectors penetrate into the model body
1144     ConfigOptionFloat pad_object_connector_penetration;
1145 
1146     // /////////////////////////////////////////////////////////////////////////
1147     // Model hollowing parameters:
1148     //   - Models can be hollowed out as part of the SLA print process
1149     //   - Thickness of the hollowed model walls can be adjusted
1150     //   -
1151     //   - Additional holes will be drilled into the hollow model to allow for
1152     //   - resin removal.
1153     // /////////////////////////////////////////////////////////////////////////
1154 
1155     ConfigOptionBool hollowing_enable;
1156 
1157     // The minimum thickness of the model walls to maintain. Note that the
1158     // resulting walls may be thicker due to smoothing out fine cavities where
1159     // resin could stuck.
1160     ConfigOptionFloat hollowing_min_thickness;
1161 
1162     // Indirectly controls the voxel size (resolution) used by openvdb
1163     ConfigOptionFloat hollowing_quality;
1164 
1165     // Indirectly controls the minimum size of created cavities.
1166     ConfigOptionFloat hollowing_closing_distance;
1167 
1168 protected:
initialize(StaticCacheBase & cache,const char * base_ptr)1169     void initialize(StaticCacheBase &cache, const char *base_ptr)
1170     {
1171         OPT_PTR(layer_height);
1172         OPT_PTR(faded_layers);
1173         OPT_PTR(slice_closing_radius);
1174         OPT_PTR(supports_enable);
1175         OPT_PTR(support_head_front_diameter);
1176         OPT_PTR(support_head_penetration);
1177         OPT_PTR(support_head_width);
1178         OPT_PTR(support_pillar_diameter);
1179         OPT_PTR(support_small_pillar_diameter_percent);
1180         OPT_PTR(support_max_bridges_on_pillar);
1181         OPT_PTR(support_pillar_connection_mode);
1182         OPT_PTR(support_buildplate_only);
1183         OPT_PTR(support_pillar_widening_factor);
1184         OPT_PTR(support_base_diameter);
1185         OPT_PTR(support_base_height);
1186         OPT_PTR(support_base_safety_distance);
1187         OPT_PTR(support_critical_angle);
1188         OPT_PTR(support_max_bridge_length);
1189         OPT_PTR(support_max_pillar_link_distance);
1190         OPT_PTR(support_points_density_relative);
1191         OPT_PTR(support_points_minimal_distance);
1192         OPT_PTR(support_object_elevation);
1193         OPT_PTR(pad_enable);
1194         OPT_PTR(pad_wall_thickness);
1195         OPT_PTR(pad_wall_height);
1196         OPT_PTR(pad_brim_size);
1197         OPT_PTR(pad_max_merge_distance);
1198         // OPT_PTR(pad_edge_radius);
1199         OPT_PTR(pad_wall_slope);
1200         OPT_PTR(pad_around_object);
1201         OPT_PTR(pad_around_object_everywhere);
1202         OPT_PTR(pad_object_gap);
1203         OPT_PTR(pad_object_connector_stride);
1204         OPT_PTR(pad_object_connector_width);
1205         OPT_PTR(pad_object_connector_penetration);
1206         OPT_PTR(hollowing_enable);
1207         OPT_PTR(hollowing_min_thickness);
1208         OPT_PTR(hollowing_quality);
1209         OPT_PTR(hollowing_closing_distance);
1210     }
1211 };
1212 
1213 class SLAMaterialConfig : public StaticPrintConfig
1214 {
1215     STATIC_PRINT_CONFIG_CACHE(SLAMaterialConfig)
1216 public:
1217     ConfigOptionFloat                       initial_layer_height;
1218     ConfigOptionFloat                       bottle_cost;
1219     ConfigOptionFloat                       bottle_volume;
1220     ConfigOptionFloat                       bottle_weight;
1221     ConfigOptionFloat                       material_density;
1222     ConfigOptionFloat                       exposure_time;
1223     ConfigOptionFloat                       initial_exposure_time;
1224     ConfigOptionFloats                      material_correction;
1225 protected:
initialize(StaticCacheBase & cache,const char * base_ptr)1226     void initialize(StaticCacheBase &cache, const char *base_ptr)
1227     {
1228         OPT_PTR(initial_layer_height);
1229         OPT_PTR(bottle_cost);
1230         OPT_PTR(bottle_volume);
1231         OPT_PTR(bottle_weight);
1232         OPT_PTR(material_density);
1233         OPT_PTR(exposure_time);
1234         OPT_PTR(initial_exposure_time);
1235         OPT_PTR(material_correction);
1236     }
1237 };
1238 
1239 class SLAPrinterConfig : public StaticPrintConfig
1240 {
1241     STATIC_PRINT_CONFIG_CACHE(SLAPrinterConfig)
1242 public:
1243     ConfigOptionEnum<PrinterTechnology>     printer_technology;
1244     ConfigOptionPoints                      bed_shape;
1245     ConfigOptionFloat                       max_print_height;
1246     ConfigOptionFloat                       display_width;
1247     ConfigOptionFloat                       display_height;
1248     ConfigOptionInt                         display_pixels_x;
1249     ConfigOptionInt                         display_pixels_y;
1250     ConfigOptionEnum<SLADisplayOrientation> display_orientation;
1251     ConfigOptionBool                        display_mirror_x;
1252     ConfigOptionBool                        display_mirror_y;
1253     ConfigOptionFloats                      relative_correction;
1254     ConfigOptionFloat                       absolute_correction;
1255     ConfigOptionFloat                       elefant_foot_compensation;
1256     ConfigOptionFloat                       elefant_foot_min_width;
1257     ConfigOptionFloat                       gamma_correction;
1258     ConfigOptionFloat                       fast_tilt_time;
1259     ConfigOptionFloat                       slow_tilt_time;
1260     ConfigOptionFloat                       area_fill;
1261     ConfigOptionFloat                       min_exposure_time;
1262     ConfigOptionFloat                       max_exposure_time;
1263     ConfigOptionFloat                       min_initial_exposure_time;
1264     ConfigOptionFloat                       max_initial_exposure_time;
1265 protected:
initialize(StaticCacheBase & cache,const char * base_ptr)1266     void initialize(StaticCacheBase &cache, const char *base_ptr)
1267     {
1268         OPT_PTR(printer_technology);
1269         OPT_PTR(bed_shape);
1270         OPT_PTR(max_print_height);
1271         OPT_PTR(display_width);
1272         OPT_PTR(display_height);
1273         OPT_PTR(display_pixels_x);
1274         OPT_PTR(display_pixels_y);
1275         OPT_PTR(display_mirror_x);
1276         OPT_PTR(display_mirror_y);
1277         OPT_PTR(display_orientation);
1278         OPT_PTR(relative_correction);
1279         OPT_PTR(absolute_correction);
1280         OPT_PTR(elefant_foot_compensation);
1281         OPT_PTR(elefant_foot_min_width);
1282         OPT_PTR(gamma_correction);
1283         OPT_PTR(fast_tilt_time);
1284         OPT_PTR(slow_tilt_time);
1285         OPT_PTR(area_fill);
1286         OPT_PTR(min_exposure_time);
1287         OPT_PTR(max_exposure_time);
1288         OPT_PTR(min_initial_exposure_time);
1289         OPT_PTR(max_initial_exposure_time);
1290     }
1291 };
1292 
1293 class SLAFullPrintConfig : public SLAPrinterConfig, public SLAPrintConfig, public SLAPrintObjectConfig, public SLAMaterialConfig
1294 {
1295     STATIC_PRINT_CONFIG_CACHE_DERIVED(SLAFullPrintConfig)
SLAFullPrintConfig()1296     SLAFullPrintConfig() : SLAPrinterConfig(0), SLAPrintConfig(0), SLAPrintObjectConfig(0), SLAMaterialConfig(0) { initialize_cache(); *this = s_cache_SLAFullPrintConfig.defaults(); }
1297 
1298 public:
1299     // Validate the SLAFullPrintConfig. Returns an empty string on success, otherwise an error message is returned.
1300 //    std::string                 validate();
1301 
1302 protected:
1303     // Protected constructor to be called to initialize ConfigCache::m_default.
SLAFullPrintConfig(int)1304     SLAFullPrintConfig(int) : SLAPrinterConfig(0), SLAPrintConfig(0), SLAPrintObjectConfig(0), SLAMaterialConfig(0) {}
initialize(StaticCacheBase & cache,const char * base_ptr)1305     void initialize(StaticCacheBase &cache, const char *base_ptr)
1306     {
1307         this->SLAPrinterConfig    ::initialize(cache, base_ptr);
1308         this->SLAPrintConfig      ::initialize(cache, base_ptr);
1309         this->SLAPrintObjectConfig::initialize(cache, base_ptr);
1310         this->SLAMaterialConfig   ::initialize(cache, base_ptr);
1311     }
1312 };
1313 
1314 #undef STATIC_PRINT_CONFIG_CACHE
1315 #undef STATIC_PRINT_CONFIG_CACHE_BASE
1316 #undef STATIC_PRINT_CONFIG_CACHE_DERIVED
1317 #undef OPT_PTR
1318 
1319 class CLIActionsConfigDef : public ConfigDef
1320 {
1321 public:
1322     CLIActionsConfigDef();
1323 };
1324 
1325 class CLITransformConfigDef : public ConfigDef
1326 {
1327 public:
1328     CLITransformConfigDef();
1329 };
1330 
1331 class CLIMiscConfigDef : public ConfigDef
1332 {
1333 public:
1334     CLIMiscConfigDef();
1335 };
1336 
1337 // This class defines the command line options representing actions.
1338 extern const CLIActionsConfigDef    cli_actions_config_def;
1339 
1340 // This class defines the command line options representing transforms.
1341 extern const CLITransformConfigDef  cli_transform_config_def;
1342 
1343 // This class defines all command line options that are not actions or transforms.
1344 extern const CLIMiscConfigDef       cli_misc_config_def;
1345 
1346 class DynamicPrintAndCLIConfig : public DynamicPrintConfig
1347 {
1348 public:
DynamicPrintAndCLIConfig()1349     DynamicPrintAndCLIConfig() {}
DynamicPrintAndCLIConfig(const DynamicPrintAndCLIConfig & other)1350     DynamicPrintAndCLIConfig(const DynamicPrintAndCLIConfig &other) : DynamicPrintConfig(other) {}
1351 
1352     // Overrides ConfigBase::def(). Static configuration definition. Any value stored into this ConfigBase shall have its definition here.
def() const1353     const ConfigDef*        def() const override { return &s_def; }
1354 
1355     // Verify whether the opt_key has not been obsoleted or renamed.
1356     // Both opt_key and value may be modified by handle_legacy().
1357     // If the opt_key is no more valid in this version of Slic3r, opt_key is cleared by handle_legacy().
1358     // handle_legacy() is called internally by set_deserialize().
1359     void                    handle_legacy(t_config_option_key &opt_key, std::string &value) const override;
1360 
1361 private:
1362     class PrintAndCLIConfigDef : public ConfigDef
1363     {
1364     public:
PrintAndCLIConfigDef()1365         PrintAndCLIConfigDef() {
1366             this->options.insert(print_config_def.options.begin(), print_config_def.options.end());
1367             this->options.insert(cli_actions_config_def.options.begin(), cli_actions_config_def.options.end());
1368             this->options.insert(cli_transform_config_def.options.begin(), cli_transform_config_def.options.end());
1369             this->options.insert(cli_misc_config_def.options.begin(), cli_misc_config_def.options.end());
1370             for (const auto &kvp : this->options)
1371                 this->by_serialization_key_ordinal[kvp.second.serialization_key_ordinal] = &kvp.second;
1372         }
1373         // Do not release the default values, they are handled by print_config_def & cli_actions_config_def / cli_transform_config_def / cli_misc_config_def.
~PrintAndCLIConfigDef()1374         ~PrintAndCLIConfigDef() { this->options.clear(); }
1375     };
1376     static PrintAndCLIConfigDef s_def;
1377 };
1378 
1379 Points get_bed_shape(const DynamicPrintConfig &cfg);
1380 Points get_bed_shape(const PrintConfig &cfg);
1381 Points get_bed_shape(const SLAPrinterConfig &cfg);
1382 
1383 // ModelConfig is a wrapper around DynamicPrintConfig with an addition of a timestamp.
1384 // Each change of ModelConfig is tracked by assigning a new timestamp from a global counter.
1385 // The counter is used for faster synchronization of the background slicing thread
1386 // with the front end by skipping synchronization of equal config dictionaries.
1387 // The global counter is also used for avoiding unnecessary serialization of config
1388 // dictionaries when taking an Undo snapshot.
1389 //
1390 // The global counter is NOT thread safe, therefore it is recommended to use ModelConfig from
1391 // the main thread only.
1392 //
1393 // As there is a global counter and it is being increased with each change to any ModelConfig,
1394 // if two ModelConfig dictionaries differ, they should differ with their timestamp as well.
1395 // Therefore copying the ModelConfig including its timestamp is safe as there is no harm
1396 // in having multiple ModelConfig with equal timestamps as long as their dictionaries are equal.
1397 //
1398 // The timestamp is used by the Undo/Redo stack. As zero timestamp means invalid timestamp
1399 // to the Undo/Redo stack (zero timestamp means the Undo/Redo stack needs to serialize and
1400 // compare serialized data for differences), zero timestamp shall never be used.
1401 // Timestamp==1 shall only be used for empty dictionaries.
1402 class ModelConfig
1403 {
1404 public:
clear()1405     void         clear() { m_data.clear(); m_timestamp = 1; }
1406 
assign_config(const ModelConfig & rhs)1407     void         assign_config(const ModelConfig &rhs) {
1408         if (m_timestamp != rhs.m_timestamp) {
1409             m_data      = rhs.m_data;
1410             m_timestamp = rhs.m_timestamp;
1411         }
1412     }
assign_config(ModelConfig && rhs)1413     void         assign_config(ModelConfig &&rhs) {
1414         if (m_timestamp != rhs.m_timestamp) {
1415             m_data      = std::move(rhs.m_data);
1416             m_timestamp = rhs.m_timestamp;
1417             rhs.clear();
1418         }
1419     }
1420 
1421     // Modification of the ModelConfig is not thread safe due to the global timestamp counter!
1422     // Don't call modification methods from the back-end!
1423     // Assign methods don't assign if src==dst to not having to bump the timestamp in case they are equal.
assign_config(const DynamicPrintConfig & rhs)1424     void         assign_config(const DynamicPrintConfig &rhs)  { if (m_data != rhs) { m_data = rhs; this->touch(); } }
assign_config(DynamicPrintConfig && rhs)1425     void         assign_config(DynamicPrintConfig &&rhs)       { if (m_data != rhs) { m_data = std::move(rhs); this->touch(); } }
apply(const ModelConfig & other,bool ignore_nonexistent=false)1426     void         apply(const ModelConfig &other, bool ignore_nonexistent = false) { this->apply(other.get(), ignore_nonexistent); }
apply(const ConfigBase & other,bool ignore_nonexistent=false)1427     void         apply(const ConfigBase &other, bool ignore_nonexistent = false) { m_data.apply_only(other, other.keys(), ignore_nonexistent); this->touch(); }
apply_only(const ModelConfig & other,const t_config_option_keys & keys,bool ignore_nonexistent=false)1428     void         apply_only(const ModelConfig &other, const t_config_option_keys &keys, bool ignore_nonexistent = false) { this->apply_only(other.get(), keys, ignore_nonexistent); }
apply_only(const ConfigBase & other,const t_config_option_keys & keys,bool ignore_nonexistent=false)1429     void         apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false) { m_data.apply_only(other, keys, ignore_nonexistent); this->touch(); }
set_key_value(const std::string & opt_key,ConfigOption * opt)1430     bool         set_key_value(const std::string &opt_key, ConfigOption *opt) { bool out = m_data.set_key_value(opt_key, opt); this->touch(); return out; }
1431     template<typename T>
set(const std::string & opt_key,T value)1432     void         set(const std::string &opt_key, T value) { m_data.set(opt_key, value, true); this->touch(); }
set_deserialize(const t_config_option_key & opt_key,const std::string & str,ConfigSubstitutionContext & substitution_context,bool append=false)1433     void         set_deserialize(const t_config_option_key &opt_key, const std::string &str, ConfigSubstitutionContext &substitution_context, bool append = false)
1434         { m_data.set_deserialize(opt_key, str, substitution_context, append); this->touch(); }
erase(const t_config_option_key & opt_key)1435     bool         erase(const t_config_option_key &opt_key) { bool out = m_data.erase(opt_key); if (out) this->touch(); return out; }
1436 
1437     // Getters are thread safe.
1438     // The following implicit conversion breaks the Cereal serialization.
1439 //    operator const DynamicPrintConfig&() const throw() { return this->get(); }
get() const1440     const DynamicPrintConfig&   get() const throw() { return m_data; }
empty() const1441     bool                        empty() const throw() { return m_data.empty(); }
size() const1442     size_t                      size() const throw() { return m_data.size(); }
cbegin() const1443     auto                        cbegin() const { return m_data.cbegin(); }
cend() const1444     auto                        cend() const { return m_data.cend(); }
keys() const1445     t_config_option_keys        keys() const { return m_data.keys(); }
has(const t_config_option_key & opt_key) const1446     bool                        has(const t_config_option_key &opt_key) const { return m_data.has(opt_key); }
option(const t_config_option_key & opt_key) const1447     const ConfigOption*         option(const t_config_option_key &opt_key) const { return m_data.option(opt_key); }
opt_int(const t_config_option_key & opt_key) const1448     int                         opt_int(const t_config_option_key &opt_key) const { return m_data.opt_int(opt_key); }
extruder() const1449     int                         extruder() const { return opt_int("extruder"); }
opt_float(const t_config_option_key & opt_key) const1450     double                      opt_float(const t_config_option_key &opt_key) const { return m_data.opt_float(opt_key); }
opt_serialize(const t_config_option_key & opt_key) const1451     std::string                 opt_serialize(const t_config_option_key &opt_key) const { return m_data.opt_serialize(opt_key); }
1452 
1453     // Return an optional timestamp of this object.
1454     // If the timestamp returned is non-zero, then the serialization framework will
1455     // only save this object on the Undo/Redo stack if the timestamp is different
1456     // from the timestmap of the object at the top of the Undo / Redo stack.
timestamp() const1457     virtual uint64_t    timestamp() const throw() { return m_timestamp; }
timestamp_matches(const ModelConfig & rhs) const1458     bool                timestamp_matches(const ModelConfig &rhs) const throw() { return m_timestamp == rhs.m_timestamp; }
1459     // Not thread safe! Should not be called from other than the main thread!
touch()1460     void                touch() { m_timestamp = ++ s_last_timestamp; }
1461 
1462 private:
1463     friend class cereal::access;
serialize(Archive & ar)1464     template<class Archive> void serialize(Archive& ar) { ar(m_timestamp); ar(m_data); }
1465 
1466     uint64_t                    m_timestamp { 1 };
1467     DynamicPrintConfig          m_data;
1468 
1469     static uint64_t             s_last_timestamp;
1470 };
1471 
1472 } // namespace Slic3r
1473 
1474 // Serialization through the Cereal library
1475 namespace cereal {
1476     // Let cereal know that there are load / save non-member functions declared for DynamicPrintConfig, ignore serialize / load / save from parent class DynamicConfig.
1477     template <class Archive> struct specialize<Archive, Slic3r::DynamicPrintConfig, cereal::specialization::non_member_load_save> {};
1478 
load(Archive & archive,Slic3r::DynamicPrintConfig & config)1479     template<class Archive> void load(Archive& archive, Slic3r::DynamicPrintConfig &config)
1480     {
1481         size_t cnt;
1482         archive(cnt);
1483         config.clear();
1484         for (size_t i = 0; i < cnt; ++ i) {
1485             size_t serialization_key_ordinal;
1486             archive(serialization_key_ordinal);
1487             assert(serialization_key_ordinal > 0);
1488             auto it = Slic3r::print_config_def.by_serialization_key_ordinal.find(serialization_key_ordinal);
1489             assert(it != Slic3r::print_config_def.by_serialization_key_ordinal.end());
1490             config.set_key_value(it->second->opt_key, it->second->load_option_from_archive(archive));
1491         }
1492     }
1493 
save(Archive & archive,const Slic3r::DynamicPrintConfig & config)1494     template<class Archive> void save(Archive& archive, const Slic3r::DynamicPrintConfig &config)
1495     {
1496         size_t cnt = config.size();
1497         archive(cnt);
1498         for (auto it = config.cbegin(); it != config.cend(); ++it) {
1499             const Slic3r::ConfigOptionDef* optdef = Slic3r::print_config_def.get(it->first);
1500             assert(optdef != nullptr);
1501             assert(optdef->serialization_key_ordinal > 0);
1502             archive(optdef->serialization_key_ordinal);
1503             optdef->save_option_to_archive(archive, it->second.get());
1504         }
1505     }
1506 }
1507 
1508 #endif
1509