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