1 #include "SLAImportJob.hpp"
2 
3 #include "libslic3r/Format/SL1.hpp"
4 
5 #include "slic3r/GUI/GUI.hpp"
6 #include "slic3r/GUI/GUI_App.hpp"
7 #include "slic3r/GUI/Plater.hpp"
8 #include "slic3r/GUI/GUI_ObjectList.hpp"
9 
10 #include "libslic3r/Model.hpp"
11 #include "libslic3r/PresetBundle.hpp"
12 
13 #include <wx/dialog.h>
14 #include <wx/stattext.h>
15 #include <wx/combobox.h>
16 #include <wx/filename.h>
17 #include <wx/filepicker.h>
18 
19 namespace Slic3r { namespace GUI {
20 
21 enum class Sel { modelAndProfile, profileOnly, modelOnly};
22 
23 class ImportDlg: public wxDialog {
24     wxFilePickerCtrl *m_filepicker;
25     wxComboBox *m_import_dropdown, *m_quality_dropdown;
26 
27 public:
ImportDlg(Plater * plater)28     ImportDlg(Plater *plater)
29         : wxDialog{plater, wxID_ANY, "Import SLA archive"}
30     {
31         auto szvert = new wxBoxSizer{wxVERTICAL};
32         auto szfilepck = new wxBoxSizer{wxHORIZONTAL};
33 
34         m_filepicker = new wxFilePickerCtrl(this, wxID_ANY,
35                                             from_u8(wxGetApp().app_config->get_last_dir()), _(L("Choose SLA archive:")),
36                                             "SL1 / SL1S archive files (*.sl1, *.sl1s, *.zip)|*.sl1;*.SL1;*.sl1s;*.SL1S;*.zip;*.ZIP",
37                                             wxDefaultPosition, wxDefaultSize, wxFLP_DEFAULT_STYLE | wxFD_OPEN | wxFD_FILE_MUST_EXIST);
38 
39         szfilepck->Add(new wxStaticText(this, wxID_ANY, _L("Import file") + ": "), 0, wxALIGN_CENTER);
40         szfilepck->Add(m_filepicker, 1);
41         szvert->Add(szfilepck, 0, wxALL | wxEXPAND, 5);
42 
43         auto szchoices = new wxBoxSizer{wxHORIZONTAL};
44 
45         static const std::vector<wxString> inp_choices = {
46             _(L("Import model and profile")),
47             _(L("Import profile only")),
48             _(L("Import model only"))
49         };
50 
51         m_import_dropdown = new wxComboBox(
52             this, wxID_ANY, inp_choices[0], wxDefaultPosition, wxDefaultSize,
53             inp_choices.size(), inp_choices.data(), wxCB_READONLY | wxCB_DROPDOWN);
54 
55         szchoices->Add(m_import_dropdown);
56         szchoices->Add(new wxStaticText(this, wxID_ANY, _L("Quality") + ": "), 0, wxALIGN_CENTER | wxALL, 5);
57 
58         static const std::vector<wxString> qual_choices = {
59             _(L("Accurate")),
60             _(L("Balanced")),
61             _(L("Quick"))
62         };
63 
64         m_quality_dropdown = new wxComboBox(
65             this, wxID_ANY, qual_choices[0], wxDefaultPosition, wxDefaultSize,
66             qual_choices.size(), qual_choices.data(), wxCB_READONLY | wxCB_DROPDOWN);
67         szchoices->Add(m_quality_dropdown);
68 
__anond4a0ffad0102(wxCommandEvent &) 69         m_import_dropdown->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent &) {
70             if (get_selection() == Sel::profileOnly)
71                 m_quality_dropdown->Disable();
72             else m_quality_dropdown->Enable();
73         });
74 
75         szvert->Add(szchoices, 0, wxALL, 5);
76         szvert->AddStretchSpacer(1);
77         auto szbtn = new wxBoxSizer(wxHORIZONTAL);
78         szbtn->Add(new wxButton{this, wxID_CANCEL});
79         szbtn->Add(new wxButton{this, wxID_OK});
80         szvert->Add(szbtn, 0, wxALIGN_RIGHT | wxALL, 5);
81 
82         SetSizerAndFit(szvert);
83     }
84 
get_selection() const85     Sel get_selection() const
86     {
87         int sel = m_import_dropdown->GetSelection();
88         return Sel(std::min(int(Sel::modelOnly), std::max(0, sel)));
89     }
90 
get_marchsq_windowsize() const91     Vec2i get_marchsq_windowsize() const
92     {
93         enum { Accurate, Balanced, Fast};
94 
95         switch(m_quality_dropdown->GetSelection())
96         {
97         case Fast: return {8, 8};
98         case Balanced: return {4, 4};
99         default:
100         case Accurate:
101             return {2, 2};
102         }
103     }
104 
get_path() const105     wxString get_path() const
106     {
107         return m_filepicker->GetPath();
108     }
109 };
110 
111 class SLAImportJob::priv {
112 public:
113     Plater *plater;
114 
115     Sel sel = Sel::modelAndProfile;
116 
117     TriangleMesh        mesh;
118     DynamicPrintConfig  profile;
119     wxString            path;
120     Vec2i               win = {2, 2};
121     std::string         err;
122     ConfigSubstitutions config_substitutions;
123 
priv(Plater * plt)124     priv(Plater *plt): plater{plt} {}
125 };
126 
SLAImportJob(std::shared_ptr<ProgressIndicator> pri,Plater * plater)127 SLAImportJob::SLAImportJob(std::shared_ptr<ProgressIndicator> pri, Plater *plater)
128     : Job{std::move(pri)}, p{std::make_unique<priv>(plater)}
129 {}
130 
131 SLAImportJob::~SLAImportJob() = default;
132 
process()133 void SLAImportJob::process()
134 {
135     auto progr = [this](int s) {
136         if (s < 100) update_status(int(s), _(L("Importing SLA archive")));
137         return !was_canceled();
138     };
139 
140     if (p->path.empty()) return;
141 
142     std::string path = p->path.ToUTF8().data();
143     try {
144         switch (p->sel) {
145         case Sel::modelAndProfile:
146             p->config_substitutions = import_sla_archive(path, p->win, p->mesh, p->profile, progr);
147             break;
148         case Sel::modelOnly:
149             p->config_substitutions = import_sla_archive(path, p->win, p->mesh, progr);
150             break;
151         case Sel::profileOnly:
152             p->config_substitutions = import_sla_archive(path, p->profile);
153             break;
154         }
155 
156     } catch (std::exception &ex) {
157         p->err = ex.what();
158     }
159 
160     update_status(100, was_canceled() ? _(L("Importing canceled.")) :
161                                         _(L("Importing done.")));
162 }
163 
reset()164 void SLAImportJob::reset()
165 {
166     p->sel     = Sel::modelAndProfile;
167     p->mesh    = {};
168     p->profile = {};
169     p->win     = {2, 2};
170     p->path.Clear();
171 }
172 
prepare()173 void SLAImportJob::prepare()
174 {
175     reset();
176 
177     ImportDlg dlg{p->plater};
178 
179     if (dlg.ShowModal() == wxID_OK) {
180         auto path = dlg.get_path();
181         auto nm = wxFileName(path);
182         p->path = !nm.Exists(wxFILE_EXISTS_REGULAR) ? "" : path.ToUTF8();
183         p->sel  = dlg.get_selection();
184         p->win  = dlg.get_marchsq_windowsize();
185         p->config_substitutions.clear();
186     } else {
187         p->path = "";
188     }
189 }
190 
finalize()191 void SLAImportJob::finalize()
192 {
193     // Ignore the arrange result if aborted.
194     if (was_canceled()) return;
195 
196     if (!p->err.empty()) {
197         show_error(p->plater, p->err);
198         p->err = "";
199         return;
200     }
201 
202     std::string name = wxFileName(p->path).GetName().ToUTF8().data();
203 
204     if (!p->profile.empty()) {
205         const ModelObjectPtrs& objects = p->plater->model().objects;
206         for (auto object : objects)
207             if (object->volumes.size() > 1)
208             {
209                 Slic3r::GUI::show_info(nullptr,
210                                        _(L("You cannot load SLA project with a multi-part object on the bed")) + "\n\n" +
211                                        _(L("Please check your object list before preset changing.")),
212                                        _(L("Attention!")) );
213                 return;
214             }
215 
216         DynamicPrintConfig config = {};
217         config.apply(SLAFullPrintConfig::defaults());
218         config += std::move(p->profile);
219 
220         wxGetApp().preset_bundle->load_config_model(name, std::move(config));
221         wxGetApp().load_current_presets();
222     }
223 
224     if (!p->mesh.empty()) {
225         bool is_centered = false;
226         p->plater->sidebar().obj_list()->load_mesh_object(p->mesh, name, is_centered);
227     }
228 
229     if (! p->config_substitutions.empty())
230         show_substitutions_info(p->config_substitutions, p->path.ToUTF8().data());
231 
232     reset();
233 }
234 
235 }} // namespace Slic3r::GUI
236