diff --git a/src/libslic3r/ExtrusionEntity.cpp b/src/libslic3r/ExtrusionEntity.cpp index 3989d0eeab..d629a3c89b 100644 --- a/src/libslic3r/ExtrusionEntity.cpp +++ b/src/libslic3r/ExtrusionEntity.cpp @@ -316,8 +316,8 @@ std::string ExtrusionEntity::role_to_string(ExtrusionRole role) case erOverhangPerimeter : return L("Overhang perimeter"); case erInternalInfill : return L("Internal infill"); case erSolidInfill : return L("Solid infill"); - case erIroning : return L("Ironing"); case erTopSolidInfill : return L("Top solid infill"); + case erIroning : return L("Ironing"); case erBridgeInfill : return L("Bridge infill"); case erGapFill : return L("Gap fill"); case erSkirt : return L("Skirt"); diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 657e9ec983..edf55ba37e 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -4,6 +4,7 @@ #include "../GCode.hpp" #include "../Geometry.hpp" #include "../GCode/ThumbnailData.hpp" +#include "../Time.hpp" #include "../I18N.hpp" @@ -1991,7 +1992,7 @@ namespace Slic3r { bool _add_content_types_file_to_archive(mz_zip_archive& archive); bool _add_thumbnail_file_to_archive(mz_zip_archive& archive, const ThumbnailData& thumbnail_data); bool _add_relationships_file_to_archive(mz_zip_archive& archive); - bool _add_model_file_to_archive(mz_zip_archive& archive, const Model& model, IdToObjectDataMap &objects_data); + bool _add_model_file_to_archive(const std::string& filename, mz_zip_archive& archive, const Model& model, IdToObjectDataMap& objects_data); bool _add_object_to_model_stream(std::stringstream& stream, unsigned int& object_id, ModelObject& object, BuildItemsList& build_items, VolumeToOffsetsMap& volumes_offsets); bool _add_mesh_to_object_stream(std::stringstream& stream, ModelObject& object, VolumeToOffsetsMap& volumes_offsets); bool _add_build_to_model_stream(std::stringstream& stream, const BuildItemsList& build_items); @@ -2054,7 +2055,7 @@ namespace Slic3r { // Adds model file ("3D/3dmodel.model"). // This is the one and only file that contains all the geometry (vertices and triangles) of all ModelVolumes. IdToObjectDataMap objects_data; - if (!_add_model_file_to_archive(archive, model, objects_data)) + if (!_add_model_file_to_archive(filename, archive, model, objects_data)) { close_zip_writer(&archive); boost::filesystem::remove(filename); @@ -2203,7 +2204,7 @@ namespace Slic3r { return true; } - bool _3MF_Exporter::_add_model_file_to_archive(mz_zip_archive& archive, const Model& model, IdToObjectDataMap &objects_data) + bool _3MF_Exporter::_add_model_file_to_archive(const std::string& filename, mz_zip_archive& archive, const Model& model, IdToObjectDataMap& objects_data) { std::stringstream stream; // https://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10 @@ -2214,6 +2215,19 @@ namespace Slic3r { stream << "\n"; stream << "<" << MODEL_TAG << " unit=\"millimeter\" xml:lang=\"en-US\" xmlns=\"http://schemas.microsoft.com/3dmanufacturing/core/2015/02\" xmlns:slic3rpe=\"http://schemas.slic3r.org/3mf/2017/06\">\n"; stream << " <" << METADATA_TAG << " name=\"" << SLIC3RPE_3MF_VERSION << "\">" << VERSION_3MF << "\n"; + std::string name = boost::filesystem::path(filename).stem().string(); + stream << " <" << METADATA_TAG << " name=\"Title\">" << name << "\n"; + stream << " <" << METADATA_TAG << " name=\"Designer\">" << "\n"; + stream << " <" << METADATA_TAG << " name=\"Description\">" << name << "\n"; + stream << " <" << METADATA_TAG << " name=\"Copyright\">" << "\n"; + stream << " <" << METADATA_TAG << " name=\"LicenseTerms\">" << "\n"; + stream << " <" << METADATA_TAG << " name=\"Rating\">" << "\n"; + std::string date = Slic3r::Utils::utc_timestamp(Slic3r::Utils::get_current_time_utc()); + // keep only the date part of the string + 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 << " <" << RESOURCES_TAG << ">\n"; // Instance transformations, indexed by the 3MF object ID (which is a linear serialization of all instances of all ModelObjects). diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index a4f25fa14c..d492acf2e8 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -579,142 +579,262 @@ namespace Slic3r { #define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_writer.extruder()->id()) - // Collect pairs of object_layer + support_layer sorted by print_z. - // object_layer & support_layer are considered to be on the same print_z, if they are not further than EPSILON. - std::vector GCode::collect_layers_to_print(const PrintObject& object) - { - std::vector layers_to_print; - layers_to_print.reserve(object.layers().size() + object.support_layers().size()); +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +// Collect pairs of object_layer + support_layer sorted by print_z. +// object_layer & support_layer are considered to be on the same print_z, if they are not further than EPSILON. +std::vector GCode::collect_layers_to_print(const PrintObject& object) +{ + std::vector layers_to_print; + layers_to_print.reserve(object.layers().size() + object.support_layers().size()); - // Calculate a minimum support layer height as a minimum over all extruders, but not smaller than 10um. - // This is the same logic as in support generator. - //FIXME should we use the printing extruders instead? - double gap_over_supports = object.config().support_material_contact_distance; - // FIXME should we test object.config().support_material_synchronize_layers ? Currently the support layers are synchronized with object layers iff soluble supports. - assert(!object.config().support_material || gap_over_supports != 0. || object.config().support_material_synchronize_layers); - if (gap_over_supports != 0.) { - gap_over_supports = std::max(0., gap_over_supports); - // Not a soluble support, - double support_layer_height_min = 1000000.; - for (auto lh : object.print()->config().min_layer_height.values) - support_layer_height_min = std::min(support_layer_height_min, std::max(0.01, lh)); - gap_over_supports += support_layer_height_min; - } - - // Pair the object layers with the support layers by z. - size_t idx_object_layer = 0; - size_t idx_support_layer = 0; - const LayerToPrint* last_extrusion_layer = nullptr; - while (idx_object_layer < object.layers().size() || idx_support_layer < object.support_layers().size()) { - LayerToPrint layer_to_print; - layer_to_print.object_layer = (idx_object_layer < object.layers().size()) ? object.layers()[idx_object_layer++] : nullptr; - layer_to_print.support_layer = (idx_support_layer < object.support_layers().size()) ? object.support_layers()[idx_support_layer++] : nullptr; - if (layer_to_print.object_layer && layer_to_print.support_layer) { - if (layer_to_print.object_layer->print_z < layer_to_print.support_layer->print_z - EPSILON) { - layer_to_print.support_layer = nullptr; - --idx_support_layer; - } - else if (layer_to_print.support_layer->print_z < layer_to_print.object_layer->print_z - EPSILON) { - layer_to_print.object_layer = nullptr; - --idx_object_layer; - } - } - - layers_to_print.emplace_back(layer_to_print); - - // Check that there are extrusions on the very first layer. - if (layers_to_print.size() == 1u) { - if ((layer_to_print.object_layer && !layer_to_print.object_layer->has_extrusions()) - || (layer_to_print.support_layer && !layer_to_print.support_layer->has_extrusions())) - throw std::runtime_error(_(L("There is an object with no extrusions on the first layer."))); - } - - // In case there are extrusions on this layer, check there is a layer to lay it on. - if ((layer_to_print.object_layer && layer_to_print.object_layer->has_extrusions()) - // Allow empty support layers, as the support generator may produce no extrusions for non-empty support regions. - || (layer_to_print.support_layer /* && layer_to_print.support_layer->has_extrusions() */)) { - double support_contact_z = (last_extrusion_layer && last_extrusion_layer->support_layer) - ? gap_over_supports - : 0.; - double maximal_print_z = (last_extrusion_layer ? last_extrusion_layer->print_z() : 0.) - + layer_to_print.layer()->height - + support_contact_z; - // Negative support_contact_z is not taken into account, it can result in false positives in cases - // where previous layer has object extrusions too (https://github.com/prusa3d/PrusaSlicer/issues/2752) - - // Only check this layer in case it has some extrusions. - bool has_extrusions = (layer_to_print.object_layer && layer_to_print.object_layer->has_extrusions()) - || (layer_to_print.support_layer && layer_to_print.support_layer->has_extrusions()); - - if (has_extrusions && layer_to_print.print_z() > maximal_print_z + 2. * EPSILON) { - const_cast(object.print())->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL, - _(L("Empty layers detected, the output would not be printable.")) + "\n\n" + - _(L("Object name")) + ": " + object.model_object()->name + "\n" + _(L("Print z")) + ": " + - std::to_string(layers_to_print.back().print_z()) + "\n\n" + _(L("This is " - "usually caused by negligibly small extrusions or by a faulty model. Try to repair " - "the model or change its orientation on the bed."))); - } - - // Remember last layer with extrusions. - if (has_extrusions) - last_extrusion_layer = &layers_to_print.back(); - } - } - - return layers_to_print; + // Calculate a minimum support layer height as a minimum over all extruders, but not smaller than 10um. + // This is the same logic as in support generator. + //FIXME should we use the printing extruders instead? + double gap_over_supports = object.config().support_material_contact_distance; + // FIXME should we test object.config().support_material_synchronize_layers ? Currently the support layers are synchronized with object layers iff soluble supports. + assert(!object.config().support_material || gap_over_supports != 0. || object.config().support_material_synchronize_layers); + if (gap_over_supports != 0.) { + gap_over_supports = std::max(0., gap_over_supports); + // Not a soluble support, + double support_layer_height_min = 1000000.; + for (auto lh : object.print()->config().min_layer_height.values) + support_layer_height_min = std::min(support_layer_height_min, std::max(0.01, lh)); + gap_over_supports += support_layer_height_min; } - // Prepare for non-sequential printing of multiple objects: Support resp. object layers with nearly identical print_z - // will be printed for all objects at once. - // Return a list of items. - std::vector>> GCode::collect_layers_to_print(const Print& print) - { - struct OrderingItem { - coordf_t print_z; - size_t object_idx; - size_t layer_idx; - }; - - std::vector> per_object(print.objects().size(), std::vector()); - std::vector ordering; - for (size_t i = 0; i < print.objects().size(); ++i) { - per_object[i] = collect_layers_to_print(*print.objects()[i]); - OrderingItem ordering_item; - ordering_item.object_idx = i; - ordering.reserve(ordering.size() + per_object[i].size()); - const LayerToPrint& front = per_object[i].front(); - for (const LayerToPrint& ltp : per_object[i]) { - ordering_item.print_z = ltp.print_z(); - ordering_item.layer_idx = <p - &front; - ordering.emplace_back(ordering_item); + // Pair the object layers with the support layers by z. + size_t idx_object_layer = 0; + size_t idx_support_layer = 0; + const LayerToPrint* last_extrusion_layer = nullptr; + while (idx_object_layer < object.layers().size() || idx_support_layer < object.support_layers().size()) { + LayerToPrint layer_to_print; + layer_to_print.object_layer = (idx_object_layer < object.layers().size()) ? object.layers()[idx_object_layer++] : nullptr; + layer_to_print.support_layer = (idx_support_layer < object.support_layers().size()) ? object.support_layers()[idx_support_layer++] : nullptr; + if (layer_to_print.object_layer && layer_to_print.support_layer) { + if (layer_to_print.object_layer->print_z < layer_to_print.support_layer->print_z - EPSILON) { + layer_to_print.support_layer = nullptr; + --idx_support_layer; + } + else if (layer_to_print.support_layer->print_z < layer_to_print.object_layer->print_z - EPSILON) { + layer_to_print.object_layer = nullptr; + --idx_object_layer; } } - std::sort(ordering.begin(), ordering.end(), [](const OrderingItem& oi1, const OrderingItem& oi2) { return oi1.print_z < oi2.print_z; }); + layers_to_print.emplace_back(layer_to_print); - std::vector>> layers_to_print; - // Merge numerically very close Z values. - for (size_t i = 0; i < ordering.size();) { - // Find the last layer with roughly the same print_z. - size_t j = i + 1; - coordf_t zmax = ordering[i].print_z + EPSILON; - for (; j < ordering.size() && ordering[j].print_z <= zmax; ++j); - // Merge into layers_to_print. - std::pair> merged; - // Assign an average print_z to the set of layers with nearly equal print_z. - merged.first = 0.5 * (ordering[i].print_z + ordering[j - 1].print_z); - merged.second.assign(print.objects().size(), LayerToPrint()); - for (; i < j; ++i) { - const OrderingItem& oi = ordering[i]; - assert(merged.second[oi.object_idx].layer() == nullptr); - merged.second[oi.object_idx] = std::move(per_object[oi.object_idx][oi.layer_idx]); - } - layers_to_print.emplace_back(std::move(merged)); + bool has_extrusions = (layer_to_print.object_layer && layer_to_print.object_layer->has_extrusions()) + || (layer_to_print.support_layer && layer_to_print.support_layer->has_extrusions()); + + // Check that there are extrusions on the very first layer. + if (layers_to_print.size() == 1u) { + if (!has_extrusions) + throw std::runtime_error(_(L("There is an object with no extrusions on the first layer."))); } - return layers_to_print; + // In case there are extrusions on this layer, check there is a layer to lay it on. + if ((layer_to_print.object_layer && layer_to_print.object_layer->has_extrusions()) + // Allow empty support layers, as the support generator may produce no extrusions for non-empty support regions. + || (layer_to_print.support_layer /* && layer_to_print.support_layer->has_extrusions() */)) { + double support_contact_z = (last_extrusion_layer && last_extrusion_layer->support_layer) + ? gap_over_supports + : 0.; + double maximal_print_z = (last_extrusion_layer ? last_extrusion_layer->print_z() : 0.) + + layer_to_print.layer()->height + + support_contact_z; + // Negative support_contact_z is not taken into account, it can result in false positives in cases + // where previous layer has object extrusions too (https://github.com/prusa3d/PrusaSlicer/issues/2752) + + if (has_extrusions && layer_to_print.print_z() > maximal_print_z + 2. * EPSILON) { + const_cast(object.print())->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL, + _(L("Empty layers detected, the output would not be printable.")) + "\n\n" + + _(L("Object name")) + ": " + object.model_object()->name + "\n" + _(L("Print z")) + ": " + + std::to_string(layers_to_print.back().print_z()) + "\n\n" + _(L("This is " + "usually caused by negligibly small extrusions or by a faulty model. Try to repair " + "the model or change its orientation on the bed."))); + } + + // Remember last layer with extrusions. + if (has_extrusions) + last_extrusion_layer = &layers_to_print.back(); + } } + return layers_to_print; +} + + +// // Collect pairs of object_layer + support_layer sorted by print_z. +// // object_layer & support_layer are considered to be on the same print_z, if they are not further than EPSILON. +// std::vector GCode::collect_layers_to_print(const PrintObject& object) +// { +// std::vector layers_to_print; +// layers_to_print.reserve(object.layers().size() + object.support_layers().size()); +// +// // Calculate a minimum support layer height as a minimum over all extruders, but not smaller than 10um. +// // This is the same logic as in support generator. +// //FIXME should we use the printing extruders instead? +// double gap_over_supports = object.config().support_material_contact_distance; +// // FIXME should we test object.config().support_material_synchronize_layers ? Currently the support layers are synchronized with object layers iff soluble supports. +// assert(!object.config().support_material || gap_over_supports != 0. || object.config().support_material_synchronize_layers); +// if (gap_over_supports != 0.) { +// gap_over_supports = std::max(0., gap_over_supports); +// // Not a soluble support, +// double support_layer_height_min = 1000000.; +// for (auto lh : object.print()->config().min_layer_height.values) +// support_layer_height_min = std::min(support_layer_height_min, std::max(0.01, lh)); +// gap_over_supports += support_layer_height_min; +// } +// +// // Pair the object layers with the support layers by z. +// size_t idx_object_layer = 0; +// size_t idx_support_layer = 0; +// const LayerToPrint* last_extrusion_layer = nullptr; +// while (idx_object_layer < object.layers().size() || idx_support_layer < object.support_layers().size()) { +// LayerToPrint layer_to_print; +// layer_to_print.object_layer = (idx_object_layer < object.layers().size()) ? object.layers()[idx_object_layer++] : nullptr; +// layer_to_print.support_layer = (idx_support_layer < object.support_layers().size()) ? object.support_layers()[idx_support_layer++] : nullptr; +// if (layer_to_print.object_layer && layer_to_print.support_layer) { +// if (layer_to_print.object_layer->print_z < layer_to_print.support_layer->print_z - EPSILON) { +// layer_to_print.support_layer = nullptr; +// --idx_support_layer; +// } +// else if (layer_to_print.support_layer->print_z < layer_to_print.object_layer->print_z - EPSILON) { +// layer_to_print.object_layer = nullptr; +// --idx_object_layer; +// } +// } +// +//<<<<<<< HEAD +// layers_to_print.emplace_back(layer_to_print); +// +// // Check that there are extrusions on the very first layer. +// if (layers_to_print.size() == 1u) { +// if ((layer_to_print.object_layer && !layer_to_print.object_layer->has_extrusions()) +// || (layer_to_print.support_layer && !layer_to_print.support_layer->has_extrusions())) +// throw std::runtime_error(_(L("There is an object with no extrusions on the first layer."))); +//======= +// layers_to_print.emplace_back(layer_to_print); +// +// bool has_extrusions = (layer_to_print.object_layer && layer_to_print.object_layer->has_extrusions()) +// || (layer_to_print.support_layer && layer_to_print.support_layer->has_extrusions()); +// +// // Check that there are extrusions on the very first layer. +// if (layers_to_print.size() == 1u) { +// if (! has_extrusions) +// throw std::runtime_error(_(L("There is an object with no extrusions on the first layer."))); +// } +// +// // In case there are extrusions on this layer, check there is a layer to lay it on. +// if ((layer_to_print.object_layer && layer_to_print.object_layer->has_extrusions()) +// // Allow empty support layers, as the support generator may produce no extrusions for non-empty support regions. +// || (layer_to_print.support_layer /* && layer_to_print.support_layer->has_extrusions() */)) { +// double support_contact_z = (last_extrusion_layer && last_extrusion_layer->support_layer) +// ? gap_over_supports +// : 0.; +// double maximal_print_z = (last_extrusion_layer ? last_extrusion_layer->print_z() : 0.) +// + layer_to_print.layer()->height +// + support_contact_z; +// // Negative support_contact_z is not taken into account, it can result in false positives in cases +// // where previous layer has object extrusions too (https://github.com/prusa3d/PrusaSlicer/issues/2752) +// +// if (has_extrusions && layer_to_print.print_z() > maximal_print_z + 2. * EPSILON) { +// const_cast(object.print())->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL, +// _(L("Empty layers detected, the output would not be printable.")) + "\n\n" + +// _(L("Object name")) + ": " + object.model_object()->name + "\n" + _(L("Print z")) + ": " + +// std::to_string(layers_to_print.back().print_z()) + "\n\n" + _(L("This is " +// "usually caused by negligibly small extrusions or by a faulty model. Try to repair " +// "the model or change its orientation on the bed."))); +//>>>>>>> b587289c141022323753fa1810552964de0b1356 +// } +// +// // In case there are extrusions on this layer, check there is a layer to lay it on. +// if ((layer_to_print.object_layer && layer_to_print.object_layer->has_extrusions()) +// // Allow empty support layers, as the support generator may produce no extrusions for non-empty support regions. +// || (layer_to_print.support_layer /* && layer_to_print.support_layer->has_extrusions() */)) { +// double support_contact_z = (last_extrusion_layer && last_extrusion_layer->support_layer) +// ? gap_over_supports +// : 0.; +// double maximal_print_z = (last_extrusion_layer ? last_extrusion_layer->print_z() : 0.) +// + layer_to_print.layer()->height +// + support_contact_z; +// // Negative support_contact_z is not taken into account, it can result in false positives in cases +// // where previous layer has object extrusions too (https://github.com/prusa3d/PrusaSlicer/issues/2752) +// +// // Only check this layer in case it has some extrusions. +// bool has_extrusions = (layer_to_print.object_layer && layer_to_print.object_layer->has_extrusions()) +// || (layer_to_print.support_layer && layer_to_print.support_layer->has_extrusions()); +// +// if (has_extrusions && layer_to_print.print_z() > maximal_print_z + 2. * EPSILON) { +// const_cast(object.print())->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL, +// _(L("Empty layers detected, the output would not be printable.")) + "\n\n" + +// _(L("Object name")) + ": " + object.model_object()->name + "\n" + _(L("Print z")) + ": " + +// std::to_string(layers_to_print.back().print_z()) + "\n\n" + _(L("This is " +// "usually caused by negligibly small extrusions or by a faulty model. Try to repair " +// "the model or change its orientation on the bed."))); +// } +// +// // Remember last layer with extrusions. +// if (has_extrusions) +// last_extrusion_layer = &layers_to_print.back(); +// } +// } +// +// return layers_to_print; +// } +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + +// Prepare for non-sequential printing of multiple objects: Support resp. object layers with nearly identical print_z +// will be printed for all objects at once. +// Return a list of items. +std::vector>> GCode::collect_layers_to_print(const Print& print) +{ + struct OrderingItem { + coordf_t print_z; + size_t object_idx; + size_t layer_idx; + }; + + std::vector> per_object(print.objects().size(), std::vector()); + std::vector ordering; + for (size_t i = 0; i < print.objects().size(); ++i) { + per_object[i] = collect_layers_to_print(*print.objects()[i]); + OrderingItem ordering_item; + ordering_item.object_idx = i; + ordering.reserve(ordering.size() + per_object[i].size()); + const LayerToPrint& front = per_object[i].front(); + for (const LayerToPrint& ltp : per_object[i]) { + ordering_item.print_z = ltp.print_z(); + ordering_item.layer_idx = <p - &front; + ordering.emplace_back(ordering_item); + } + } + + std::sort(ordering.begin(), ordering.end(), [](const OrderingItem& oi1, const OrderingItem& oi2) { return oi1.print_z < oi2.print_z; }); + + std::vector>> layers_to_print; + // Merge numerically very close Z values. + for (size_t i = 0; i < ordering.size();) { + // Find the last layer with roughly the same print_z. + size_t j = i + 1; + coordf_t zmax = ordering[i].print_z + EPSILON; + for (; j < ordering.size() && ordering[j].print_z <= zmax; ++j); + // Merge into layers_to_print. + std::pair> merged; + // Assign an average print_z to the set of layers with nearly equal print_z. + merged.first = 0.5 * (ordering[i].print_z + ordering[j - 1].print_z); + merged.second.assign(print.objects().size(), LayerToPrint()); + for (; i < j; ++i) { + const OrderingItem& oi = ordering[i]; + assert(merged.second[oi.object_idx].layer() == nullptr); + merged.second[oi.object_idx] = std::move(per_object[oi.object_idx][oi.layer_idx]); + } + layers_to_print.emplace_back(std::move(merged)); + } + + return layers_to_print; +} + #if ENABLE_GCODE_VIEWER void GCode::do_export(Print* print, const char* path, GCodeProcessor::Result* result, ThumbnailsGeneratorCallback thumbnail_cb) #else diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index d6a23d75d3..0c1c828f7e 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1122,7 +1122,7 @@ void PrintConfigDef::init_fff_params() def = this->add("ironing_spacing", coFloat); def->label = L("Spacing between ironing passes"); - def->tooltip = L("Distance between ironing lins"); + def->tooltip = L("Distance between ironing lines"); def->sidetext = L("mm"); def->min = 0; def->mode = comExpert;