diff --git a/src/libslic3r/Format/SL1.cpp b/src/libslic3r/Format/SL1.cpp index e2ef801f2..4ddc584ba 100644 --- a/src/libslic3r/Format/SL1.cpp +++ b/src/libslic3r/Format/SL1.cpp @@ -203,7 +203,7 @@ RasterParams get_raster_params(const DynamicPrintConfig &cfg) if (!opt_disp_cols || !opt_disp_rows || !opt_disp_w || !opt_disp_h || !opt_mirror_x || !opt_mirror_y || !opt_orient) - throw Slic3r::FileIOError("Invalid SL1 / SL1S file"); + throw MissingProfileError("Invalid SL1 / SL1S file"); RasterParams rstp; @@ -229,7 +229,7 @@ SliceParams get_slice_params(const DynamicPrintConfig &cfg) auto *opt_init_layerh = cfg.option("initial_layer_height"); if (!opt_layerh || !opt_init_layerh) - throw Slic3r::FileIOError("Invalid SL1 / SL1S file"); + throw MissingProfileError("Invalid SL1 / SL1S file"); return SliceParams{opt_layerh->getFloat(), opt_init_layerh->getFloat()}; } @@ -293,24 +293,34 @@ ConfigSubstitutions import_sla_archive(const std::string &zipfname, DynamicPrint return out.load(arch.profile, ForwardCompatibilitySubstitutionRule::Enable); } +// If the profile is missing from the archive (older PS versions did not have +// it), profile_out's initial value will be used as fallback. profile_out will be empty on +// function return if the archive did not contain any profile. ConfigSubstitutions import_sla_archive( const std::string & zipfname, Vec2i windowsize, indexed_triangle_set & out, - DynamicPrintConfig & profile, + DynamicPrintConfig & profile_out, std::function progr) { // Ensure minimum window size for marching squares windowsize.x() = std::max(2, windowsize.x()); windowsize.y() = std::max(2, windowsize.y()); - ArchiveData arch = extract_sla_archive(zipfname, "thumbnail"); - ConfigSubstitutions config_substitutions = profile.load(arch.profile, ForwardCompatibilitySubstitutionRule::Enable); + std::string exclude_entries{"thumbnail"}; + ArchiveData arch = extract_sla_archive(zipfname, exclude_entries); + DynamicPrintConfig profile_in, profile_use; + ConfigSubstitutions config_substitutions = profile_in.load(arch.profile, ForwardCompatibilitySubstitutionRule::Enable); - RasterParams rstp = get_raster_params(profile); + // If the archive contains an empty profile, use the one that was passed as output argument + // then replace it with the readed profile to report that it was empty. + profile_use = profile_in.empty() ? profile_out : profile_in; + profile_out = profile_in; + + RasterParams rstp = get_raster_params(profile_use); rstp.win = {windowsize.y(), windowsize.x()}; - SliceParams slicp = get_slice_params(profile); + SliceParams slicp = get_slice_params(profile_use); std::vector slices = extract_slices_from_sla_archive(arch, rstp, progr); diff --git a/src/libslic3r/Format/SL1.hpp b/src/libslic3r/Format/SL1.hpp index c2aef30f4..7f4356b12 100644 --- a/src/libslic3r/Format/SL1.hpp +++ b/src/libslic3r/Format/SL1.hpp @@ -57,6 +57,8 @@ inline ConfigSubstitutions import_sla_archive( return import_sla_archive(zipfname, windowsize, out, profile, progr); } +class MissingProfileError : public RuntimeError { using RuntimeError::RuntimeError; }; + } // namespace Slic3r::sla #endif // ARCHIVETRAITS_HPP diff --git a/src/slic3r/GUI/Jobs/SLAImportJob.cpp b/src/slic3r/GUI/Jobs/SLAImportJob.cpp index e63202862..3d611ffc3 100644 --- a/src/slic3r/GUI/Jobs/SLAImportJob.cpp +++ b/src/slic3r/GUI/Jobs/SLAImportJob.cpp @@ -6,6 +6,7 @@ #include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/GUI_ObjectList.hpp" +#include "slic3r/GUI/NotificationManager.hpp" #include "libslic3r/Model.hpp" #include "libslic3r/PresetBundle.hpp" @@ -144,16 +145,16 @@ void SLAImportJob::process() try { switch (p->sel) { case Sel::modelAndProfile: - p->config_substitutions = import_sla_archive(path, p->win, p->mesh, p->profile, progr); - break; case Sel::modelOnly: - p->config_substitutions = import_sla_archive(path, p->win, p->mesh, progr); + p->config_substitutions = import_sla_archive(path, p->win, p->mesh, p->profile, progr); break; case Sel::profileOnly: p->config_substitutions = import_sla_archive(path, p->profile); break; } - + } catch (MissingProfileError &) { + p->err = _L("The archive doesn't contain any profile data. Try to import after switching " + "to an SLA profile that can be used as fallback.").ToStdString(); } catch (std::exception &ex) { p->err = ex.what(); } @@ -166,7 +167,7 @@ void SLAImportJob::reset() { p->sel = Sel::modelAndProfile; p->mesh = {}; - p->profile = {}; + p->profile = m_plater->sla_print().full_print_config(); p->win = {2, 2}; p->path.Clear(); } @@ -202,7 +203,18 @@ void SLAImportJob::finalize() std::string name = wxFileName(p->path).GetName().ToUTF8().data(); - if (!p->profile.empty()) { + if (p->profile.empty()) { + m_plater->get_notification_manager()->push_notification( + NotificationType::CustomNotification, + NotificationManager::NotificationLevel::WarningNotificationLevel, + _L("Loaded archive did not contain any profile data. " + "The current SLA profile was used as fallback.").ToStdString()); + } + + if (p->sel != Sel::modelOnly) { + if (p->profile.empty()) + p->profile = m_plater->sla_print().full_print_config(); + const ModelObjectPtrs& objects = p->plater->model().objects; for (auto object : objects) if (object->volumes.size() > 1)