#include "SLAImportJob.hpp" #include "libslic3r/Format/SL1.hpp" #include "slic3r/GUI/GUI.hpp" #include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/GUI_ObjectList.hpp" #include "libslic3r/Model.hpp" #include "libslic3r/PresetBundle.hpp" #include #include #include #include #include namespace Slic3r { namespace GUI { enum class Sel { modelAndProfile, profileOnly, modelOnly}; class ImportDlg: public wxDialog { wxFilePickerCtrl *m_filepicker; wxComboBox *m_import_dropdown, *m_quality_dropdown; public: ImportDlg(Plater *plater) : wxDialog{plater, wxID_ANY, "Import SLA archive"} { auto szvert = new wxBoxSizer{wxVERTICAL}; auto szfilepck = new wxBoxSizer{wxHORIZONTAL}; m_filepicker = new wxFilePickerCtrl(this, wxID_ANY, from_u8(wxGetApp().app_config->get_last_dir()), _(L("Choose SLA archive:")), "SL1 / SL1S archive files (*.sl1, *.sl1s, *.zip)|*.sl1;*.SL1;*.sl1s;*.SL1S;*.zip;*.ZIP", wxDefaultPosition, wxDefaultSize, wxFLP_DEFAULT_STYLE | wxFD_OPEN | wxFD_FILE_MUST_EXIST); szfilepck->Add(new wxStaticText(this, wxID_ANY, _L("Import file") + ": "), 0, wxALIGN_CENTER); szfilepck->Add(m_filepicker, 1); szvert->Add(szfilepck, 0, wxALL | wxEXPAND, 5); auto szchoices = new wxBoxSizer{wxHORIZONTAL}; static const std::vector inp_choices = { _(L("Import model and profile")), _(L("Import profile only")), _(L("Import model only")) }; m_import_dropdown = new wxComboBox( this, wxID_ANY, inp_choices[0], wxDefaultPosition, wxDefaultSize, inp_choices.size(), inp_choices.data(), wxCB_READONLY | wxCB_DROPDOWN); szchoices->Add(m_import_dropdown); szchoices->Add(new wxStaticText(this, wxID_ANY, _L("Quality") + ": "), 0, wxALIGN_CENTER | wxALL, 5); static const std::vector qual_choices = { _(L("Accurate")), _(L("Balanced")), _(L("Quick")) }; m_quality_dropdown = new wxComboBox( this, wxID_ANY, qual_choices[0], wxDefaultPosition, wxDefaultSize, qual_choices.size(), qual_choices.data(), wxCB_READONLY | wxCB_DROPDOWN); szchoices->Add(m_quality_dropdown); m_import_dropdown->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent &) { if (get_selection() == Sel::profileOnly) m_quality_dropdown->Disable(); else m_quality_dropdown->Enable(); }); szvert->Add(szchoices, 0, wxALL, 5); szvert->AddStretchSpacer(1); auto szbtn = new wxBoxSizer(wxHORIZONTAL); szbtn->Add(new wxButton{this, wxID_CANCEL}); szbtn->Add(new wxButton{this, wxID_OK}); szvert->Add(szbtn, 0, wxALIGN_RIGHT | wxALL, 5); SetSizerAndFit(szvert); } Sel get_selection() const { int sel = m_import_dropdown->GetSelection(); return Sel(std::min(int(Sel::modelOnly), std::max(0, sel))); } Vec2i get_marchsq_windowsize() const { enum { Accurate, Balanced, Fast}; switch(m_quality_dropdown->GetSelection()) { case Fast: return {8, 8}; case Balanced: return {4, 4}; default: case Accurate: return {2, 2}; } } wxString get_path() const { return m_filepicker->GetPath(); } }; class SLAImportJob::priv { public: Plater *plater; Sel sel = Sel::modelAndProfile; TriangleMesh mesh; DynamicPrintConfig profile; wxString path; Vec2i win = {2, 2}; std::string err; ConfigSubstitutions config_substitutions; priv(Plater *plt): plater{plt} {} }; SLAImportJob::SLAImportJob(std::shared_ptr pri, Plater *plater) : Job{std::move(pri)}, p{std::make_unique(plater)} {} SLAImportJob::~SLAImportJob() = default; void SLAImportJob::process() { auto progr = [this](int s) { if (s < 100) update_status(int(s), _(L("Importing SLA archive"))); return !was_canceled(); }; if (p->path.empty()) return; std::string path = p->path.ToUTF8().data(); 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); break; case Sel::profileOnly: p->config_substitutions = import_sla_archive(path, p->profile); break; } } catch (std::exception &ex) { p->err = ex.what(); } update_status(100, was_canceled() ? _(L("Importing canceled.")) : _(L("Importing done."))); } void SLAImportJob::reset() { p->sel = Sel::modelAndProfile; p->mesh = {}; p->profile = {}; p->win = {2, 2}; p->path.Clear(); } void SLAImportJob::prepare() { reset(); ImportDlg dlg{p->plater}; if (dlg.ShowModal() == wxID_OK) { auto path = dlg.get_path(); auto nm = wxFileName(path); p->path = !nm.Exists(wxFILE_EXISTS_REGULAR) ? "" : path.ToUTF8(); p->sel = dlg.get_selection(); p->win = dlg.get_marchsq_windowsize(); p->config_substitutions.clear(); } else { p->path = ""; } } void SLAImportJob::finalize() { // Ignore the arrange result if aborted. if (was_canceled()) return; if (!p->err.empty()) { show_error(p->plater, p->err); p->err = ""; return; } std::string name = wxFileName(p->path).GetName().ToUTF8().data(); if (!p->profile.empty()) { const ModelObjectPtrs& objects = p->plater->model().objects; for (auto object : objects) if (object->volumes.size() > 1) { Slic3r::GUI::show_info(nullptr, _(L("You cannot load SLA project with a multi-part object on the bed")) + "\n\n" + _(L("Please check your object list before preset changing.")), _(L("Attention!")) ); return; } DynamicPrintConfig config = {}; config.apply(SLAFullPrintConfig::defaults()); config += std::move(p->profile); wxGetApp().preset_bundle->load_config_model(name, std::move(config)); wxGetApp().load_current_presets(); } if (!p->mesh.empty()) { bool is_centered = false; p->plater->sidebar().obj_list()->load_mesh_object(p->mesh, name, is_centered); } if (! p->config_substitutions.empty()) show_substitutions_info(p->config_substitutions, p->path.ToUTF8().data()); reset(); } }} // namespace Slic3r::GUI