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 2c7e1edc1..7f4356b12 100644 --- a/src/libslic3r/Format/SL1.hpp +++ b/src/libslic3r/Format/SL1.hpp @@ -8,7 +8,7 @@ namespace Slic3r { -class SL1Archive: public SLAPrinter { +class SL1Archive: public SLAArchive { SLAPrinterConfig m_cfg; protected: @@ -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/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index a09f5ea98..7899d173e 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -670,7 +670,7 @@ std::string SLAPrint::validate(std::string*) const return ""; } -void SLAPrint::set_printer(SLAPrinter *arch) +void SLAPrint::set_printer(SLAArchive *arch) { invalidate_step(slapsRasterize); m_printer = arch; diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index e11926c7e..deaabbe19 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -387,7 +387,7 @@ struct SLAPrintStatistics } }; -class SLAPrinter { +class SLAArchive { protected: std::vector m_layers; @@ -395,7 +395,7 @@ protected: virtual sla::RasterEncoder get_encoder() const = 0; public: - virtual ~SLAPrinter() = default; + virtual ~SLAArchive() = default; virtual void apply(const SLAPrinterConfig &cfg) = 0; @@ -526,7 +526,7 @@ public: // TODO: use this structure for the preview in the future. const std::vector& print_layers() const { return m_printer_input; } - void set_printer(SLAPrinter *archiver); + void set_printer(SLAArchive *archiver); private: @@ -548,7 +548,7 @@ private: std::vector m_printer_input; // The archive object which collects the raster images after slicing - SLAPrinter *m_printer = nullptr; + SLAArchive *m_printer = nullptr; // Estimated print time, material consumed. SLAPrintStatistics m_print_statistics; 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)