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