From 3799d533cc2bfcdc8a28165cfae693d252c19ef8 Mon Sep 17 00:00:00 2001 From: supermerill Date: Sat, 21 Nov 2020 20:54:46 +0100 Subject: [PATCH] Export to prusa: * now the .3mf contains the modified config compatible with purusaslicer * now the superslicer settings are stored in their own file. Note: projects saved with this version will transfer only prusa settings back to older superslicer version. --- src/libslic3r/Config.hpp | 6 +- src/libslic3r/Format/3mf.cpp | 117 +++++++++++++++++-- src/libslic3r/PrintConfig.cpp | 208 ++++++++++++++++++++++++++++++++++ src/libslic3r/PrintConfig.hpp | 8 +- 4 files changed, 326 insertions(+), 13 deletions(-) diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index a5a326834..217cb1d83 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -1648,7 +1648,11 @@ protected: // Both opt_key and value may be modified by handle_legacy(). // If the opt_key is no more valid in this version of Slic3r, opt_key is cleared by handle_legacy(). // handle_legacy() is called internally by set_deserialize(). - virtual void handle_legacy(t_config_option_key &/*opt_key*/, std::string &/*value*/) const {} + virtual void handle_legacy(t_config_option_key&/*opt_key*/, std::string&/*value*/) const {} + // Verify whether the opt_key has to be converted or isn't present int prusaslicer + // Both opt_key and value may be modified by to_prusa(). + // If the opt_key is no more valid in this version of Slic3r, opt_key is cleared by to_prusa(). + virtual void to_prusa(t_config_option_key&/*opt_key*/, std::string&/*value*/) const {} public: using ConfigOptionResolver::option; diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 446da363e..ada502aba 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -48,8 +48,10 @@ const std::string MODEL_FILE = "3D/3dmodel.model"; // << this is the only format const std::string CONTENT_TYPES_FILE = "[Content_Types].xml"; const std::string RELATIONSHIPS_FILE = "_rels/.rels"; const std::string THUMBNAIL_FILE = "Metadata/thumbnail.png"; -const std::string PRINT_CONFIG_FILE = "Metadata/Slic3r_PE.config"; -const std::string MODEL_CONFIG_FILE = "Metadata/Slic3r_PE_model.config"; +const std::string PRINT_CONFIG_FILE = "Metadata/SuperSlicer.config"; +const std::string MODEL_CONFIG_FILE = "Metadata/SuperSlicer_model.config"; +const std::string PRINT_PRUSA_CONFIG_FILE = "Metadata/Slic3r_PE.config"; +const std::string MODEL_PRUSA_CONFIG_FILE = "Metadata/Slic3r_PE_model.config"; const std::string LAYER_HEIGHTS_PROFILE_FILE = "Metadata/Slic3r_PE_layer_heights_profile.txt"; const std::string LAYER_CONFIG_RANGES_FILE = "Metadata/Prusa_Slicer_layer_config_ranges.xml"; const std::string SLA_SUPPORT_POINTS_FILE = "Metadata/Slic3r_PE_sla_support_points.txt"; @@ -615,6 +617,7 @@ namespace Slic3r { } // we then loop again the entries to read other files stored in the archive + bool print_config_parsed = false, model_config_parsed = false; for (mz_uint i = 0; i < num_entries; ++i) { if (mz_zip_reader_file_stat(&archive, i, &stat)) @@ -646,6 +649,7 @@ namespace Slic3r { { // extract slic3r print config file _extract_print_config_from_archive(archive, stat, config, filename); + print_config_parsed = true; } if (boost::algorithm::iequals(name, CUSTOM_GCODE_PER_PRINT_Z_FILE)) { @@ -653,6 +657,32 @@ namespace Slic3r { _extract_custom_gcode_per_print_z_from_archive(archive, stat); } else if (boost::algorithm::iequals(name, MODEL_CONFIG_FILE)) + { + // extract slic3r model config file + if (!_extract_model_config_from_archive(archive, stat, model)) + { + close_zip_reader(&archive); + add_error("Archive does not contain a valid model config"); + return false; + } + model_config_parsed = true; + } + } + } + //parsed prusa files if superslicer not found + for (mz_uint i = 0; i < num_entries; ++i) + { + if (mz_zip_reader_file_stat(&archive, i, &stat)) + { + std::string name(stat.m_filename); + std::replace(name.begin(), name.end(), '\\', '/'); + + //TODO use special methods to convert them better? + if (!print_config_parsed && boost::algorithm::iequals(name, PRINT_PRUSA_CONFIG_FILE)) + { + // extract slic3r print config file + _extract_print_config_from_archive(archive, stat, config, filename); + } else if (!model_config_parsed && boost::algorithm::iequals(name, MODEL_PRUSA_CONFIG_FILE)) { // extract slic3r model config file if (!_extract_model_config_from_archive(archive, stat, model)) @@ -2661,13 +2691,13 @@ namespace Slic3r { return true; } - bool _3MF_Exporter::_add_print_config_file_to_archive(mz_zip_archive& archive, const DynamicPrintConfig &config) + bool _3MF_Exporter::_add_print_config_file_to_archive(mz_zip_archive& archive, const DynamicPrintConfig& config) { char buffer[1024]; sprintf(buffer, "; %s\n\n", header_slic3r_generated().c_str()); std::string out = buffer; - for (const std::string &key : config.keys()) + for (const std::string& key : config.keys()) if (key != "compatible_printers") out += "; " + key + " = " + config.opt_serialize(key) + "\n"; @@ -2680,18 +2710,44 @@ namespace Slic3r { } } + //add prusa print config + out = buffer; + + for (std::string key : config.keys()) + if (key != "compatible_printers") { + std::string value = config.opt_serialize(key); + config.to_prusa(key, value); + if(!key.empty()) + out += "; " + key + " = " + value + "\n"; + } + + if (!out.empty()) + { + if (!mz_zip_writer_add_mem(&archive, PRINT_PRUSA_CONFIG_FILE.c_str(), (const void*)out.data(), out.length(), MZ_DEFAULT_COMPRESSION)) + { + add_error("Unable to add prusa print config file to archive"); + return false; + } + } + return true; } bool _3MF_Exporter::_add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, const IdToObjectDataMap &objects_data) { std::stringstream stream; + std::stringstream stream_prusa; // Store mesh transformation in full precision, as the volumes are stored transformed and they need to be transformed back // when loaded as accurately as possible. stream << std::setprecision(std::numeric_limits::max_digits10); stream << "\n"; stream << "<" << CONFIG_TAG << ">\n"; + stream_prusa << std::setprecision(std::numeric_limits::max_digits10); + stream_prusa << "\n"; + stream_prusa << "<" << CONFIG_TAG << ">\n"; + + for (const IdToObjectDataMap::value_type& obj_metadata : objects_data) { const ModelObject* obj = obj_metadata.second.object; @@ -2699,15 +2755,18 @@ namespace Slic3r { { // Output of instances count added because of github #3435, currently not used by PrusaSlicer stream << " <" << OBJECT_TAG << " " << ID_ATTR << "=\"" << obj_metadata.first << "\" " << INSTANCESCOUNT_ATTR << "=\"" << obj->instances.size() << "\">\n"; + stream_prusa << " <" << OBJECT_TAG << " " << ID_ATTR << "=\"" << obj_metadata.first << "\" " << INSTANCESCOUNT_ATTR << "=\"" << obj->instances.size() << "\">\n"; // stores object's name - if (!obj->name.empty()) + if (!obj->name.empty()) { stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << OBJECT_TYPE << "\" " << KEY_ATTR << "=\"name\" " << VALUE_ATTR << "=\"" << xml_escape(obj->name) << "\"/>\n"; + stream_prusa << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << OBJECT_TYPE << "\" " << KEY_ATTR << "=\"name\" " << VALUE_ATTR << "=\"" << xml_escape(obj->name) << "\"/>\n"; + } // stores object's config data - for (const std::string& key : obj->config.keys()) - { + for (const std::string& key : obj->config.keys()) { stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << OBJECT_TYPE << "\" " << KEY_ATTR << "=\"" << key << "\" " << VALUE_ATTR << "=\"" << obj->config.opt_serialize(key) << "\"/>\n"; + stream_prusa << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << OBJECT_TYPE << "\" " << KEY_ATTR << "=\"" << key << "\" " << VALUE_ATTR << "=\"" << obj->config.opt_serialize(key) << "\"/>\n"; } for (const ModelVolume* volume : obj_metadata.second.object->volumes) @@ -2722,20 +2781,30 @@ namespace Slic3r { stream << " <" << VOLUME_TAG << " "; stream << FIRST_TRIANGLE_ID_ATTR << "=\"" << it->second.first_triangle_id << "\" "; stream << LAST_TRIANGLE_ID_ATTR << "=\"" << it->second.last_triangle_id << "\">\n"; + stream_prusa << " <" << VOLUME_TAG << " "; + stream_prusa << FIRST_TRIANGLE_ID_ATTR << "=\"" << it->second.first_triangle_id << "\" "; + stream_prusa << LAST_TRIANGLE_ID_ATTR << "=\"" << it->second.last_triangle_id << "\">\n"; // stores volume's name - if (!volume->name.empty()) + if (!volume->name.empty()) { stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << NAME_KEY << "\" " << VALUE_ATTR << "=\"" << xml_escape(volume->name) << "\"/>\n"; + stream_prusa << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << NAME_KEY << "\" " << VALUE_ATTR << "=\"" << xml_escape(volume->name) << "\"/>\n"; + } // stores volume's modifier field (legacy, to support old slicers) - if (volume->is_modifier()) + if (volume->is_modifier()) { stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << MODIFIER_KEY << "\" " << VALUE_ATTR << "=\"1\"/>\n"; + stream_prusa << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << MODIFIER_KEY << "\" " << VALUE_ATTR << "=\"1\"/>\n"; + } // stores volume's type (overrides the modifier field above) - stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << VOLUME_TYPE_KEY << "\" " << + stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << VOLUME_TYPE_KEY << "\" " << + VALUE_ATTR << "=\"" << ModelVolume::type_to_string(volume->type()) << "\"/>\n"; + stream_prusa << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << VOLUME_TYPE_KEY << "\" " << VALUE_ATTR << "=\"" << ModelVolume::type_to_string(volume->type()) << "\"/>\n"; // stores volume's local matrix stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << MATRIX_KEY << "\" " << VALUE_ATTR << "=\""; + stream_prusa << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << MATRIX_KEY << "\" " << VALUE_ATTR << "=\""; Transform3d matrix = volume->get_matrix() * volume->source.transform.get_matrix(); for (int r = 0; r < 4; ++r) { @@ -2744,9 +2813,13 @@ namespace Slic3r { stream << matrix(r, c); if ((r != 3) || (c != 3)) stream << " "; + stream_prusa << matrix(r, c); + if ((r != 3) || (c != 3)) + stream_prusa << " "; } } stream << "\"/>\n"; + stream_prusa << "\"/>\n"; // stores volume's source data if (!volume->source.input_file.empty()) @@ -2758,24 +2831,39 @@ namespace Slic3r { stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << SOURCE_OFFSET_X_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.mesh_offset(0) << "\"/>\n"; stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << SOURCE_OFFSET_Y_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.mesh_offset(1) << "\"/>\n"; stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << SOURCE_OFFSET_Z_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.mesh_offset(2) << "\"/>\n"; + stream_prusa << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << SOURCE_FILE_KEY << "\" " << VALUE_ATTR << "=\"" << input_file << "\"/>\n"; + stream_prusa << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << SOURCE_OBJECT_ID_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.object_idx << "\"/>\n"; + stream_prusa << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << SOURCE_VOLUME_ID_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.volume_idx << "\"/>\n"; + stream_prusa << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << SOURCE_OFFSET_X_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.mesh_offset(0) << "\"/>\n"; + stream_prusa << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << SOURCE_OFFSET_Y_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.mesh_offset(1) << "\"/>\n"; + stream_prusa << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << SOURCE_OFFSET_Z_KEY << "\" " << VALUE_ATTR << "=\"" << volume->source.mesh_offset(2) << "\"/>\n"; } // stores volume's config data - for (const std::string& key : volume->config.keys()) + for (std::string key : volume->config.keys()) { + //superslicer config stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << key << "\" " << VALUE_ATTR << "=\"" << volume->config.opt_serialize(key) << "\"/>\n"; + //now the prusa config + std::string value = volume->config.opt_serialize(key); + volume->config.to_prusa(key, value); + if (!key.empty()) + stream_prusa << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << key << "\" " << VALUE_ATTR << "=\"" << value << "\"/>\n"; } stream << " \n"; + stream_prusa << " \n"; } } } stream << " \n"; + stream_prusa << " \n"; } } stream << "\n"; + stream_prusa << "\n"; std::string out = stream.str(); @@ -2785,6 +2873,13 @@ namespace Slic3r { return false; } + out = stream_prusa.str(); + if (!mz_zip_writer_add_mem(&archive, MODEL_PRUSA_CONFIG_FILE.c_str(), (const void*)out.data(), out.length(), MZ_DEFAULT_COMPRESSION)) + { + add_error("Unable to add prusa model config file to archive"); + return false; + } + return true; } diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 432889c28..46a74bad6 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -4943,6 +4943,214 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va } } +void PrintConfigDef::to_prusa(t_config_option_key& opt_key, std::string& value, const DynamicConfig& all_conf) { + + std::unordered_set to_remove_keys = { +"thumbnails_color", +"thumbnails_custom_color", +"thumbnails_with_bed", +"thumbnails_with_support", +"allow_empty_layers", +"avoid_crossing_not_first_layer", +"top_fan_speed", +"over_bridge_flow_ratio", +"bridge_overlap", +"bridge_speed_internal", +"brim_inside_holes", +"brim_width_interior", +"brim_ears", +"brim_ears_max_angle", +"brim_ears_pattern", +"brim_offset", +"chamber_temperature", +"complete_objects_one_skirt", +"complete_objects_sort", +"top_fill_pattern", +"solid_fill_pattern", +"enforce_full_fill_volume", +"external_infill_margin", +"bridged_infill_margin", +"external_perimeter_cut_corners", +"external_perimeter_fan_speed", +"external_perimeter_overlap", +"perimeter_overlap", +"perimeter_bonding", +"external_perimeters_vase", +"external_perimeters_nothole", +"external_perimeters_hole", +"perimeter_loop", +"perimeter_loop_seam", +"extra_perimeters_overhangs", +"extra_perimeters_odd_layers", +"only_one_perimeter_top", +"extruder_temperature_offset", +"extruder_fan_offset", +"print_extrusion_multiplier", +"filament_max_speed", +"filament_max_wipe_tower_speed", +"filament_enable_toolchange_temp", +"filament_use_fast_skinnydip", +"filament_enable_toolchange_part_fan", +"filament_toolchange_part_fan_speed", +"filament_use_skinnydip", +"filament_melt_zone_pause", +"filament_cooling_zone_pause", +"filament_dip_insertion_speed", +"filament_dip_extraction_speed", +"filament_toolchange_temp", +"filament_skinnydip_distance", +"filament_shrink", +"fill_angle_increment", +"fill_top_flow_ratio", +"fill_top_flow_ratio", +"first_layer_flow_ratio", +"fill_smooth_width", +"fill_smooth_distribution", +"first_layer_infill_speed", +"gap_fill", +"gap_fill_min_area", +"gap_fill_overlap", +"infill_dense", +"infill_connection", +"infill_dense_algo", +"feature_gcode", +"exact_last_layer_height", +"fan_speedup_time", +"fan_speedup_overhangs", +"fan_kickstart", +"machine_max_acceleration_travel", +"max_speed_reduction", +"min_length", +"min_width_top_surface", +"printhost_apikey", +"printhost_cafile", +"print_host", +"overhangs_speed", +"overhangs_width_speed", +"overhangs_reverse", +"overhangs_reverse_threshold", +"no_perimeter_unsupported_algo", +"support_material_solid_first_layer", +"print_retract_length", +"retract_lift_first_layer", +"retract_lift_top", +"seam_angle_cost", +"seam_travel_cost", +"skirt_extrusion_width", +"small_perimeter_min_length", +"small_perimeter_max_length", +"curve_smoothing_angle_convex", +"curve_smoothing_angle_concave", +"curve_smoothing_precision", +"curve_smoothing_cutoff_dist", +"model_precision", +"support_material_contact_distance_type", +"support_material_contact_distance_bottom", +"support_material_interface_pattern", +"print_temperature", +"print_retract_lift", +"thin_perimeters", +"thin_perimeters_all", +"thin_walls_min_width", +"thin_walls_overlap", +"thin_walls_merge", +"thin_walls_speed", +"time_estimation_compensation", +"tool_name", +"wipe_advanced", +"wipe_advanced_nozzle_melted_volume", +"filament_wipe_advanced_pigment", +"wipe_advanced_multiplier", +"wipe_advanced_algo", +"wipe_tower_brim", +"wipe_extra_perimeter", +"xy_inner_size_compensation", +"hole_size_compensation", +"hole_size_threshold", +"hole_to_polyhole", +"z_step", +"milling_cutter", +"milling_diameter", +"milling_offset", +"milling_z_offset", +"milling_z_lift", +"milling_toolchange_start_gcode", +"milling_toolchange_end_gcode", +"milling_post_process", +"milling_extra_size", +"milling_after_z", +"milling_speed" + + }; + //looks if it's to be removed, or have to be transformed + if (to_remove_keys.find(opt_key) != to_remove_keys.end()) { + opt_key = ""; + value = ""; + } else if (opt_key.find("_pattern") != std::string::npos) { + if ("smooth" == value || "smoothtriple" == value || "smoothhilbert" == value || "rectiwithperimeter" == value || "scatteredrectilinear" == value || "rectilineargapfill" == value || "sawtooth" == value) { + value = "rectilinear"; + } else if ( "concentricgapfill" == value) { + value = "concentric"; + } + } else if ("seam_position" == opt_key) { + if ("seam_travel_cost" == value || "near" == value || "hidden" == value) { + value = "nearest"; + } + } else if ("first_layer_size_compensation" == opt_key) { + opt_key = "elefant_foot_compensation"; + if (!value.empty()) { + if (value[0] == '-') { + value = value.substr(1); + } else { + value = "0"; + } + } + } else if ("elephant_foot_min_width" == opt_key) { + opt_key = "elefant_foot_min_width"; + } else if("first_layer_acceleration" == opt_key || "infill_acceleration" == opt_key || "bridge_acceleration" == opt_key || "default_acceleration" == opt_key || "overhangs_speed" == opt_key || "perimeter_acceleration" == opt_key){ + if (value.find("%") != std::string::npos) + value = "0"; + } else if ("gap_fill_speed" == opt_key && all_conf.has("gap_fill") && !all_conf.option("gap_fill")->value) { + value = "0"; + } else if ("bridge_flow_ratio" == opt_key && all_conf.has("bridge_flow_ratio")) { + value = boost::lexical_cast(all_conf.option("bridge_flow_ratio")->get_abs_value(1)); + } else if ("overhangs_width" == opt_key) { + opt_key = "overhangs"; + if (value != "0") + value = "1"; + } else if ("support_material_contact_distance_top" == opt_key) { + opt_key = "support_material_contact_distance"; + //default : get the top value or 0.2 if a % + if (value.find("%") != std::string::npos) + value = "0.2"; + try { //avoid most useless cheks and multiple corners cases with this try catch + SupportZDistanceType dist_type = all_conf.option>("support_material_contact_distance_type")->value; + if (SupportZDistanceType::zdNone == dist_type) { + value = "0"; + } else { + double val = all_conf.option("support_material_contact_distance_top")->get_abs_value(all_conf.option("nozzle_diameter")->values.front()); + if (SupportZDistanceType::zdFilament == dist_type) { // not exact but good enough effort + val += all_conf.option("nozzle_diameter")->values.front(); + val -= all_conf.get_abs_value("layer_height"); + } + value = boost::lexical_cast(val); + } + } + catch (...) { + } + } else if ("gcode_flavor" == opt_key) { + if ("reprap" == value) + value = "reprapfirmware"; + else if ("sprinter" == value) + value = "reprap"; + else if ("lerdge" == value) + value = "marlin"; + else if ("klipper" == value) + value = "reprap"; + } + +} + const PrintConfigDef print_config_def; DynamicPrintConfig DynamicPrintConfig::full_print_config() diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 781973b71..70059d23d 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -364,7 +364,8 @@ class PrintConfigDef : public ConfigDef public: PrintConfigDef(); - static void handle_legacy(t_config_option_key &opt_key, std::string &value); + static void handle_legacy(t_config_option_key& opt_key, std::string& value); + static void to_prusa(t_config_option_key& opt_key, std::string& value, const DynamicConfig& all_conf); // Array options growing with the number of extruders const std::vector& extruder_option_keys() const { return m_extruder_option_keys; } @@ -435,6 +436,9 @@ public: // handle_legacy() is called internally by set_deserialize(). void handle_legacy(t_config_option_key &opt_key, std::string &value) const override { PrintConfigDef::handle_legacy(opt_key, value); } + + void to_prusa(t_config_option_key& opt_key, std::string& value) const override + { PrintConfigDef::to_prusa(opt_key, value, *this); } }; class StaticPrintConfig : public StaticConfig @@ -1860,6 +1864,8 @@ public: // Not thread safe! Should not be called from other than the main thread! void touch() { m_timestamp = ++ s_last_timestamp; } + void to_prusa(t_config_option_key& opt_key, std::string& value) const + { m_data.to_prusa(opt_key, value); } private: friend class cereal::access; template void serialize(Archive& ar) { ar(m_timestamp); ar(m_data); }