diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 2f330fefc..43465f5ef 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -50,6 +50,8 @@ const std::string RELATIONSHIPS_FILE = "_rels/.rels"; const std::string THUMBNAIL_FILE = "Metadata/thumbnail.png"; const std::string PRINT_CONFIG_FILE = "Metadata/Slic3r.config"; const std::string MODEL_CONFIG_FILE = "Metadata/Slic3r_model.config"; +const std::string PRINT_SUPER_CONFIG_FILE = "Metadata/SuperSlicer.config"; +const std::string MODEL_SUPER_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"; @@ -635,18 +637,15 @@ namespace Slic3r { { // extract slic3r layer config ranges file _extract_layer_config_ranges_from_archive(archive, stat); - } - else if (boost::algorithm::iequals(name, SLA_SUPPORT_POINTS_FILE)) + } else if (boost::algorithm::iequals(name, SLA_SUPPORT_POINTS_FILE)) { // extract sla support points file _extract_sla_support_points_from_archive(archive, stat); - } - else if (boost::algorithm::iequals(name, SLA_DRAIN_HOLES_FILE)) + } else if (boost::algorithm::iequals(name, SLA_DRAIN_HOLES_FILE)) { // extract sla support points file _extract_sla_drain_holes_from_archive(archive, stat); - } - else if (boost::algorithm::iequals(name, PRINT_CONFIG_FILE)) + } else if (boost::algorithm::iequals(name, PRINT_CONFIG_FILE)) { // extract slic3r print config file _extract_print_config_from_archive(archive, stat, config, filename); @@ -656,8 +655,7 @@ namespace Slic3r { { // extract slic3r layer config ranges file _extract_custom_gcode_per_print_z_from_archive(archive, stat); - } - else if (boost::algorithm::iequals(name, MODEL_CONFIG_FILE)) + } else if (boost::algorithm::iequals(name, MODEL_CONFIG_FILE)) { // extract slic3r model config file if (!_extract_model_config_from_archive(archive, stat, model)) @@ -666,35 +664,47 @@ namespace Slic3r { add_error("Archive does not contain a valid model config"); return false; } - model_config_parsed = true; + print_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)) + //parsed superslicer/prusa files if slic3r not found + //note that is we successfully read one of the config file, then the other ones should also have the same name + auto read_from_other_storage = [this, &print_config_parsed, num_entries, &archive, &stat, &config, &model, &filename](const std::string &print_config_name, const std::string& model_config_name) -> bool { + for (mz_uint i = 0; i < num_entries; ++i) { - std::string name(stat.m_filename); - std::replace(name.begin(), name.end(), '\\', '/'); + 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)) + //TODO use special methods to convert them better? + if (boost::algorithm::iequals(name, print_config_name)) { - close_zip_reader(&archive); - add_error("Archive does not contain a valid model config"); - return false; + // extract slic3r print config file + _extract_print_config_from_archive(archive, stat, config, filename); + print_config_parsed = true; + } else if (boost::algorithm::iequals(name, model_config_name)) + { + // 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; + } + print_config_parsed = true; } } } - } + return true; + }; + if (!print_config_parsed) + if (!read_from_other_storage(PRINT_SUPER_CONFIG_FILE, MODEL_SUPER_CONFIG_FILE)) + return false; + if (!print_config_parsed) + if (!read_from_other_storage(PRINT_PRUSA_CONFIG_FILE, MODEL_PRUSA_CONFIG_FILE)) + return false; close_zip_reader(&archive); @@ -2066,8 +2076,8 @@ namespace Slic3r { bool _add_layer_config_ranges_file_to_archive(mz_zip_archive& archive, Model& model); bool _add_sla_support_points_file_to_archive(mz_zip_archive& archive, Model& model); bool _add_sla_drain_holes_file_to_archive(mz_zip_archive& archive, Model& model); - bool _add_print_config_file_to_archive(mz_zip_archive& archive, const DynamicPrintConfig &config); - bool _add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, const IdToObjectDataMap &objects_data); + bool _add_print_config_file_to_archive(mz_zip_archive& archive, const DynamicPrintConfig &config, const std::string &file_path); + bool _add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, const IdToObjectDataMap &objects_data, const std::string &file_path); bool _add_custom_gcode_per_print_z_file_to_archive(mz_zip_archive& archive, Model& model, const DynamicPrintConfig* config); }; @@ -2180,7 +2190,11 @@ namespace Slic3r { // This file contains the content of FullPrintConfing / SLAFullPrintConfig. if (config != nullptr) { - if (!_add_print_config_file_to_archive(archive, *config)) + // also add prusa (& superslicer for backward comp, just for some version from 2.3.56) print config + bool error = !_add_print_config_file_to_archive(archive, *config, PRINT_CONFIG_FILE); + error = error || !_add_print_config_file_to_archive(archive, *config, PRINT_PRUSA_CONFIG_FILE); + error = error || !_add_print_config_file_to_archive(archive, *config, PRINT_SUPER_CONFIG_FILE); + if(error) { close_zip_writer(&archive); boost::filesystem::remove(filename); @@ -2188,11 +2202,25 @@ namespace Slic3r { } } - // Adds slic3r model config file ("Metadata/Slic3r_PE_model.config"). + // Adds slic3r model config file ("Metadata/Slic3r_model.config"). // This file contains all the attributes of all ModelObjects and their ModelVolumes (names, parameter overrides). // As there is just a single Indexed Triangle Set data stored per ModelObject, offsets of volumes into their respective Indexed Triangle Set data // is stored here as well. - if (!_add_model_config_file_to_archive(archive, model, objects_data)) + if (!_add_model_config_file_to_archive(archive, model, objects_data, MODEL_CONFIG_FILE)) + { + close_zip_writer(&archive); + boost::filesystem::remove(filename); + return false; + } + // also add prusa + if (!_add_model_config_file_to_archive(archive, model, objects_data, MODEL_PRUSA_CONFIG_FILE)) + { + close_zip_writer(&archive); + boost::filesystem::remove(filename); + return false; + } + // also superslicer for backward comp, just for some version from 2.3.56 + if (!_add_model_config_file_to_archive(archive, model, objects_data, MODEL_SUPER_CONFIG_FILE)) { close_zip_writer(&archive); boost::filesystem::remove(filename); @@ -2294,7 +2322,8 @@ namespace Slic3r { date = date.substr(0, 10); stream << " <" << METADATA_TAG << " name=\"CreationDate\">" << date << "\n"; stream << " <" << METADATA_TAG << " name=\"ModificationDate\">" << date << "\n"; - stream << " <" << METADATA_TAG << " name=\"Application\">" << SLIC3R_APP_KEY << "-" << SLIC3R_VERSION << "\n"; + stream << " <" << METADATA_TAG << " name=\"Application\">" << SLIC3R_APP_KEY << "\n"; + stream << " <" << METADATA_TAG << " name=\"ApplicationVersion\">" << SLIC3R_VERSION_FULL << "\n"; stream << " <" << RESOURCES_TAG << ">\n"; // Instance transformations, indexed by the 3MF object ID (which is a linear serialization of all instances of all ModelObjects). @@ -2695,41 +2724,30 @@ 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, const std::string &config_name) { char buffer[1024]; sprintf(buffer, "; %s\n\n", header_slic3r_generated().c_str()); std::string out = buffer; - - for (const std::string& key : config.keys()) - if (key != "compatible_printers") - out += "; " + key + " = " + config.opt_serialize(key) + "\n"; - - if (!out.empty()) - { - if (!mz_zip_writer_add_mem(&archive, PRINT_CONFIG_FILE.c_str(), (const void*)out.data(), out.length(), MZ_DEFAULT_COMPRESSION)) - { - add_error("Unable to add print config file to archive"); - return false; - } + if (config_name == PRINT_PRUSA_CONFIG_FILE) { + 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"; + } + } else { + for (const std::string& key : config.keys()) + if (key != "compatible_printers") + out += "; " + key + " = " + config.opt_serialize(key) + "\n"; } - //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)) + if (!mz_zip_writer_add_mem(&archive, config_name.c_str(), (const void*)out.data(), out.length(), MZ_DEFAULT_COMPRESSION)) { - add_error("Unable to add prusa print config file to archive"); + add_error("Unable to add print config file to archive"); return false; } } @@ -2737,20 +2755,15 @@ namespace Slic3r { return true; } - bool _3MF_Exporter::_add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, const IdToObjectDataMap &objects_data) + bool _3MF_Exporter::_add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, const IdToObjectDataMap &objects_data, const std::string &file_path) { 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) { @@ -2759,18 +2772,15 @@ 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()) { 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()) { 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) @@ -2785,30 +2795,22 @@ 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()) { 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()) { 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 << "\" " << 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) { @@ -2817,13 +2819,9 @@ 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 { @@ -2840,55 +2838,42 @@ namespace Slic3r { } if (volume->source.is_converted_from_inches) stream << prefix << SOURCE_IN_INCHES << "\" " << VALUE_ATTR << "=\"1\"/>\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 (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"; + // config + if (file_path == MODEL_PRUSA_CONFIG_FILE) { + // convert to prusa config + std::string value = volume->config.opt_serialize(key); + volume->config.to_prusa(key, value); + if (!key.empty()) + stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << key << "\" " << VALUE_ATTR << "=\"" << value << "\"/>\n"; + } else { + stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << key << "\" " << VALUE_ATTR << "=\"" << volume->config.opt_serialize(key) << "\"/>\n"; + } } stream << " \n"; - stream_prusa << " \n"; } } } stream << " \n"; - stream_prusa << " \n"; } } stream << "\n"; - stream_prusa << "\n"; std::string out = stream.str(); - if (!mz_zip_writer_add_mem(&archive, MODEL_CONFIG_FILE.c_str(), (const void*)out.data(), out.length(), MZ_DEFAULT_COMPRESSION)) + if (!mz_zip_writer_add_mem(&archive, file_path.c_str(), (const void*)out.data(), out.length(), MZ_DEFAULT_COMPRESSION)) { add_error("Unable to add model config file to archive"); 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; }