diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 1edc3b50e5..adf25d9e10 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -3888,8 +3888,10 @@ bool _3MF_Exporter::_add_wipe_tower_information_file_to_archive( mz_zip_archive& } // Perform conversions based on the config values available. -static void handle_legacy_project_loaded(unsigned int version_project_file, DynamicPrintConfig& config, const boost::optional& prusaslicer_generator_version) -{ +static void handle_legacy_project_loaded( + DynamicPrintConfig& config, + const boost::optional& prusaslicer_generator_version +) { if (! config.has("brim_separation")) { if (auto *opt_elephant_foot = config.option("elefant_foot_compensation", false); opt_elephant_foot) { // Conversion from older PrusaSlicer which applied brim separation equal to elephant foot compensation. @@ -3897,7 +3899,7 @@ static void handle_legacy_project_loaded(unsigned int version_project_file, Dyna opt_brim_separation->value = opt_elephant_foot->value; } } - + // In PrusaSlicer 2.5.0-alpha2 and 2.5.0-alpha3, we introduce several parameters for Arachne that depend // on nozzle size . Later we decided to make default values for those parameters computed automatically // until the user changes them. @@ -3946,7 +3948,14 @@ bool is_project_3mf(const std::string& filename) return config_found; } -bool load_3mf(const char* path, DynamicPrintConfig& config, ConfigSubstitutionContext& config_substitutions, Model* model, bool check_version) +bool load_3mf( + const char* path, + DynamicPrintConfig& config, + ConfigSubstitutionContext& config_substitutions, + Model* model, + bool check_version, + boost::optional &prusaslicer_generator_version +) { if (path == nullptr || model == nullptr) return false; @@ -3956,7 +3965,8 @@ bool load_3mf(const char* path, DynamicPrintConfig& config, ConfigSubstitutionCo _3MF_Importer importer; bool res = importer.load_model_from_file(path, *model, config, config_substitutions, check_version); importer.log_errors(); - handle_legacy_project_loaded(importer.version(), config, importer.prusaslicer_generator_version()); + handle_legacy_project_loaded(config, importer.prusaslicer_generator_version()); + prusaslicer_generator_version = importer.prusaslicer_generator_version(); return res; } diff --git a/src/libslic3r/Format/3mf.hpp b/src/libslic3r/Format/3mf.hpp index 3547003b49..78f95b7db0 100644 --- a/src/libslic3r/Format/3mf.hpp +++ b/src/libslic3r/Format/3mf.hpp @@ -5,6 +5,8 @@ #ifndef slic3r_Format_3mf_hpp_ #define slic3r_Format_3mf_hpp_ +#include "libslic3r/Semver.hpp" +#include namespace Slic3r { /* The format for saving the SLA points was changing in the past. This enum holds the latest version that is being currently used. @@ -37,7 +39,14 @@ namespace Slic3r { extern bool is_project_3mf(const std::string& filename); // Load the content of a 3mf file into the given model and preset bundle. - extern bool load_3mf(const char* path, DynamicPrintConfig& config, ConfigSubstitutionContext& config_substitutions, Model* model, bool check_version); + extern bool load_3mf( + const char* path, + DynamicPrintConfig& config, + ConfigSubstitutionContext& config_substitutions, + Model* model, + bool check_version, + boost::optional &prusaslicer_generator_version + ); // Save the given model and the config data contained in the given Print into a 3mf file. // The model could be modified during the export process if meshes are not repaired or have no shared vertices diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index a899e14cc9..d843ebaa92 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -171,10 +171,11 @@ Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* c result = load_step(input_file.c_str(), &model); else if (boost::algorithm::iends_with(input_file, ".amf") || boost::algorithm::iends_with(input_file, ".amf.xml")) result = load_amf(input_file.c_str(), config, config_substitutions, &model, options & LoadAttribute::CheckVersion); - else if (boost::algorithm::iends_with(input_file, ".3mf") || boost::algorithm::iends_with(input_file, ".zip")) + else if (boost::algorithm::iends_with(input_file, ".3mf") || boost::algorithm::iends_with(input_file, ".zip")) { //FIXME options & LoadAttribute::CheckVersion ? - result = load_3mf(input_file.c_str(), *config, *config_substitutions, &model, false); - else if (boost::algorithm::iends_with(input_file, ".svg")) + boost::optional prusaslicer_generator_version; + result = load_3mf(input_file.c_str(), *config, *config_substitutions, &model, false, prusaslicer_generator_version); + } else if (boost::algorithm::iends_with(input_file, ".svg")) result = load_svg(input_file, model); else if (boost::ends_with(input_file, ".printRequest")) result = load_printRequest(input_file.c_str(), &model); @@ -204,17 +205,22 @@ Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* c } // Loading model from a file (3MF or AMF), not from a simple geometry file (STL or OBJ). -Model Model::read_from_archive(const std::string& input_file, DynamicPrintConfig* config, ConfigSubstitutionContext* config_substitutions, LoadAttributes options) -{ +Model Model::read_from_archive( + const std::string& input_file, + DynamicPrintConfig* config, + ConfigSubstitutionContext* config_substitutions, + boost::optional &prusaslicer_generator_version, + LoadAttributes options +) { assert(config != nullptr); assert(config_substitutions != nullptr); Model model; bool result = false; - if (boost::algorithm::iends_with(input_file, ".3mf") || boost::algorithm::iends_with(input_file, ".zip")) - result = load_3mf(input_file.c_str(), *config, *config_substitutions, &model, options & LoadAttribute::CheckVersion); - else if (boost::algorithm::iends_with(input_file, ".zip.amf")) + if (boost::algorithm::iends_with(input_file, ".3mf") || boost::algorithm::iends_with(input_file, ".zip")) { + result = load_3mf(input_file.c_str(), *config, *config_substitutions, &model, options & LoadAttribute::CheckVersion, prusaslicer_generator_version); + } else if (boost::algorithm::iends_with(input_file, ".zip.amf")) result = load_amf(input_file.c_str(), config, config_substitutions, &model, options & LoadAttribute::CheckVersion); else throw Slic3r::RuntimeError("Unknown file format. Input file must have .3mf or .zip.amf extension."); diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index d110beece2..62e4312f85 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -1329,9 +1329,12 @@ public: DynamicPrintConfig* config = nullptr, ConfigSubstitutionContext* config_substitutions = nullptr, LoadAttributes options = LoadAttribute::AddDefaultInstances); static Model read_from_archive( - const std::string& input_file, - DynamicPrintConfig* config, ConfigSubstitutionContext* config_substitutions, - LoadAttributes options = LoadAttribute::AddDefaultInstances); + const std::string& input_file, + DynamicPrintConfig* config, + ConfigSubstitutionContext* config_substitutions, + boost::optional &prusaslicer_generator_version, + LoadAttributes options = LoadAttribute::AddDefaultInstances + ); // Add a new ModelObject to this Model, generate a new ID for this ModelObject. ModelObject* add_object(); diff --git a/src/libslic3r/MultipleBeds.cpp b/src/libslic3r/MultipleBeds.cpp index 67e94ced42..6c8a803c06 100644 --- a/src/libslic3r/MultipleBeds.cpp +++ b/src/libslic3r/MultipleBeds.cpp @@ -218,7 +218,7 @@ void MultipleBeds::update_shown_beds(Model& model, const BuildVolume& build_volu set_active_bed(m_number_of_beds != original_number_of_beds ? 0 : stash_active); } -bool MultipleBeds::rearrange_after_load(Model& model, const BuildVolume& build_volume, std::function update_fn) +bool MultipleBeds::rearrange_after_load(Model& model, const BuildVolume& build_volume) { int original_number_of_beds = m_number_of_beds; int stash_active = get_active_bed(); @@ -233,7 +233,6 @@ bool MultipleBeds::rearrange_after_load(Model& model, const BuildVolume& build_v model.update_print_volume_state(build_volume); request_next_bed(false); set_active_bed(m_number_of_beds != original_number_of_beds ? 0 : stash_active); - update_fn(); }); m_legacy_layout = true; diff --git a/src/libslic3r/MultipleBeds.hpp b/src/libslic3r/MultipleBeds.hpp index ac27a710ab..d5209d2315 100644 --- a/src/libslic3r/MultipleBeds.hpp +++ b/src/libslic3r/MultipleBeds.hpp @@ -54,7 +54,7 @@ public: int get_last_hovered_bed() const { return m_last_hovered_bed; } void update_shown_beds(Model& model, const BuildVolume& build_volume, bool only_remove = false); - bool rearrange_after_load(Model& model, const BuildVolume& build_volume, std::function update_fn); + bool rearrange_after_load(Model& model, const BuildVolume& build_volume); void set_loading_project_flag(bool project) { m_loading_project = project; } bool get_loading_project_flag() const { return m_loading_project; } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 39060650b0..07e281ce84 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1245,6 +1245,7 @@ std::vector Plater::priv::load_files(const std::vector& input_ auto *new_model = (!load_model || one_by_one) ? nullptr : new Slic3r::Model(); std::vector obj_idxs; + boost::optional prusaslicer_generator_version; int answer_convert_from_meters = wxOK_DEFAULT; int answer_convert_from_imperial_units = wxOK_DEFAULT; @@ -1285,6 +1286,7 @@ std::vector Plater::priv::load_files(const std::vector& input_ Slic3r::Model model; bool is_project_file = type_prusa; + try { if (type_3mf || type_zip_amf) { #ifdef __linux__ @@ -1304,7 +1306,13 @@ std::vector Plater::priv::load_files(const std::vector& input_ { DynamicPrintConfig config_loaded; ConfigSubstitutionContext config_substitutions{ ForwardCompatibilitySubstitutionRule::Enable }; - model = Slic3r::Model::read_from_archive(path.string(), &config_loaded, &config_substitutions, only_if(load_config, Model::LoadAttribute::CheckVersion)); + model = Slic3r::Model::read_from_archive( + path.string(), + &config_loaded, + &config_substitutions, + prusaslicer_generator_version, + only_if(load_config, Model::LoadAttribute::CheckVersion) + ); if (load_config && !config_loaded.empty()) { // Based on the printer technology field found in the loaded config, select the base for the config, loaded_printer_technology = Preset::printer_technology(config_loaded); @@ -1600,15 +1608,20 @@ std::vector Plater::priv::load_files(const std::vector& input_ // this is required because the selected object changed and the flatten on face an sla support gizmos need to be updated accordingly view3D->get_canvas3d()->update_gizmos_on_off_state(); } - + GLGizmoSimplify::add_simplify_suggestion_notification( obj_idxs, model.objects, *notification_manager); - s_multiple_beds.rearrange_after_load(model, q->build_volume(), [this]() { - q->canvas3D()->check_volumes_outside_state(); - s_multiple_beds.ensure_wipe_towers_on_beds(model, fff_prints); - s_multiple_beds.update_shown_beds(model, q->build_volume()); - }); + if ( + prusaslicer_generator_version + && *prusaslicer_generator_version < Semver("2.9.0-alpha1") + ) { + BOOST_LOG_TRIVIAL(info) << "Rearranging legacy project..."; + s_multiple_beds.rearrange_after_load(model, q->build_volume()); + } + q->canvas3D()->check_volumes_outside_state(); + s_multiple_beds.ensure_wipe_towers_on_beds(model, fff_prints); + s_multiple_beds.update_shown_beds(model, q->build_volume()); update(); return obj_idxs; diff --git a/src/slic3r/Utils/FixModelByWin10.cpp b/src/slic3r/Utils/FixModelByWin10.cpp index c42856e16b..41f9b8a72b 100644 --- a/src/slic3r/Utils/FixModelByWin10.cpp +++ b/src/slic3r/Utils/FixModelByWin10.cpp @@ -37,6 +37,7 @@ #include "libslic3r/Print.hpp" #include "libslic3r/PresetBundle.hpp" #include "libslic3r/Format/3mf.hpp" +#include "libslic3r/Semver.hpp" #include "../GUI/GUI.hpp" #include "../GUI/I18N.hpp" #include "../GUI/MsgDialog.hpp" @@ -392,7 +393,8 @@ bool fix_model_by_win10_sdk_gui(ModelObject &model_object, int volume_idx, wxPro on_progress(L("Loading repaired model"), 80); DynamicPrintConfig config; ConfigSubstitutionContext config_substitutions{ ForwardCompatibilitySubstitutionRule::EnableSilent }; - bool loaded = Slic3r::load_3mf(path_dst.string().c_str(), config, config_substitutions, &model, false); + boost::optional prusaslicer_generator_version; + bool loaded = Slic3r::load_3mf(path_dst.string().c_str(), config, config_substitutions, &model, false, prusaslicer_generator_version); boost::filesystem::remove(path_dst); if (! loaded) throw Slic3r::RuntimeError("Import of the repaired 3mf file failed"); diff --git a/tests/fff_print/test_data.hpp b/tests/fff_print/test_data.hpp index 939d1a7631..9eee9c9d2e 100644 --- a/tests/fff_print/test_data.hpp +++ b/tests/fff_print/test_data.hpp @@ -165,7 +165,8 @@ inline std::unique_ptr process_3mf(const std::filesystem::path &path) { Model model; ConfigSubstitutionContext context{ForwardCompatibilitySubstitutionRule::Disable}; - load_3mf(path.string().c_str(), config, context, &model, false); + boost::optional version; + load_3mf(path.string().c_str(), config, context, &model, false, version); Slic3r::Test::init_print(std::vector{}, *print, model, config); print->process(); diff --git a/tests/libslic3r/test_3mf.cpp b/tests/libslic3r/test_3mf.cpp index 3602d6972d..dc9a3d55c7 100644 --- a/tests/libslic3r/test_3mf.cpp +++ b/tests/libslic3r/test_3mf.cpp @@ -15,7 +15,8 @@ SCENARIO("Reading 3mf file", "[3mf]") { std::string path = std::string(TEST_DATA_DIR) + "/test_3mf/Geräte/Büchse.3mf"; DynamicPrintConfig config; ConfigSubstitutionContext ctxt{ ForwardCompatibilitySubstitutionRule::Disable }; - bool ret = load_3mf(path.c_str(), config, ctxt, &model, false); + boost::optional version; + bool ret = load_3mf(path.c_str(), config, ctxt, &model, false, version); THEN("load should succeed") { REQUIRE(ret); } @@ -59,7 +60,8 @@ SCENARIO("Export+Import geometry to/from 3mf file cycle", "[3mf]") { DynamicPrintConfig dst_config; { ConfigSubstitutionContext ctxt{ ForwardCompatibilitySubstitutionRule::Disable }; - load_3mf(test_file.c_str(), dst_config, ctxt, &dst_model, false); + boost::optional version; + load_3mf(test_file.c_str(), dst_config, ctxt, &dst_model, false, version); } boost::filesystem::remove(test_file);