diff --git a/src/PrusaSlicer.cpp b/src/PrusaSlicer.cpp index 881230ff59..584c49a8ab 100644 --- a/src/PrusaSlicer.cpp +++ b/src/PrusaSlicer.cpp @@ -606,9 +606,6 @@ int CLI::run(int argc, char **argv) model.add_default_instances(); if (! this->export_models(IO::OBJ)) return 1; - } else if (opt_key == "export_amf") { - if (! this->export_models(IO::AMF)) - return 1; } else if (opt_key == "export_3mf") { if (! this->export_models(IO::TMF)) return 1; @@ -955,7 +952,6 @@ bool CLI::export_models(IO::ExportFormat format) const std::string path = this->output_filepath(model, format); bool success = false; switch (format) { - case IO::AMF: success = Slic3r::store_amf(path.c_str(), &model, nullptr, false); break; case IO::OBJ: success = Slic3r::store_obj(path.c_str(), &model); break; case IO::STL: success = Slic3r::store_stl(path.c_str(), &model, true); break; case IO::TMF: success = Slic3r::store_3mf(path.c_str(), &model, nullptr, false); break; @@ -975,7 +971,6 @@ std::string CLI::output_filepath(const Model &model, IO::ExportFormat format) co { std::string ext; switch (format) { - case IO::AMF: ext = ".zip.amf"; break; case IO::OBJ: ext = ".obj"; break; case IO::STL: ext = ".stl"; break; case IO::TMF: ext = ".3mf"; break; diff --git a/src/PrusaSlicer.hpp b/src/PrusaSlicer.hpp index b11e1b5d30..b26000a320 100644 --- a/src/PrusaSlicer.hpp +++ b/src/PrusaSlicer.hpp @@ -8,7 +8,6 @@ namespace Slic3r { namespace IO { enum ExportFormat : int { - AMF, OBJ, STL, // SVG, diff --git a/src/libslic3r/Format/AMF.cpp b/src/libslic3r/Format/AMF.cpp index aedd126343..0c21aa52a5 100644 --- a/src/libslic3r/Format/AMF.cpp +++ b/src/libslic3r/Format/AMF.cpp @@ -1101,283 +1101,4 @@ bool load_amf(const char* path, DynamicPrintConfig* config, ConfigSubstitutionCo return false; } -bool store_amf(const char* path, Model* model, const DynamicPrintConfig* config, bool fullpath_sources) -{ - if ((path == nullptr) || (model == nullptr)) - return false; - - // forces ".zip.amf" extension - std::string export_path = path; - if (!boost::iends_with(export_path, ".zip.amf")) - export_path = boost::filesystem::path(export_path).replace_extension(".zip.amf").string(); - - mz_zip_archive archive; - mz_zip_zero_struct(&archive); - - if (!open_zip_writer(&archive, export_path)) return false; - - std::stringstream stream; - // https://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10 - // Conversion of a floating-point value to text and back is exact as long as at least max_digits10 were used (9 for float, 17 for double). - // It is guaranteed to produce the same floating-point value, even though the intermediate text representation is not exact. - // The default value of std::stream precision is 6 digits only! - stream << std::setprecision(std::numeric_limits::max_digits10); - stream << "\n"; - stream << "\n"; - stream << "Slic3r " << SLIC3R_VERSION << "\n"; - stream << "" << VERSION_AMF << "\n"; - - if (config != nullptr) - { - std::string str_config = "\n"; - for (const std::string &key : config->keys()) - if (key != "compatible_printers") - str_config += "; " + key + " = " + config->opt_serialize(key) + "\n"; - stream << "" << xml_escape(str_config) << "\n"; - } - - for (const auto &material : model->materials) { - if (material.first.empty()) - continue; - // note that material-id must never be 0 since it's reserved by the AMF spec - stream << " \n"; - for (const auto &attr : material.second->attributes) - stream << " " << attr.second << "\n"; - for (const std::string &key : material.second->config.keys()) - stream << " " << material.second->config.opt_serialize(key) << "\n"; - stream << " \n"; - } - std::string instances; - for (size_t object_id = 0; object_id < model->objects.size(); ++ object_id) { - ModelObject *object = model->objects[object_id]; - stream << " \n"; - for (const std::string &key : object->config.keys()) - stream << " " << object->config.opt_serialize(key) << "\n"; - if (!object->name.empty()) - stream << " " << xml_escape(object->name) << "\n"; - const std::vector &layer_height_profile = object->layer_height_profile.get(); - if (layer_height_profile.size() >= 4 && (layer_height_profile.size() % 2) == 0) { - // Store the layer height profile as a single semicolon separated list. - stream << " "; - stream << layer_height_profile.front(); - for (size_t i = 1; i < layer_height_profile.size(); ++i) - stream << ";" << layer_height_profile[i]; - stream << "\n \n"; - } - - // Export layer height ranges including the layer range specific config overrides. - const t_layer_config_ranges& config_ranges = object->layer_config_ranges; - if (!config_ranges.empty()) - { - // Store the layer config range as a single semicolon separated list. - stream << " \n"; - size_t layer_counter = 0; - for (const auto &range : config_ranges) { - stream << " \n"; - - stream << " "; - stream << range.first.first << ";" << range.first.second << "\n"; - - for (const std::string& key : range.second.keys()) - stream << " " << range.second.opt_serialize(key) << "\n"; - - stream << " \n"; - layer_counter++; - } - - stream << " \n"; - } - - - const std::vector& sla_support_points = object->sla_support_points; - if (!sla_support_points.empty()) { - // Store the SLA supports as a single semicolon separated list. - stream << " "; - for (size_t i = 0; i < sla_support_points.size(); ++i) { - if (i != 0) - stream << ";"; - stream << sla_support_points[i].pos(0) << ";" << sla_support_points[i].pos(1) << ";" << sla_support_points[i].pos(2) << ";" << sla_support_points[i].head_front_radius << ";" << sla_support_points[i].is_new_island; - } - stream << "\n \n"; - } - - stream << " \n"; - stream << " \n"; - std::vector vertices_offsets; - int num_vertices = 0; - for (ModelVolume *volume : object->volumes) { - vertices_offsets.push_back(num_vertices); - const indexed_triangle_set &its = volume->mesh().its; - const Transform3d& matrix = volume->get_matrix(); - for (size_t i = 0; i < its.vertices.size(); ++i) { - stream << " \n"; - stream << " \n"; - Vec3f v = (matrix * its.vertices[i].cast()).cast(); - stream << " " << v(0) << "\n"; - stream << " " << v(1) << "\n"; - stream << " " << v(2) << "\n"; - stream << " \n"; - stream << " \n"; - } - num_vertices += (int)its.vertices.size(); - } - stream << " \n"; - for (size_t i_volume = 0; i_volume < object->volumes.size(); ++i_volume) { - ModelVolume *volume = object->volumes[i_volume]; - int vertices_offset = vertices_offsets[i_volume]; - if (volume->material_id().empty()) - stream << " \n"; - else - stream << " material_id() << "\">\n"; - for (const std::string &key : volume->config.keys()) - stream << " " << volume->config.opt_serialize(key) << "\n"; - if (!volume->name.empty()) - stream << " " << xml_escape(volume->name) << "\n"; - if (volume->is_modifier()) - stream << " 1\n"; - stream << " " << ModelVolume::type_to_string(volume->type()) << "\n"; - stream << " "; - const Transform3d& matrix = volume->get_matrix() * volume->source.transform.get_matrix(); - stream << std::setprecision(std::numeric_limits::max_digits10); - for (int r = 0; r < 4; ++r) { - for (int c = 0; c < 4; ++c) { - stream << matrix(r, c); - if (r != 3 || c != 3) - stream << " "; - } - } - stream << "\n"; - if (!volume->source.input_file.empty()) { - std::string input_file = xml_escape(fullpath_sources ? volume->source.input_file : boost::filesystem::path(volume->source.input_file).filename().string()); - stream << " " << input_file << "\n"; - stream << " " << volume->source.object_idx << "\n"; - stream << " " << volume->source.volume_idx << "\n"; - stream << " " << volume->source.mesh_offset(0) << "\n"; - stream << " " << volume->source.mesh_offset(1) << "\n"; - stream << " " << volume->source.mesh_offset(2) << "\n"; - } - assert(! volume->source.is_converted_from_inches || ! volume->source.is_converted_from_meters); - if (volume->source.is_converted_from_inches) - stream << " 1\n"; - else if (volume->source.is_converted_from_meters) - stream << " 1\n"; - if (volume->source.is_from_builtin_objects) - stream << " 1\n"; - stream << std::setprecision(std::numeric_limits::max_digits10); - const indexed_triangle_set &its = volume->mesh().its; - for (size_t i = 0; i < its.indices.size(); ++i) { - stream << " \n"; - for (int j = 0; j < 3; ++j) - stream << " " << its.indices[i][j] + vertices_offset << "\n"; - stream << " \n"; - } - stream << " \n"; - } - stream << " \n"; - stream << " \n"; - if (!object->instances.empty()) { - for (ModelInstance *instance : object->instances) { - std::stringstream buf; - buf << " \n" - << " " << instance->get_offset(X) << "\n" - << " " << instance->get_offset(Y) << "\n" - << " " << instance->get_offset(Z) << "\n" - << " " << instance->get_rotation(X) << "\n" - << " " << instance->get_rotation(Y) << "\n" - << " " << instance->get_rotation(Z) << "\n" - << " " << instance->get_scaling_factor(X) << "\n" - << " " << instance->get_scaling_factor(Y) << "\n" - << " " << instance->get_scaling_factor(Z) << "\n" - << " " << instance->get_mirror(X) << "\n" - << " " << instance->get_mirror(Y) << "\n" - << " " << instance->get_mirror(Z) << "\n" - << " " << instance->printable << "\n" - << " \n"; - - //FIXME missing instance->scaling_factor - instances.append(buf.str()); - } - } - } - if (! instances.empty()) { - stream << " \n"; - stream << instances; - stream << " \n"; - } - - if (!model->custom_gcode_per_print_z.gcodes.empty()) - { - std::string out = ""; - pt::ptree tree; - - pt::ptree& main_tree = tree.add("custom_gcodes_per_height", ""); - - for (const CustomGCode::Item& code : model->custom_gcode_per_print_z.gcodes) - { - pt::ptree& code_tree = main_tree.add("code", ""); - // store custom_gcode_per_print_z gcodes information - code_tree.put(".print_z" , code.print_z ); - code_tree.put(".type" , static_cast(code.type)); - code_tree.put(".extruder" , code.extruder ); - code_tree.put(".color" , code.color ); - code_tree.put(".extra" , code.extra ); - - // add gcode field data for the old version of the PrusaSlicer - std::string gcode = code.type == CustomGCode::ColorChange ? config->opt_string("color_change_gcode") : - code.type == CustomGCode::PausePrint ? config->opt_string("pause_print_gcode") : - code.type == CustomGCode::Template ? config->opt_string("template_custom_gcode") : - code.type == CustomGCode::ToolChange ? "tool_change" : code.extra; - code_tree.put(".gcode" , gcode ); - } - - pt::ptree& mode_tree = main_tree.add("mode", ""); - // store mode of a custom_gcode_per_print_z - mode_tree.put(".value", - model->custom_gcode_per_print_z.mode == CustomGCode::Mode::SingleExtruder ? CustomGCode::SingleExtruderMode : - model->custom_gcode_per_print_z.mode == CustomGCode::Mode::MultiAsSingle ? - CustomGCode::MultiAsSingleMode : CustomGCode::MultiExtruderMode); - - if (!tree.empty()) - { - std::ostringstream oss; - pt::write_xml(oss, tree); - out = oss.str(); - - size_t del_header_pos = out.find("\n \n <", ">\n<"); - - stream << out << "\n"; - } - } - - stream << "\n"; - - std::string internal_amf_filename = boost::ireplace_last_copy(boost::filesystem::path(export_path).filename().string(), ".zip.amf", ".amf"); - std::string out = stream.str(); - - if (!mz_zip_writer_add_mem(&archive, internal_amf_filename.c_str(), (const void*)out.data(), out.length(), MZ_DEFAULT_COMPRESSION)) - { - close_zip_writer(&archive); - boost::filesystem::remove(export_path); - return false; - } - - if (!mz_zip_writer_finalize_archive(&archive)) - { - close_zip_writer(&archive); - boost::filesystem::remove(export_path); - return false; - } - - close_zip_writer(&archive); - - return true; -} - }; // namespace Slic3r diff --git a/src/libslic3r/Format/AMF.hpp b/src/libslic3r/Format/AMF.hpp index 20f0676c9c..8cfe816679 100644 --- a/src/libslic3r/Format/AMF.hpp +++ b/src/libslic3r/Format/AMF.hpp @@ -17,9 +17,8 @@ class DynamicPrintConfig; // Load the content of an amf file into the given model and configuration. extern bool load_amf(const char* path, DynamicPrintConfig* config, ConfigSubstitutionContext* config_substitutions, Model* model, bool check_version); -// Save the given model and the config data into an amf file. -// The model could be modified during the export process if meshes are not repaired or have no shared vertices -extern bool store_amf(const char* path, Model* model, const DynamicPrintConfig* config, bool fullpath_sources); +// Function to save AMF has been removed in 2.9.0, we no longer support saving data in AMF format. +// The option has been missing in the UI since 2.4.0 (except for CLI). } // namespace Slic3r diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 3235b023c8..ccaeb57efd 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -5521,11 +5521,6 @@ CLIActionsConfigDef::CLIActionsConfigDef() def->tooltip = L("Export the model(s) as 3MF."); def->set_default_value(new ConfigOptionBool(false)); - def = this->add("export_amf", coBool); - def->label = L("Export AMF"); - def->tooltip = L("Export the model(s) as AMF."); - def->set_default_value(new ConfigOptionBool(false)); - def = this->add("export_stl", coBool); def->label = L("Export STL"); def->tooltip = L("Export the model(s) as STL.");