Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
Slic3r::CLI Class Reference

#include <src/PrusaSlicer.hpp>

+ Collaboration diagram for Slic3r::CLI:

Public Member Functions

int run (int argc, char **argv)
 

Private Member Functions

bool setup (int argc, char **argv)
 
void print_help (bool include_print_options=false, PrinterTechnology printer_technology=ptAny) const
 Prints usage of the CLI.
 
bool export_models (IO::ExportFormat format)
 Exports loaded models to a file of the specified format, according to the options affecting output filename.
 
bool has_print_action () const
 
std::string output_filepath (const Model &model, IO::ExportFormat format) const
 

Private Attributes

DynamicPrintAndCLIConfig m_config
 
DynamicPrintConfig m_print_config
 
DynamicPrintConfig m_extra_config
 
std::vector< std::string > m_input_files
 
std::vector< std::string > m_actions
 
std::vector< std::string > m_transforms
 
std::vector< Modelm_models
 

Detailed Description

Member Function Documentation

◆ export_models()

bool CLI::export_models ( IO::ExportFormat  format)
private

Exports loaded models to a file of the specified format, according to the options affecting output filename.

851{
852 for (Model &model : m_models) {
853 const std::string path = this->output_filepath(model, format);
854 bool success = false;
855 switch (format) {
856 case IO::AMF: success = Slic3r::store_amf(path.c_str(), &model, nullptr, false); break;
857 case IO::OBJ: success = Slic3r::store_obj(path.c_str(), &model); break;
858 case IO::STL: success = Slic3r::store_stl(path.c_str(), &model, true); break;
859 case IO::TMF: success = Slic3r::store_3mf(path.c_str(), &model, nullptr, false); break;
860 default: assert(false); break;
861 }
862 if (success)
863 std::cout << "File exported to " << path << std::endl;
864 else {
865 std::cerr << "File export to " << path << " failed" << std::endl;
866 return false;
867 }
868 }
869 return true;
870}
std::vector< Model > m_models
Definition PrusaSlicer.hpp:31
std::string output_filepath(const Model &model, IO::ExportFormat format) const
Definition PrusaSlicer.cpp:872
Definition Model.hpp:1248
@ TMF
Definition PrusaSlicer.hpp:15
@ OBJ
Definition PrusaSlicer.hpp:12
@ STL
Definition PrusaSlicer.hpp:13
@ AMF
Definition PrusaSlicer.hpp:11
bool store_3mf(const char *path, Model *model, const DynamicPrintConfig *config, bool fullpath_sources, const ThumbnailData *thumbnail_data, bool zip64)
Definition 3mf.cpp:3476
bool store_stl(const char *path, TriangleMesh *mesh, bool binary)
Definition STL.cpp:40
bool store_obj(const char *path, TriangleMesh *mesh)
Definition OBJ.cpp:121
std::string format(const char *fmt, TArgs &&... args)
Definition format.hpp:44
bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config, bool fullpath_sources)
Definition AMF.cpp:1095

References Slic3r::IO::AMF, Slic3r::format(), m_models, Slic3r::IO::OBJ, output_filepath(), Slic3r::IO::STL, Slic3r::store_3mf(), Slic3r::store_amf(), Slic3r::store_obj(), Slic3r::store_stl(), and Slic3r::IO::TMF.

Referenced by run().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ has_print_action()

bool Slic3r::CLI::has_print_action ( ) const
inlineprivate
41{ return m_config.opt_bool("export_gcode") || m_config.opt_bool("export_sla"); }
DynamicPrintAndCLIConfig m_config
Definition PrusaSlicer.hpp:25
bool opt_bool(const t_config_option_key &opt_key) const
Definition Config.hpp:2296

References m_config, and Slic3r::ConfigBase::opt_bool().

Referenced by run().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ output_filepath()

std::string CLI::output_filepath ( const Model model,
IO::ExportFormat  format 
) const
private
873{
874 std::string ext;
875 switch (format) {
876 case IO::AMF: ext = ".zip.amf"; break;
877 case IO::OBJ: ext = ".obj"; break;
878 case IO::STL: ext = ".stl"; break;
879 case IO::TMF: ext = ".3mf"; break;
880 default: assert(false); break;
881 };
882 auto proposed_path = boost::filesystem::path(model.propose_export_file_name_and_path(ext));
883 // use --output when available
884 std::string cmdline_param = m_config.opt_string("output");
885 if (! cmdline_param.empty()) {
886 // if we were supplied a directory, use it and append our automatically generated filename
887 boost::filesystem::path cmdline_path(cmdline_param);
888 if (boost::filesystem::is_directory(cmdline_path))
889 proposed_path = cmdline_path / proposed_path.filename();
890 else
891 proposed_path = cmdline_path;
892 }
893 return proposed_path.string();
894}
std::string & opt_string(const t_config_option_key &opt_key, bool create=false)
Definition Config.hpp:2276
std::string propose_export_file_name_and_path() const
Definition Model.cpp:585

References Slic3r::IO::AMF, Slic3r::format(), m_config, Slic3r::IO::OBJ, Slic3r::ConfigBase::opt_string(), Slic3r::Model::propose_export_file_name_and_path(), Slic3r::IO::STL, and Slic3r::IO::TMF.

Referenced by export_models().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ print_help()

void CLI::print_help ( bool  include_print_options = false,
PrinterTechnology  printer_technology = ptAny 
) const
private

Prints usage of the CLI.

806{
807 boost::nowide::cout
808 << SLIC3R_BUILD_ID << " " << "based on Slic3r"
809#ifdef SLIC3R_GUI
810 << " (with GUI support)"
811#else /* SLIC3R_GUI */
812 << " (without GUI support)"
813#endif /* SLIC3R_GUI */
814 << std::endl
815 << "https://github.com/prusa3d/PrusaSlicer" << std::endl << std::endl
816 << "Usage: prusa-slicer [ ACTIONS ] [ TRANSFORM ] [ OPTIONS ] [ file.stl ... ]" << std::endl
817 << std::endl
818 << "Actions:" << std::endl;
819 cli_actions_config_def.print_cli_help(boost::nowide::cout, false);
820
821 boost::nowide::cout
822 << std::endl
823 << "Transform options:" << std::endl;
824 cli_transform_config_def.print_cli_help(boost::nowide::cout, false);
825
826 boost::nowide::cout
827 << std::endl
828 << "Other options:" << std::endl;
829 cli_misc_config_def.print_cli_help(boost::nowide::cout, false);
830
831 boost::nowide::cout
832 << std::endl
833 << "Print options are processed in the following order:" << std::endl
834 << "\t1) Config keys from the command line, for example --fill-pattern=stars" << std::endl
835 << "\t (highest priority, overwrites everything below)" << std::endl
836 << "\t2) Config files loaded with --load" << std::endl
837 << "\t3) Config values loaded from amf or 3mf files" << std::endl;
838
839 if (include_print_options) {
840 boost::nowide::cout << std::endl;
841 print_config_def.print_cli_help(boost::nowide::cout, true, [printer_technology](const ConfigOptionDef &def)
843 } else {
844 boost::nowide::cout
845 << std::endl
846 << "Run --help-fff / --help-sla to see the full listing of print options." << std::endl;
847 }
848}
std::ostream & print_cli_help(std::ostream &out, bool show_defaults, std::function< bool(const ConfigOptionDef &)> filter=[](const ConfigOptionDef &){ return true;}) const
Definition Config.cpp:331
Definition Config.hpp:1797
PrinterTechnology printer_technology
Definition Config.hpp:1917
@ ptAny
Definition Config.hpp:213
const CLIActionsConfigDef cli_actions_config_def
Definition PrintConfig.cpp:4911
printer_technology((ConfigOptionPoints, bed_shape))((ConfigOptionFloat
const PrintConfigDef print_config_def
Definition PrintConfig.cpp:4288
const CLITransformConfigDef cli_transform_config_def
Definition PrintConfig.cpp:4912
const CLIMiscConfigDef cli_misc_config_def
Definition PrintConfig.cpp:4913

References Slic3r::cli_actions_config_def, Slic3r::cli_misc_config_def, Slic3r::cli_transform_config_def, Slic3r::ConfigDef::print_cli_help(), Slic3r::print_config_def, Slic3r::ConfigOptionDef::printer_technology, Slic3r::printer_technology(), and Slic3r::ptAny.

Referenced by run(), and setup().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ run()

int CLI::run ( int  argc,
char **  argv 
)
72{
73 // Mark the main thread for the debugger and for runtime checks.
74 set_current_thread_name("slic3r_main");
75 // Save the thread ID of the main thread.
77
78#ifdef __WXGTK__
79 // On Linux, wxGTK has no support for Wayland, and the app crashes on
80 // startup if gtk3 is used. This env var has to be set explicitly to
81 // instruct the window manager to fall back to X server mode.
82 ::setenv("GDK_BACKEND", "x11", /* replace */ true);
83#endif
84
85 // Switch boost::filesystem to utf8.
86 try {
88 } catch (const std::runtime_error& ex) {
89 std::string caption = std::string(SLIC3R_APP_NAME) + " Error";
90 std::string text = std::string("An error occured while setting up locale.\n") + (
91#if !defined(_WIN32) && !defined(__APPLE__)
92 // likely some linux system
93 "You may need to reconfigure the missing locales, likely by running the \"locale-gen\" and \"dpkg-reconfigure locales\" commands.\n"
94#endif
95 SLIC3R_APP_NAME " will now terminate.\n\n") + ex.what();
96 #if defined(_WIN32) && defined(SLIC3R_GUI)
97 if (m_actions.empty())
98 // Empty actions means Slicer is executed in the GUI mode. Show a GUI message.
99 MessageBoxA(NULL, text.c_str(), caption.c_str(), MB_OK | MB_ICONERROR);
100 #endif
101 boost::nowide::cerr << text.c_str() << std::endl;
102 return 1;
103 }
104
105 if (! this->setup(argc, argv))
106 return 1;
107
110
112
113 bool start_gui = m_actions.empty() &&
114 // cutting transformations are setting an "export" action.
115 std::find(m_transforms.begin(), m_transforms.end(), "cut") == m_transforms.end() &&
116 std::find(m_transforms.begin(), m_transforms.end(), "cut_x") == m_transforms.end() &&
117 std::find(m_transforms.begin(), m_transforms.end(), "cut_y") == m_transforms.end();
118 bool start_downloader = false;
119 bool delete_after_load = false;
120 std::string download_url;
121 bool start_as_gcodeviewer =
122#ifdef _WIN32
123 false;
124#else
125 // On Unix systems, the prusa-slicer binary may be symlinked to give the application a different meaning.
126 boost::algorithm::iends_with(boost::filesystem::path(argv[0]).filename().string(), "gcodeviewer");
127#endif // _WIN32
128#if ENABLE_GL_CORE_PROFILE
129 std::pair<int, int> opengl_version = { 0, 0 };
130#if ENABLE_OPENGL_DEBUG_OPTION
131 bool opengl_debug = false;
132#endif // ENABLE_OPENGL_DEBUG_OPTION
133#endif // ENABLE_GL_CORE_PROFILE
134
135 const std::vector<std::string> &load_configs = m_config.option<ConfigOptionStrings>("load", true)->values;
136 const ForwardCompatibilitySubstitutionRule config_substitution_rule = m_config.option<ConfigOptionEnum<ForwardCompatibilitySubstitutionRule>>("config_compatibility", true)->value;
137
138 // load config files supplied via --load
139 for (auto const &file : load_configs) {
140 if (! boost::filesystem::exists(file)) {
141 if (m_config.opt_bool("ignore_nonexistent_config")) {
142 continue;
143 } else {
144 boost::nowide::cerr << "No such file: " << file << std::endl;
145 return 1;
146 }
147 }
148 DynamicPrintConfig config;
149 ConfigSubstitutions config_substitutions;
150 try {
151 config_substitutions = config.load(file, config_substitution_rule);
152 } catch (std::exception &ex) {
153 boost::nowide::cerr << "Error while reading config file \"" << file << "\": " << ex.what() << std::endl;
154 return 1;
155 }
156 if (! config_substitutions.empty()) {
157 boost::nowide::cout << "The following configuration values were substituted when loading \" << file << \":\n";
158 for (const ConfigSubstitution &subst : config_substitutions)
159 boost::nowide::cout << "\tkey = \"" << subst.opt_def->opt_key << "\"\t loaded = \"" << subst.old_value << "\tsubstituted = \"" << subst.new_value->serialize() << "\"\n";
160 }
161 config.normalize_fdm();
162 PrinterTechnology other_printer_technology = get_printer_technology(config);
164 printer_technology = other_printer_technology;
165 } else if (printer_technology != other_printer_technology && other_printer_technology != ptUnknown) {
166 boost::nowide::cerr << "Mixing configurations for FFF and SLA technologies" << std::endl;
167 return 1;
168 }
169 m_print_config.apply(config);
170 }
171
172#if ENABLE_GL_CORE_PROFILE
173 // search for special keys into command line parameters
174 auto it = std::find(m_actions.begin(), m_actions.end(), "gcodeviewer");
175 if (it != m_actions.end()) {
176 start_gui = true;
177 start_as_gcodeviewer = true;
178 m_actions.erase(it);
179 }
180
181 it = std::find(m_actions.begin(), m_actions.end(), "opengl-version");
182 if (it != m_actions.end()) {
183 std::string opengl_version_str = m_config.opt_string("opengl-version");
186 boost::nowide::cerr << "Found invalid OpenGL version: " << opengl_version_str << std::endl;
187 opengl_version_str.clear();
188 }
189 }
190
191 if (!opengl_version_str.empty()) {
192 std::vector<std::string> tokens;
193 boost::split(tokens, opengl_version_str, boost::is_any_of("."), boost::token_compress_on);
194 opengl_version.first = std::stoi(tokens[0].c_str());
195 opengl_version.second = std::stoi(tokens[1].c_str());
196 }
197 start_gui = true;
198 m_actions.erase(it);
199 }
200
201 it = std::find(m_actions.begin(), m_actions.end(), "opengl-debug");
202 if (it != m_actions.end()) {
203 start_gui = true;
204#if ENABLE_OPENGL_DEBUG_OPTION
205 opengl_debug = true;
206#endif // ENABLE_OPENGL_DEBUG_OPTION
207 m_actions.erase(it);
208 }
209#else
210 // are we starting as gcodeviewer ?
211 for (auto it = m_actions.begin(); it != m_actions.end(); ++it) {
212 if (*it == "gcodeviewer") {
213 start_gui = true;
214 start_as_gcodeviewer = true;
215 m_actions.erase(it);
216 break;
217 }
218 }
219#endif // ENABLE_GL_CORE_PROFILE
220
221 // Read input file(s) if any.
222 for (const std::string& file : m_input_files)
223 if (is_gcode_file(file) && boost::filesystem::exists(file)) {
224 start_as_gcodeviewer = true;
225 break;
226 }
227 if (!start_as_gcodeviewer) {
228 for (const std::string& file : m_input_files) {
229 if (boost::starts_with(file, "prusaslicer://")) {
230 start_downloader = true;
231 download_url = file;
232 continue;
233 }
234 if (!boost::filesystem::exists(file)) {
235 boost::nowide::cerr << "No such file: " << file << std::endl;
236 exit(1);
237 }
238 Model model;
239 try {
240 // When loading an AMF or 3MF, config is imported as well, including the printer technology.
241 DynamicPrintConfig config;
242 ConfigSubstitutionContext config_substitutions(config_substitution_rule);
243 //FIXME should we check the version here? // | Model::LoadAttribute::CheckVersion ?
244 model = Model::read_from_file(file, &config, &config_substitutions, Model::LoadAttribute::AddDefaultInstances);
245 PrinterTechnology other_printer_technology = get_printer_technology(config);
247 printer_technology = other_printer_technology;
248 }
249 else if (printer_technology != other_printer_technology && other_printer_technology != ptUnknown) {
250 boost::nowide::cerr << "Mixing configurations for FFF and SLA technologies" << std::endl;
251 return 1;
252 }
253 if (! config_substitutions.substitutions.empty()) {
254 boost::nowide::cout << "The following configuration values were substituted when loading \" << file << \":\n";
255 for (const ConfigSubstitution& subst : config_substitutions.substitutions)
256 boost::nowide::cout << "\tkey = \"" << subst.opt_def->opt_key << "\"\t loaded = \"" << subst.old_value << "\tsubstituted = \"" << subst.new_value->serialize() << "\"\n";
257 }
258 // config is applied to m_print_config before the current m_config values.
259 config += std::move(m_print_config);
260 m_print_config = std::move(config);
261 }
262 catch (std::exception& e) {
263 boost::nowide::cerr << file << ": " << e.what() << std::endl;
264 return 1;
265 }
266 if (model.objects.empty()) {
267 boost::nowide::cerr << "Error: file is empty: " << file << std::endl;
268 continue;
269 }
270 m_models.push_back(model);
271 }
272 }
273
274 // Apply command line options to a more specific DynamicPrintConfig which provides normalize()
275 // (command line options override --load files)
277 // Normalizing after importing the 3MFs / AMFs
279
281 printer_technology = std::find(m_actions.begin(), m_actions.end(), "export_sla") == m_actions.end() ? ptFFF : ptSLA;
283
284 // Initialize full print configs for both the FFF and SLA technologies.
285 FullPrintConfig fff_print_config;
286 SLAFullPrintConfig sla_print_config;
287
288 // Synchronize the default parameters and the ones received on the command line.
289 if (printer_technology == ptFFF) {
290 fff_print_config.apply(m_print_config, true);
291 m_print_config.apply(fff_print_config, true);
292 } else {
293 assert(printer_technology == ptSLA);
294 sla_print_config.output_filename_format.value = "[input_filename_base].sl1";
295
296 // The default bed shape should reflect the default display parameters
297 // and not the fff defaults.
298 double w = sla_print_config.display_width.getFloat();
299 double h = sla_print_config.display_height.getFloat();
300 sla_print_config.bed_shape.values = { Vec2d(0, 0), Vec2d(w, 0), Vec2d(w, h), Vec2d(0, h) };
301
302 sla_print_config.apply(m_print_config, true);
303 m_print_config.apply(sla_print_config, true);
304 }
305
306 {
307 std::string validity = m_print_config.validate();
308 if (! validity.empty()) {
309 boost::nowide::cerr << "Error: The composite configation is not valid: " << validity << std::endl;
310 return 1;
311 }
312 }
313
314 // Loop through transform options.
315 bool user_center_specified = false;
317 ArrangeParams arrange_cfg;
319
320 for (auto const &opt_key : m_transforms) {
321 if (opt_key == "merge") {
322 Model m;
323 for (auto &model : m_models)
324 for (ModelObject *o : model.objects)
325 m.add_object(*o);
326 // Rearrange instances unless --dont-arrange is supplied
327 if (! m_config.opt_bool("dont_arrange")) {
329 if (this->has_print_action())
330 arrange_objects(m, bed, arrange_cfg);
331 else
332 arrange_objects(m, InfiniteBed{}, arrange_cfg);
333 }
334 m_models.clear();
335 m_models.emplace_back(std::move(m));
336 } else if (opt_key == "duplicate") {
337 for (auto &model : m_models) {
338 const bool all_objects_have_instances = std::none_of(
339 model.objects.begin(), model.objects.end(),
340 [](ModelObject* o){ return o->instances.empty(); }
341 );
342
343 int dups = m_config.opt_int("duplicate");
344 if (!all_objects_have_instances) model.add_default_instances();
345
346 try {
347 if (dups > 1) {
348 // if all input objects have defined position(s) apply duplication to the whole model
349 duplicate(model, size_t(dups), bed, arrange_cfg);
350 } else {
351 arrange_objects(model, bed, arrange_cfg);
352 }
353 } catch (std::exception &ex) {
354 boost::nowide::cerr << "error: " << ex.what() << std::endl;
355 return 1;
356 }
357 }
358 } else if (opt_key == "duplicate_grid") {
359 std::vector<int> &ints = m_config.option<ConfigOptionInts>("duplicate_grid")->values;
360 const int x = ints.size() > 0 ? ints.at(0) : 1;
361 const int y = ints.size() > 1 ? ints.at(1) : 1;
362 const double distance = fff_print_config.duplicate_distance.value;
363 for (auto &model : m_models)
364 model.duplicate_objects_grid(x, y, (distance > 0) ? distance : 6); // TODO: this is not the right place for setting a default
365 } else if (opt_key == "center") {
366 user_center_specified = true;
367 for (auto &model : m_models) {
368 model.add_default_instances();
369 // this affects instances:
371 // this affects volumes:
372 //FIXME Vojtech: Who knows why the complete model should be aligned with Z as a single rigid body?
373 //model.align_to_ground();
374 BoundingBoxf3 bbox;
375 for (ModelObject *model_object : model.objects)
376 // We are interested into the Z span only, therefore it is sufficient to measure the bounding box of the 1st instance only.
377 bbox.merge(model_object->instance_bounding_box(0, false));
378 for (ModelObject *model_object : model.objects)
379 for (ModelInstance *model_instance : model_object->instances)
380 model_instance->set_offset(Z, model_instance->get_offset(Z) - bbox.min.z());
381 }
382 } else if (opt_key == "align_xy") {
383 const Vec2d &p = m_config.option<ConfigOptionPoint>("align_xy")->value;
384 for (auto &model : m_models) {
386 // this affects volumes:
387 model.translate(-(bb.min.x() - p.x()), -(bb.min.y() - p.y()), -bb.min.z());
388 }
389 } else if (opt_key == "dont_arrange") {
390 // do nothing - this option alters other transform options
391 } else if (opt_key == "ensure_on_bed") {
392 // do nothing, the value is used later
393 } else if (opt_key == "rotate") {
394 for (auto &model : m_models)
395 for (auto &o : model.objects)
396 // this affects volumes:
397 o->rotate(Geometry::deg2rad(m_config.opt_float(opt_key)), Z);
398 } else if (opt_key == "rotate_x") {
399 for (auto &model : m_models)
400 for (auto &o : model.objects)
401 // this affects volumes:
402 o->rotate(Geometry::deg2rad(m_config.opt_float(opt_key)), X);
403 } else if (opt_key == "rotate_y") {
404 for (auto &model : m_models)
405 for (auto &o : model.objects)
406 // this affects volumes:
407 o->rotate(Geometry::deg2rad(m_config.opt_float(opt_key)), Y);
408 } else if (opt_key == "scale") {
409 for (auto &model : m_models)
410 for (auto &o : model.objects)
411 // this affects volumes:
412 o->scale(m_config.get_abs_value(opt_key, 1));
413 } else if (opt_key == "scale_to_fit") {
414 const Vec3d &opt = m_config.opt<ConfigOptionPoint3>(opt_key)->value;
415 if (opt.x() <= 0 || opt.y() <= 0 || opt.z() <= 0) {
416 boost::nowide::cerr << "--scale-to-fit requires a positive volume" << std::endl;
417 return 1;
418 }
419 for (auto &model : m_models)
420 for (auto &o : model.objects)
421 // this affects volumes:
422 o->scale_to_fit(opt);
423 } else if (opt_key == "cut" || opt_key == "cut_x" || opt_key == "cut_y") {
424 std::vector<Model> new_models;
425 for (auto &model : m_models) {
426 model.translate(0, 0, -model.bounding_box_exact().min.z()); // align to z = 0
427 size_t num_objects = model.objects.size();
428 for (size_t i = 0; i < num_objects; ++ i) {
429
430#if 0
431 if (opt_key == "cut_x") {
432 o->cut(X, m_config.opt_float("cut_x"), &out);
433 } else if (opt_key == "cut_y") {
434 o->cut(Y, m_config.opt_float("cut_y"), &out);
435 } else if (opt_key == "cut") {
436 o->cut(Z, m_config.opt_float("cut"), &out);
437 }
438#else
439// model.objects.front()->cut(0, m_config.opt_float("cut"), ModelObjectCutAttribute::KeepLower | ModelObjectCutAttribute::KeepUpper | ModelObjectCutAttribute::FlipLower);
440 model.objects.front()->cut(0, Geometry::translation_transform(m_config.opt_float("cut") * Vec3d::UnitZ()),
442#endif
443 model.delete_object(size_t(0));
444 }
445 }
446
447 // TODO: copy less stuff around using pointers
448 m_models = new_models;
449
450 if (m_actions.empty())
451 m_actions.push_back("export_stl");
452 }
453#if 0
454 else if (opt_key == "cut_grid") {
455 std::vector<Model> new_models;
456 for (auto &model : m_models) {
457 TriangleMesh mesh = model.mesh();
458 mesh.repair();
459
460 std::vector<TriangleMesh> meshes = mesh.cut_by_grid(m_config.option<ConfigOptionPoint>("cut_grid")->value);
461 size_t i = 0;
462 for (TriangleMesh* m : meshes) {
463 Model out;
464 auto o = out.add_object();
465 o->add_volume(*m);
466 o->input_file += "_" + std::to_string(i++);
467 delete m;
468 }
469 }
470
471 // TODO: copy less stuff around using pointers
472 m_models = new_models;
473
474 if (m_actions.empty())
475 m_actions.push_back("export_stl");
476 }
477#endif
478 else if (opt_key == "split") {
479 for (Model &model : m_models) {
480 size_t num_objects = model.objects.size();
481 for (size_t i = 0; i < num_objects; ++ i) {
482 ModelObjectPtrs new_objects;
483 model.objects.front()->split(&new_objects);
484 model.delete_object(size_t(0));
485 }
486 }
487 } else if (opt_key == "repair") {
488 // Models are repaired by default.
489 //for (auto &model : m_models)
490 // model.repair();
491
492 } else if (opt_key == "delete-after-load") {
493 delete_after_load = true;
494 } else {
495 boost::nowide::cerr << "error: option not implemented yet: " << opt_key << std::endl;
496 return 1;
497 }
498 }
499
500 // All transforms have been dealt with. Now ensure that the objects are on bed.
501 // (Unless the user said otherwise.)
502 if (m_config.opt_bool("ensure_on_bed"))
503 for (auto &model : m_models)
504 for (auto &o : model.objects)
505 o->ensure_on_bed();
506
507 // loop through action options
508 for (auto const &opt_key : m_actions) {
509 if (opt_key == "help") {
510 this->print_help();
511 } else if (opt_key == "help_fff") {
512 this->print_help(true, ptFFF);
513 } else if (opt_key == "help_sla") {
514 this->print_help(true, ptSLA);
515 } else if (opt_key == "save") {
516 //FIXME check for mixing the FFF / SLA parameters.
517 // or better save fff_print_config vs. sla_print_config
519 } else if (opt_key == "info") {
520 // --info works on unrepaired model
521 for (Model &model : m_models) {
522 model.add_default_instances();
523 model.print_info();
524 }
525 } else if (opt_key == "export_stl") {
526 for (auto &model : m_models)
527 model.add_default_instances();
528 if (! this->export_models(IO::STL))
529 return 1;
530 } else if (opt_key == "export_obj") {
531 for (auto &model : m_models)
532 model.add_default_instances();
533 if (! this->export_models(IO::OBJ))
534 return 1;
535 } else if (opt_key == "export_amf") {
536 if (! this->export_models(IO::AMF))
537 return 1;
538 } else if (opt_key == "export_3mf") {
539 if (! this->export_models(IO::TMF))
540 return 1;
541 } else if (opt_key == "export_gcode" || opt_key == "export_sla" || opt_key == "slice") {
542 if (opt_key == "export_gcode" && printer_technology == ptSLA) {
543 boost::nowide::cerr << "error: cannot export G-code for an FFF configuration" << std::endl;
544 return 1;
545 } else if (opt_key == "export_sla" && printer_technology == ptFFF) {
546 boost::nowide::cerr << "error: cannot export SLA slices for a SLA configuration" << std::endl;
547 return 1;
548 }
549 // Make a copy of the model if the current action is not the last action, as the model may be
550 // modified by the centering and such.
551 Model model_copy;
552 bool make_copy = &opt_key != &m_actions.back();
553 for (Model &model_in : m_models) {
554 if (make_copy)
555 model_copy = model_in;
556 Model &model = make_copy ? model_copy : model_in;
557 // If all objects have defined instances, their relative positions will be
558 // honored when printing (they will be only centered, unless --dont-arrange
559 // is supplied); if any object has no instances, it will get a default one
560 // and all instances will be rearranged (unless --dont-arrange is supplied).
561 std::string outfile = m_config.opt_string("output");
562 Print fff_print;
563 SLAPrint sla_print;
564 sla_print.set_status_callback(
565 [](const PrintBase::SlicingStatus& s)
566 {
567 if(s.percent >= 0) // FIXME: is this sufficient?
568 printf("%3d%s %s\n", s.percent, "% =>", s.text.c_str());
569 });
570
571 PrintBase *print = (printer_technology == ptFFF) ? static_cast<PrintBase*>(&fff_print) : static_cast<PrintBase*>(&sla_print);
572 if (! m_config.opt_bool("dont_arrange")) {
573 if (user_center_specified) {
574 Vec2d c = m_config.option<ConfigOptionPoint>("center")->value;
575 arrange_objects(model, InfiniteBed{scaled(c)}, arrange_cfg);
576 } else
577 arrange_objects(model, bed, arrange_cfg);
578 }
579 if (printer_technology == ptFFF) {
580 for (auto* mo : model.objects)
581 fff_print.auto_assign_extruders(mo);
582 }
583 print->apply(model, m_print_config);
584 std::string err = print->validate();
585 if (! err.empty()) {
586 boost::nowide::cerr << err << std::endl;
587 return 1;
588 }
589 if (print->empty())
590 boost::nowide::cout << "Nothing to print for " << outfile << " . Either the print is empty or no object is fully inside the print volume." << std::endl;
591 else
592 try {
593 std::string outfile_final;
594 print->process();
595 if (printer_technology == ptFFF) {
596 // The outfile is processed by a PlaceholderParser.
597 outfile = fff_print.export_gcode(outfile, nullptr, nullptr);
598 outfile_final = fff_print.print_statistics().finalize_output_path(outfile);
599 } else {
600 outfile = sla_print.output_filepath(outfile);
601 // We need to finalize the filename beforehand because the export function sets the filename inside the zip metadata
602 outfile_final = sla_print.print_statistics().finalize_output_path(outfile);
603 sla_print.export_print(outfile_final);
604 }
605 if (outfile != outfile_final) {
606 if (Slic3r::rename_file(outfile, outfile_final)) {
607 boost::nowide::cerr << "Renaming file " << outfile << " to " << outfile_final << " failed" << std::endl;
608 return 1;
609 }
610 outfile = outfile_final;
611 }
612 // Run the post-processing scripts if defined.
613 run_post_process_scripts(outfile, fff_print.full_print_config());
614 boost::nowide::cout << "Slicing result exported to " << outfile << std::endl;
615 } catch (const std::exception &ex) {
616 boost::nowide::cerr << ex.what() << std::endl;
617 return 1;
618 }
619/*
620 print.center = ! m_config.has("center")
621 && ! m_config.has("align_xy")
622 && ! m_config.opt_bool("dont_arrange");
623 print.set_model(model);
624
625 // start chronometer
626 typedef std::chrono::high_resolution_clock clock_;
627 typedef std::chrono::duration<double, std::ratio<1> > second_;
628 std::chrono::time_point<clock_> t0{ clock_::now() };
629
630 const std::string outfile = this->output_filepath(model, IO::Gcode);
631 try {
632 print.export_gcode(outfile);
633 } catch (std::runtime_error &e) {
634 boost::nowide::cerr << e.what() << std::endl;
635 return 1;
636 }
637 boost::nowide::cout << "G-code exported to " << outfile << std::endl;
638
639 // output some statistics
640 double duration { std::chrono::duration_cast<second_>(clock_::now() - t0).count() };
641 boost::nowide::cout << std::fixed << std::setprecision(0)
642 << "Done. Process took " << (duration/60) << " minutes and "
643 << std::setprecision(3)
644 << std::fmod(duration, 60.0) << " seconds." << std::endl
645 << std::setprecision(2)
646 << "Filament required: " << print.total_used_filament() << "mm"
647 << " (" << print.total_extruded_volume()/1000 << "cm3)" << std::endl;
648*/
649 }
650 } else {
651 boost::nowide::cerr << "error: option not supported yet: " << opt_key << std::endl;
652 return 1;
653 }
654 }
655
656
657 if (start_gui) {
658#ifdef SLIC3R_GUI
659 #if !defined(_WIN32) && !defined(__APPLE__)
660 // likely some linux / unix system
661 const char *display = boost::nowide::getenv("DISPLAY");
662 // const char *wayland_display = boost::nowide::getenv("WAYLAND_DISPLAY");
663 //if (! ((display && *display) || (wayland_display && *wayland_display))) {
664 if (! (display && *display)) {
665 // DISPLAY not set.
666 boost::nowide::cerr << "DISPLAY not set, GUI mode not available." << std::endl << std::endl;
667 this->print_help(false);
668 // Indicate an error.
669 return 1;
670 }
671 #endif // some linux / unix system
673 params.argc = argc;
674 params.argv = argv;
675 params.load_configs = load_configs;
676 params.extra_config = std::move(m_extra_config);
677 params.input_files = std::move(m_input_files);
678 params.start_as_gcodeviewer = start_as_gcodeviewer;
679 params.start_downloader = start_downloader;
680 params.download_url = download_url;
681 params.delete_after_load = delete_after_load;
682#if ENABLE_GL_CORE_PROFILE
683#if ENABLE_OPENGL_DEBUG_OPTION
684 params.opengl_version = opengl_version;
685 params.opengl_debug = opengl_debug;
686#endif // ENABLE_OPENGL_DEBUG_OPTION
687#endif // ENABLE_GL_CORE_PROFILE
688 return Slic3r::GUI::GUI_Run(params);
689#else // SLIC3R_GUI
690 // No GUI support. Just print out a help.
691 this->print_help(false);
692 // If started without a parameter, consider it to be OK, otherwise report an error code (no action etc).
693 return (argc == 0) ? 0 : 1;
694#endif // SLIC3R_GUI
695 }
696
697 return 0;
698}
void serialize(Archive &ar, FacenamesSerializer &t, const std::uint32_t version)
Definition GLGizmoEmboss.cpp:1562
static PrinterTechnology get_printer_technology(const DynamicConfig &config)
Definition PrusaSlicer.cpp:65
int scale(const int val)
Definition WipeTowerDialog.cpp:14
PointType min
Definition BoundingBox.hpp:16
Definition BoundingBox.hpp:221
std::vector< std::string > m_input_files
Definition PrusaSlicer.hpp:28
bool has_print_action() const
Definition PrusaSlicer.hpp:41
DynamicPrintConfig m_extra_config
Definition PrusaSlicer.hpp:27
std::vector< std::string > m_actions
Definition PrusaSlicer.hpp:29
bool export_models(IO::ExportFormat format)
Exports loaded models to a file of the specified format, according to the options affecting output fi...
Definition PrusaSlicer.cpp:850
bool setup(int argc, char **argv)
Definition PrusaSlicer.cpp:700
void print_help(bool include_print_options=false, PrinterTechnology printer_technology=ptAny) const
Prints usage of the CLI.
Definition PrusaSlicer.cpp:805
DynamicPrintConfig m_print_config
Definition PrusaSlicer.hpp:26
std::vector< std::string > m_transforms
Definition PrusaSlicer.hpp:30
ConfigSubstitutions load(const std::string &file, ForwardCompatibilitySubstitutionRule compatibility_rule)
Definition Config.cpp:723
void apply(const ConfigBase &other, bool ignore_nonexistent=false)
Definition Config.hpp:2209
void save(const std::string &file) const
Definition Config.cpp:1030
double & opt_float(const t_config_option_key &opt_key)
Definition Config.hpp:2281
ConfigOption * option(const t_config_option_key &opt_key, bool create=false)
Definition Config.hpp:2169
int & opt_int(const t_config_option_key &opt_key)
Definition Config.hpp:2286
T * opt(const t_config_option_key &opt_key, bool create=false)
Definition Config.hpp:2196
Definition Config.hpp:1501
Definition Config.hpp:761
Definition Config.hpp:1311
Definition Config.hpp:1200
T value
Definition Config.hpp:305
Definition Config.hpp:879
Definition PrintConfig.hpp:212
std::string validate()
Definition PrintConfig.cpp:4427
void normalize_fdm()
Definition PrintConfig.cpp:4332
void delete_object(size_t idx)
Definition Model.cpp:233
static Model read_from_file(const std::string &input_file, DynamicPrintConfig *config=nullptr, ConfigSubstitutionContext *config_substitutions=nullptr, LoadAttributes options=LoadAttribute::AddDefaultInstances)
Definition Model.cpp:104
void print_info() const
Definition Model.hpp:1337
ModelObjectPtrs objects
Definition Model.hpp:1254
void translate(coordf_t x, coordf_t y, coordf_t z)
Definition Model.hpp:1320
ModelObject * add_object()
Definition Model.cpp:189
bool add_default_instances()
Definition Model.cpp:318
bool center_instances_around_point(const Vec2d &point)
Definition Model.cpp:360
BoundingBoxf3 bounding_box_exact() const
Definition Model.cpp:336
TriangleMesh mesh() const
Definition Model.cpp:382
Definition Model.hpp:1120
Definition Model.hpp:328
ModelVolume * add_volume(const TriangleMesh &mesh)
Definition Model.cpp:717
Printing involves slicing and export of device dependent instructions.
Definition PrintBase.hpp:405
virtual bool empty() const =0
virtual void process()=0
virtual ApplyStatus apply(const Model &model, DynamicPrintConfig config)=0
virtual std::string validate(std::vector< std::string > *warnings=nullptr) const
Definition PrintBase.hpp:421
const DynamicPrintConfig & full_print_config() const
Definition PrintBase.hpp:523
void set_status_callback(status_callback_type cb)
Definition PrintBase.hpp:490
std::string output_filepath(const std::string &path, const std::string &filename_base=std::string()) const
Definition PrintBase.cpp:84
Definition Print.hpp:540
const PrintStatistics & print_statistics() const
Definition Print.hpp:632
std::string export_gcode(const std::string &path_template, GCodeProcessorResult *result, ThumbnailsGeneratorCallback thumbnail_cb=nullptr)
Definition Print.cpp:984
This class is the high level FSM for the SLA printing process.
Definition SLAPrint.hpp:440
const SLAPrintStatistics & print_statistics() const
Definition SLAPrint.hpp:495
void export_print(const std::string &fname, const std::string &projectname="")
Definition SLAPrint.hpp:541
Definition TriangleMesh.hpp:88
if(!(yy_init))
Definition lexer.c:1190
int exists(char *filename)
Definition loaddrv.c:45
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half() min(const half &a, const half &b)
Definition Half.h:507
const Scalar & y
Definition MathFunctions.h:552
std::vector< std::string > input_files
Definition GUI_Init.hpp:30
bool start_as_gcodeviewer
Definition GUI_Init.hpp:32
int argc
Definition GUI_Init.hpp:22
bool delete_after_load
Definition GUI_Init.hpp:34
DynamicPrintConfig extra_config
Definition GUI_Init.hpp:29
int GUI_Run(GUI_InitParams &params)
Definition GUI_Init.cpp:35
bool start_downloader
Definition GUI_Init.hpp:33
char ** argv
Definition GUI_Init.hpp:23
std::string download_url
Definition GUI_Init.hpp:35
std::vector< std::string > load_configs
Definition GUI_Init.hpp:28
Definition GUI_Init.hpp:21
void translation_transform(Transform3d &transform, const Vec3d &translation)
Definition Geometry.cpp:328
ForwardCompatibilitySubstitutionRule
Definition Config.hpp:217
BoundingBox scaled(const BoundingBoxf &bb)
Definition BoundingBox.hpp:240
bool run_post_process_scripts(std::string &src_path, bool make_copy, const std::string &host, std::string &output_name, const DynamicPrintConfig &config)
Definition PostProcessor.cpp:198
Eigen::Matrix< double, 2, 1, Eigen::DontAlign > Vec2d
Definition Point.hpp:51
void duplicate(Model &model, Slic3r::arrangement::ArrangePolygons &copies, VirtualBedFn vfn)
Definition ModelArrange.cpp:57
PrinterTechnology
Definition Config.hpp:205
@ ptSLA
Definition Config.hpp:209
@ ptFFF
Definition Config.hpp:207
@ ptUnknown
Definition Config.hpp:211
void save_main_thread_id()
Definition Thread.cpp:197
bool arrange_objects(Model &model, const TBed &bed, const ArrangeParams &params, VirtualBedFn vfn=throw_if_out_of_bed)
Definition ModelArrange.hpp:34
bool is_gcode_file(const std::string &path)
Definition utils.cpp:783
bool set_current_thread_name(const char *thread_name)
Definition Thread.cpp:178
Points get_bed_shape(const DynamicPrintConfig &config)
Definition PrintConfig.cpp:4936
std::vector< ConfigSubstitution > ConfigSubstitutions
Definition Config.hpp:246
std::error_code rename_file(const std::string &from, const std::string &to)
Definition utils.cpp:468
std::vector< ModelObject * > ModelObjectPtrs
Definition Model.hpp:105
@ Y
Definition libslic3r.h:99
@ Z
Definition libslic3r.h:100
@ X
Definition libslic3r.h:98
std::vector< Point, PointsAllocator< Point > > Points
Definition Point.hpp:58
double min_object_distance(const ConfigBase &cfg)
Definition PrintConfig.cpp:4306
Definition Config.hpp:240
double deg2rad(double deg)
Definition agg_basics.h:271
void nowide_filesystem()
Instal utf8_codecvt facet into boost::filesystem::path such all char strings are interpreted as utf-8...
Definition filesystem.hpp:18
Definition args.hpp:18
TMultiShape< PolygonImpl > merge(const TMultiShape< PolygonImpl > &shapes)
Definition geometries.hpp:259
TCoord< P > x(const P &p)
Definition geometry_traits.hpp:297
double distance(const P &p1, const P &p2)
Definition geometry_traits.hpp:329
S::iterator begin(S &sh, const PathTag &)
Definition geometry_traits.hpp:614
S::iterator end(S &sh, const PathTag &)
Definition geometry_traits.hpp:620
void rotate(Slic3r::ExPolygon &sh, const Radians &rads)
Definition geometries.hpp:248
Definition Config.hpp:251
static const std::vector< std::string > precore_str
Definition GUI_Init.hpp:14
static const std::vector< std::string > core_str
Definition GUI_Init.hpp:13
Definition PrintBase.hpp:458
int percent
Definition PrintBase.hpp:464
std::string text
Definition PrintBase.hpp:465
std::string finalize_output_path(const std::string &path_in) const
Definition Print.cpp:1585
std::string finalize_output_path(const std::string &path_in) const
Definition SLAPrint.cpp:1147
Definition Arrange.hpp:130
coord_t min_obj_distance
The minimum distance which is allowed for any pair of items on the print bed in any direction.
Definition Arrange.hpp:134
Representing an unbounded bed.
Definition Arrange.hpp:16

References Slic3r::Model::add_default_instances(), Slic3r::Model::add_object(), Slic3r::ModelObject::add_volume(), Slic3r::Model::AddDefaultInstances, Slic3r::IO::AMF, Slic3r::ConfigBase::apply(), Slic3r::PrintBase::apply(), Slic3r::GUI::GUI_InitParams::argc, Slic3r::GUI::GUI_InitParams::argv, Slic3r::arrange_objects(), Slic3r::Print::auto_assign_extruders(), Slic3r::GUI::OpenGLVersions::core_str, Slic3r::Geometry::deg2rad(), Slic3r::GUI::GUI_InitParams::delete_after_load, Slic3r::GUI::GUI_InitParams::download_url, Slic3r::duplicate(), Slic3r::PrintBase::empty(), Slic3r::Print::export_gcode(), export_models(), Slic3r::SLAPrint::export_print(), Slic3r::GUI::GUI_InitParams::extra_config, Slic3r::PrintStatistics::finalize_output_path(), Slic3r::SLAPrintStatistics::finalize_output_path(), Slic3r::PrintBase::full_print_config(), Slic3r::ConfigBase::get_abs_value(), Slic3r::get_bed_shape(), get_printer_technology(), Slic3r::GUI::GUI_Run(), has_print_action(), Slic3r::GUI::GUI_InitParams::input_files, Slic3r::is_gcode_file(), Slic3r::KeepLower, Slic3r::KeepUpper, Slic3r::ConfigBase::load(), Slic3r::GUI::GUI_InitParams::load_configs, m_actions, m_config, m_extra_config, m_input_files, m_models, m_print_config, m_transforms, Slic3r::BoundingBox3Base< PointType >::merge(), Slic3r::BoundingBoxBase< PointType, APointsType >::min, Slic3r::arrangement::ArrangeParams::min_obj_distance, Slic3r::min_object_distance(), Slic3r::DynamicPrintConfig::normalize_fdm(), boost::nowide::nowide_filesystem(), Slic3r::IO::OBJ, Slic3r::Model::objects, Slic3r::ConfigBase::opt(), Slic3r::ConfigBase::opt_bool(), Slic3r::ConfigBase::opt_float(), Slic3r::ConfigBase::opt_int(), Slic3r::ConfigBase::opt_string(), Slic3r::ConfigBase::option(), Slic3r::PrintBase::output_filepath(), Slic3r::PrintBase::SlicingStatus::percent, Slic3r::PlaceOnCutUpper, Slic3r::GUI::OpenGLVersions::precore_str, print_help(), Slic3r::Print::print_statistics(), Slic3r::SLAPrint::print_statistics(), Slic3r::printer_technology(), Slic3r::PrintBase::process(), Slic3r::ptFFF, Slic3r::ptSLA, Slic3r::ptUnknown, Slic3r::Model::read_from_file(), Slic3r::rename_file(), Slic3r::run_post_process_scripts(), Slic3r::ConfigBase::save(), Slic3r::save_main_thread_id(), Slic3r::scaled(), Slic3r::set_current_thread_name(), Slic3r::PrintBase::set_status_callback(), setup(), Slic3r::GUI::GUI_InitParams::start_as_gcodeviewer, Slic3r::GUI::GUI_InitParams::start_downloader, Slic3r::IO::STL, Slic3r::ConfigSubstitutionContext::substitutions, Slic3r::PrintBase::SlicingStatus::text, Slic3r::IO::TMF, Slic3r::BoundingBox3Base< PointType >::translate(), Slic3r::Geometry::translation_transform(), Slic3r::DynamicPrintConfig::validate(), Slic3r::PrintBase::validate(), Slic3r::ConfigOptionSingle< T >::value, Slic3r::X, Slic3r::Y, and Slic3r::Z.

Referenced by main().

+ Here is the caller graph for this function:

◆ setup()

bool CLI::setup ( int  argc,
char **  argv 
)
private
701{
702 {
704 const char *loglevel = boost::nowide::getenv("SLIC3R_LOGLEVEL");
705 if (loglevel != nullptr) {
706 if (loglevel[0] >= '0' && loglevel[0] <= '9' && loglevel[1] == 0)
707 set_logging_level(loglevel[0] - '0');
708 else
709 boost::nowide::cerr << "Invalid SLIC3R_LOGLEVEL environment variable: " << loglevel << std::endl;
710 }
711 }
712
713 // Detect the operating system flavor after SLIC3R_LOGLEVEL is set.
715
716#ifdef WIN32
717 // Notify user that a blacklisted DLL was injected into PrusaSlicer process (for example Nahimic, see GH #5573).
718 // We hope that if a DLL is being injected into a PrusaSlicer process, it happens at the very start of the application,
719 // thus we shall detect them now.
720 if (BlacklistedLibraryCheck::get_instance().perform_check()) {
721 std::wstring text = L"Following DLLs have been injected into the PrusaSlicer process:\n\n";
722 text += BlacklistedLibraryCheck::get_instance().get_blacklisted_string();
723 text += L"\n\n"
724 L"PrusaSlicer is known to not run correctly with these DLLs injected. "
725 L"We suggest stopping or uninstalling these services if you experience "
726 L"crashes or unexpected behaviour while using PrusaSlicer.\n"
727 L"For example, ASUS Sonic Studio injects a Nahimic driver, which makes PrusaSlicer "
728 L"to crash on a secondary monitor, see PrusaSlicer github issue #5573";
729 MessageBoxW(NULL, text.c_str(), L"Warning"/*L"Incopatible library found"*/, MB_OK);
730 }
731#endif
732
733 // See Invoking prusa-slicer from $PATH environment variable crashes #5542
734 // boost::filesystem::path path_to_binary = boost::filesystem::system_complete(argv[0]);
735 boost::filesystem::path path_to_binary = boost::dll::program_location();
736
737 // Path from the Slic3r binary to its resources.
738#ifdef __APPLE__
739 // The application is packed in the .dmg archive as 'Slic3r.app/Contents/MacOS/Slic3r'
740 // The resources are packed to 'Slic3r.app/Contents/Resources'
741 boost::filesystem::path path_resources = boost::filesystem::canonical(path_to_binary).parent_path() / "../Resources";
742#elif defined _WIN32
743 // The application is packed in the .zip archive in the root,
744 // The resources are packed to 'resources'
745 // Path from Slic3r binary to resources:
746 boost::filesystem::path path_resources = path_to_binary.parent_path() / "resources";
747#elif defined SLIC3R_FHS
748 // The application is packaged according to the Linux Filesystem Hierarchy Standard
749 // Resources are set to the 'Architecture-independent (shared) data', typically /usr/share or /usr/local/share
750 boost::filesystem::path path_resources = SLIC3R_FHS_RESOURCES;
751#else
752 // The application is packed in the .tar.bz archive (or in AppImage) as 'bin/slic3r',
753 // The resources are packed to 'resources'
754 // Path from Slic3r binary to resources:
755 boost::filesystem::path path_resources = boost::filesystem::canonical(path_to_binary).parent_path() / "../resources";
756#endif
757
758 set_resources_dir(path_resources.string());
759 set_var_dir((path_resources / "icons").string());
760 set_local_dir((path_resources / "localization").string());
761 set_sys_shapes_dir((path_resources / "shapes").string());
762
763 // Parse all command line options into a DynamicConfig.
764 // If any option is unsupported, print usage and abort immediately.
765 t_config_option_keys opt_order;
766 if (! m_config.read_cli(argc, argv, &m_input_files, &opt_order)) {
767 // Separate error message reported by the CLI parser from the help.
768 boost::nowide::cerr << std::endl;
769 this->print_help();
770 return false;
771 }
772 // Parse actions and transform options.
773 for (auto const &opt_key : opt_order) {
774 if (cli_actions_config_def.has(opt_key))
775 m_actions.emplace_back(opt_key);
776 else if (cli_transform_config_def.has(opt_key))
777 m_transforms.emplace_back(opt_key);
778 }
779
780 {
781 const ConfigOptionInt *opt_loglevel = m_config.opt<ConfigOptionInt>("loglevel");
782 if (opt_loglevel != 0)
783 set_logging_level(opt_loglevel->value);
784 }
785
786 //FIXME Validating at this stage most likely does not make sense, as the config is not fully initialized yet.
787 std::string validity = m_config.validate();
788
789 // Initialize with defaults.
791 for (const t_optiondef_map::value_type &optdef : *options)
792 m_config.option(optdef.first, true);
793
794 set_data_dir(m_config.opt_string("datadir"));
795
796 //FIXME Validating at this stage most likely does not make sense, as the config is not fully initialized yet.
797 if (!validity.empty()) {
798 boost::nowide::cerr << "error: " << validity << std::endl;
799 return false;
800 }
801
802 return true;
803}
bool has(const t_config_option_key &opt_key) const
Definition Config.hpp:2068
t_optiondef_map options
Definition Config.hpp:2065
Definition Config.hpp:720
bool read_cli(int argc, const char *const argv[], t_config_option_keys *extra, t_config_option_keys *keys=nullptr)
Definition Config.cpp:1112
Definition getopt.h:102
void set_data_dir(const std::string &dir)
Definition utils.cpp:201
void detect_platform()
Definition Platform.cpp:17
void set_local_dir(const std::string &dir)
Definition utils.cpp:174
std::map< t_config_option_key, ConfigOptionDef > t_optiondef_map
Definition Config.hpp:2057
std::vector< std::string > t_config_option_keys
Definition Config.hpp:77
void set_logging_level(unsigned int level)
Definition utils.cpp:97
void set_resources_dir(const std::string &dir)
Definition utils.cpp:162
void set_sys_shapes_dir(const std::string &dir)
Definition utils.cpp:186
void set_var_dir(const std::string &dir)
Definition utils.cpp:144
#define L(s)
Definition I18N.hpp:18

References Slic3r::cli_actions_config_def, Slic3r::cli_misc_config_def, Slic3r::cli_transform_config_def, Slic3r::detect_platform(), Slic3r::ConfigDef::has(), L, m_actions, m_config, m_input_files, m_transforms, Slic3r::ConfigBase::opt(), Slic3r::ConfigBase::opt_string(), Slic3r::ConfigBase::option(), Slic3r::ConfigDef::options, print_help(), Slic3r::DynamicConfig::read_cli(), Slic3r::set_data_dir(), Slic3r::set_local_dir(), Slic3r::set_logging_level(), Slic3r::set_resources_dir(), Slic3r::set_sys_shapes_dir(), Slic3r::set_var_dir(), Slic3r::DynamicPrintConfig::validate(), and Slic3r::ConfigOptionSingle< T >::value.

Referenced by run().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Member Data Documentation

◆ m_actions

std::vector<std::string> Slic3r::CLI::m_actions
private

Referenced by run(), and setup().

◆ m_config

DynamicPrintAndCLIConfig Slic3r::CLI::m_config
private

◆ m_extra_config

DynamicPrintConfig Slic3r::CLI::m_extra_config
private

Referenced by run().

◆ m_input_files

std::vector<std::string> Slic3r::CLI::m_input_files
private

Referenced by run(), and setup().

◆ m_models

std::vector<Model> Slic3r::CLI::m_models
private

Referenced by export_models(), and run().

◆ m_print_config

DynamicPrintConfig Slic3r::CLI::m_print_config
private

Referenced by run().

◆ m_transforms

std::vector<std::string> Slic3r::CLI::m_transforms
private

Referenced by run(), and setup().


The documentation for this class was generated from the following files: