From dbaaa35534c54d0d5ab8c858b29be7712fff222b Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 26 Aug 2021 10:38:14 +0200 Subject: [PATCH 01/82] Tech ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED -> 1st installment: Allow to save/load empty projects --- src/libslic3r/Format/3mf.cpp | 7 +++++++ src/libslic3r/Model.cpp | 2 ++ src/libslic3r/Technologies.hpp | 2 ++ src/slic3r/GUI/GLCanvas3D.cpp | 15 +++++++++++++-- src/slic3r/GUI/MainFrame.cpp | 11 +++++++++++ src/slic3r/GUI/Plater.cpp | 8 ++++++++ 6 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index ed2d5d9c36..d6f14f643b 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -2577,9 +2577,16 @@ namespace Slic3r { bool _3MF_Exporter::_add_build_to_model_stream(std::stringstream& stream, const BuildItemsList& build_items) { +#if ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED + // This happens for empty projects +#endif // ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED if (build_items.size() == 0) { add_error("No build item found"); +#if ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED + return true; +#else return false; +#endif // ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED } stream << " <" << BUILD_TAG << ">\n"; diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 6654d3a130..7d551e2c31 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -161,8 +161,10 @@ Model Model::read_from_archive(const std::string& input_file, DynamicPrintConfig if (!result) throw Slic3r::RuntimeError("Loading of a model file failed."); +#if !ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED if (model.objects.empty()) throw Slic3r::RuntimeError("The supplied file couldn't be read because it's empty"); +#endif // !ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED for (ModelObject *o : model.objects) { diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 02d8fccd45..57f55bb3b7 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -49,6 +49,8 @@ #define ENABLE_SINKING_CONTOURS (1 && ENABLE_2_4_0_ALPHA0) // Enable implementation of retract acceleration in gcode processor #define ENABLE_RETRACT_ACCELERATION (1 && ENABLE_2_4_0_ALPHA0) +// Enable save and save as commands to be enabled also when the plater is empty and allow to load empty projects +#define ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED (1 && ENABLE_2_4_0_ALPHA0) #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index ee1d3b14a4..2cbf3f6c82 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4108,13 +4108,24 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const } } +#if !ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED if (visible_volumes.empty()) return; +#endif // !ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED BoundingBoxf3 volumes_box; - for (const GLVolume* vol : visible_volumes) { - volumes_box.merge(vol->transformed_bounding_box()); +#if ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED + if (!visible_volumes.empty()) { +#endif // ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED + for (const GLVolume* vol : visible_volumes) { + volumes_box.merge(vol->transformed_bounding_box()); + } +#if ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED } + else + // This happens for empty projects + volumes_box = wxGetApp().plater()->get_bed().get_bounding_box(true); +#endif // ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED Camera camera; camera.set_type(camera_type); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 329a9a62a7..b15bab5796 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -824,15 +824,26 @@ bool MainFrame::can_start_new_project() const bool MainFrame::can_save() const { +#if ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED + return (m_plater != nullptr) && + !m_plater->canvas3D()->get_gizmos_manager().is_in_editing_mode(false) && + !m_plater->get_project_filename().empty() && m_plater->is_project_dirty(); +#else return (m_plater != nullptr) && !m_plater->model().objects.empty() && !m_plater->canvas3D()->get_gizmos_manager().is_in_editing_mode(false) && !m_plater->get_project_filename().empty() && m_plater->is_project_dirty(); +#endif // ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED } bool MainFrame::can_save_as() const { +#if ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED + return (m_plater != nullptr) && + !m_plater->canvas3D()->get_gizmos_manager().is_in_editing_mode(false); +#else return (m_plater != nullptr) && !m_plater->model().objects.empty() && !m_plater->canvas3D()->get_gizmos_manager().is_in_editing_mode(false); +#endif // ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED } void MainFrame::save_project() diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 1841220d51..d145aeb75e 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -5587,8 +5587,16 @@ void Plater::export_amf() bool Plater::export_3mf(const boost::filesystem::path& output_path) { +#if ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED + if (p->model.objects.empty()) { + MessageDialog dialog(nullptr, _L("The plater is empty.\nConfirm you want to save the project ?"), _L("Save project"), wxYES_NO); + if (dialog.ShowModal() != wxID_YES) + return false; + } +#else if (p->model.objects.empty()) return false; +#endif // ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED wxString path; bool export_config = true; From 4cc729b312533e8b2001b93b51f0f15c69229a78 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 31 Aug 2021 12:05:06 +0200 Subject: [PATCH 02/82] Fixed encoding of undo/redo snapshot names created through TakeSnapshot class (implicit std::string/wxString conversion) --- src/slic3r/GUI/Plater.cpp | 5 +++++ src/slic3r/GUI/Plater.hpp | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index e8ce905161..14350bddf1 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -6581,6 +6581,11 @@ bool Plater::is_render_statistic_dialog_visible() const return p->show_render_statistic_dialog; } + +Plater::TakeSnapshot::TakeSnapshot(Plater *plater, const std::string &snapshot_name) +: TakeSnapshot(plater, from_u8(snapshot_name)) {} + + // Wrapper around wxWindow::PopupMenu to suppress error messages popping out while tracking the popup menu. bool Plater::PopupMenu(wxMenu *menu, const wxPoint& pos) { diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 3556756e23..99f7e3cdaa 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -383,10 +383,11 @@ public: Plater *m_plater; }; - // ROII wrapper for taking an Undo / Redo snapshot while disabling the snapshot taking by the methods called from inside this snapshot. + // RAII wrapper for taking an Undo / Redo snapshot while disabling the snapshot taking by the methods called from inside this snapshot. class TakeSnapshot { public: + TakeSnapshot(Plater *plater, const std::string &snapshot_name); TakeSnapshot(Plater *plater, const wxString &snapshot_name) : m_plater(plater) { m_plater->take_snapshot(snapshot_name); From 5f26bfd3974c006f3aa0e419c2f7f866225d50de Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Tue, 31 Aug 2021 12:22:38 +0200 Subject: [PATCH 03/82] Brim separation from object, follow up to 82373334bcdaaaf10ed860fd2887b635f815d81f 1) Changed the name of the variable "brim_offset" to "brim_separation" for clarity. 2) Added legacy conversion after loading an old 3MF that does not define then new "brim_separation" variable: The "brim_separation" is being filled in with the "elefant_foot_compensation" value to produce equal brim separation to the old PrusaSlicer that saved that 3MF file. --- resources/profiles/PrusaResearch.idx | 2 +- resources/profiles/PrusaResearch.ini | 2 +- src/libslic3r/Brim.cpp | 26 +++++++++++++------------- src/libslic3r/Format/3mf.cpp | 15 +++++++++++++++ src/libslic3r/Preset.cpp | 2 +- src/libslic3r/PrintConfig.cpp | 6 +++--- src/libslic3r/PrintConfig.hpp | 2 +- src/libslic3r/PrintObject.cpp | 2 +- src/libslic3r/SupportMaterial.cpp | 14 +++++++------- src/slic3r/GUI/ConfigManipulation.cpp | 2 +- src/slic3r/GUI/Plater.cpp | 2 +- src/slic3r/GUI/Tab.cpp | 2 +- 12 files changed, 46 insertions(+), 31 deletions(-) diff --git a/resources/profiles/PrusaResearch.idx b/resources/profiles/PrusaResearch.idx index 37d144ff0f..8a34a9a113 100644 --- a/resources/profiles/PrusaResearch.idx +++ b/resources/profiles/PrusaResearch.idx @@ -1,5 +1,5 @@ min_slic3r_version = 2.4.0-alpha0 -1.4.0-alpha7 Updated brim_offset value. Updated Prusa MINI end g-code. Added Filamentworld filament profiles. +1.4.0-alpha7 Updated brim_separation value. Updated Prusa MINI end g-code. Added Filamentworld filament profiles. 1.4.0-alpha6 Added nozzle priming after M600. Added nozzle diameter checks for 0.8 nozzle printer profiles. Updated FW version. Increased number of top solid infill layers (0.2 layer height). 1.4.0-alpha5 Added multiple add:north and Extrudr filament profiles. Updated support head settings (SL1S). 1.4.0-alpha4 Decreased Area Fill (SL1S). diff --git a/resources/profiles/PrusaResearch.ini b/resources/profiles/PrusaResearch.ini index 0ed5b59a6d..835e552a18 100644 --- a/resources/profiles/PrusaResearch.ini +++ b/resources/profiles/PrusaResearch.ini @@ -144,7 +144,7 @@ bridge_angle = 0 bridge_flow_ratio = 1 bridge_speed = 25 brim_width = 0 -brim_offset = 0.1 +brim_separation = 0.1 clip_multipart_objects = 1 compatible_printers = complete_objects = 0 diff --git a/src/libslic3r/Brim.cpp b/src/libslic3r/Brim.cpp index f4455fdd55..f20404bc9f 100644 --- a/src/libslic3r/Brim.cpp +++ b/src/libslic3r/Brim.cpp @@ -134,10 +134,10 @@ static Polygons top_level_outer_brim_islands(const ConstPrintObjectPtrs &top_lev Polygons islands; for (const PrintObject *object : top_level_objects_with_brim) { //FIXME how about the brim type? - auto brim_offset = float(scale_(object->config().brim_offset.value)); + auto brim_separation = float(scale_(object->config().brim_separation.value)); Polygons islands_object; for (const ExPolygon &ex_poly : get_print_object_bottom_layer_expolygons(*object)) { - Polygons contour_offset = offset(ex_poly.contour, brim_offset); + Polygons contour_offset = offset(ex_poly.contour, brim_separation); for (Polygon &poly : contour_offset) poly.douglas_peucker(SCALED_RESOLUTION); @@ -166,7 +166,7 @@ static ExPolygons top_level_outer_brim_area(const Print &print for(size_t print_object_idx = 0; print_object_idx < print.objects().size(); ++print_object_idx) { const PrintObject *object = print.objects()[print_object_idx]; const BrimType brim_type = object->config().brim_type.value; - const float brim_offset = scale_(object->config().brim_offset.value); + const float brim_separation = scale_(object->config().brim_separation.value); const float brim_width = scale_(object->config().brim_width.value); const bool is_top_outer_brim = top_level_objects_idx.find(object->id().id) != top_level_objects_idx.end(); @@ -174,7 +174,7 @@ static ExPolygons top_level_outer_brim_area(const Print &print ExPolygons no_brim_area_object; for (const ExPolygon &ex_poly : bottom_layers_expolygons[print_object_idx]) { if ((brim_type == BrimType::btOuterOnly || brim_type == BrimType::btOuterAndInner) && is_top_outer_brim) - append(brim_area_object, diff_ex(offset(ex_poly.contour, brim_width + brim_offset), offset(ex_poly.contour, brim_offset))); + append(brim_area_object, diff_ex(offset(ex_poly.contour, brim_width + brim_separation), offset(ex_poly.contour, brim_separation))); if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btNoBrim) append(no_brim_area_object, offset_ex(ex_poly.holes, -no_brim_offset)); @@ -183,7 +183,7 @@ static ExPolygons top_level_outer_brim_area(const Print &print append(no_brim_area_object, diff_ex(offset(ex_poly.contour, no_brim_offset), ex_poly.holes)); if (brim_type != BrimType::btNoBrim) - append(no_brim_area_object, offset_ex(ExPolygon(ex_poly.contour), brim_offset)); + append(no_brim_area_object, offset_ex(ExPolygon(ex_poly.contour), brim_separation)); no_brim_area_object.emplace_back(ex_poly.contour); } @@ -212,11 +212,11 @@ static ExPolygons inner_brim_area(const Print &print, ExPolygons no_brim_area; Polygons holes; for(size_t print_object_idx = 0; print_object_idx < print.objects().size(); ++print_object_idx) { - const PrintObject *object = print.objects()[print_object_idx]; - const BrimType brim_type = object->config().brim_type.value; - const float brim_offset = scale_(object->config().brim_offset.value); - const float brim_width = scale_(object->config().brim_width.value); - const bool top_outer_brim = top_level_objects_idx.find(object->id().id) != top_level_objects_idx.end(); + const PrintObject *object = print.objects()[print_object_idx]; + const BrimType brim_type = object->config().brim_type.value; + const float brim_separation = scale_(object->config().brim_separation.value); + const float brim_width = scale_(object->config().brim_width.value); + const bool top_outer_brim = top_level_objects_idx.find(object->id().id) != top_level_objects_idx.end(); ExPolygons brim_area_object; ExPolygons no_brim_area_object; @@ -226,11 +226,11 @@ static ExPolygons inner_brim_area(const Print &print, if (top_outer_brim) no_brim_area_object.emplace_back(ex_poly); else - append(brim_area_object, diff_ex(offset(ex_poly.contour, brim_width + brim_offset), offset(ex_poly.contour, brim_offset))); + append(brim_area_object, diff_ex(offset(ex_poly.contour, brim_width + brim_separation), offset(ex_poly.contour, brim_separation))); } if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btOuterAndInner) - append(brim_area_object, diff_ex(offset_ex(ex_poly.holes, -brim_offset), offset_ex(ex_poly.holes, -brim_width - brim_offset))); + append(brim_area_object, diff_ex(offset_ex(ex_poly.holes, -brim_separation), offset_ex(ex_poly.holes, -brim_width - brim_separation))); if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btNoBrim) append(no_brim_area_object, diff_ex(offset(ex_poly.contour, no_brim_offset), ex_poly.holes)); @@ -240,7 +240,7 @@ static ExPolygons inner_brim_area(const Print &print, append(holes_object, ex_poly.holes); } - append(no_brim_area_object, offset_ex(bottom_layers_expolygons[print_object_idx], brim_offset)); + append(no_brim_area_object, offset_ex(bottom_layers_expolygons[print_object_idx], brim_separation)); for (const PrintInstance &instance : object->instances()) { append_and_translate(brim_area, brim_area_object, instance); diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 57b0d81159..74969b5239 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -420,6 +420,7 @@ namespace Slic3r { ~_3MF_Importer(); bool load_model_from_file(const std::string& filename, Model& model, DynamicPrintConfig& config, ConfigSubstitutionContext& config_substitutions, bool check_version); + unsigned int version() const { return m_version; } private: void _destroy_xml_parser(); @@ -2990,6 +2991,19 @@ bool _3MF_Exporter::_add_custom_gcode_per_print_z_file_to_archive( mz_zip_archiv return true; } +// Perform conversions based on the config values available. +//FIXME provide a version of PrusaSlicer that stored the project file (3MF). +static void handle_legacy_project_loaded(unsigned int version_project_file, DynamicPrintConfig& config) +{ + if (! config.has("brim_separation")) { + if (auto *opt_elephant_foot = config.option("elefant_foot_compensation", false); opt_elephant_foot) { + // Conversion from older PrusaSlicer which applied brim separation equal to elephant foot compensation. + auto *opt_brim_separation = config.option("brim_separation", true); + opt_brim_separation->value = opt_elephant_foot->value; + } + } +} + bool load_3mf(const char* path, DynamicPrintConfig& config, ConfigSubstitutionContext& config_substitutions, Model* model, bool check_version) { if (path == nullptr || model == nullptr) @@ -3000,6 +3014,7 @@ bool load_3mf(const char* path, DynamicPrintConfig& config, ConfigSubstitutionCo _3MF_Importer importer; bool res = importer.load_model_from_file(path, *model, config, config_substitutions, check_version); importer.log_errors(); + handle_legacy_project_loaded(importer.version(), config); return res; } diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 3883c4980b..564300baf3 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -430,7 +430,7 @@ static std::vector s_Preset_print_options { "top_solid_infill_speed", "support_material_speed", "support_material_xy_spacing", "support_material_interface_speed", "bridge_speed", "gap_fill_speed", "gap_fill_enabled", "travel_speed", "travel_speed_z", "first_layer_speed", "perimeter_acceleration", "infill_acceleration", "bridge_acceleration", "first_layer_acceleration", "default_acceleration", "skirts", "skirt_distance", "skirt_height", "draft_shield", - "min_skirt_length", "brim_width", "brim_offset", "brim_type", "support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers", + "min_skirt_length", "brim_width", "brim_separation", "brim_type", "support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers", "raft_layers", "raft_first_layer_density", "raft_first_layer_expansion", "raft_contact_distance", "raft_expansion", "support_material_pattern", "support_material_with_sheath", "support_material_spacing", "support_material_closing_radius", "support_material_style", "support_material_synchronize_layers", "support_material_angle", "support_material_interface_layers", "support_material_bottom_interface_layers", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index f010bad399..b5c1cbeb33 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -505,10 +505,10 @@ void PrintConfigDef::init_fff_params() def->mode = comSimple; def->set_default_value(new ConfigOptionEnum(btOuterOnly)); - def = this->add("brim_offset", coFloat); - def->label = L("Brim offset"); + def = this->add("brim_separation", coFloat); + def->label = L("Brim separation gap"); def->category = L("Skirt and brim"); - def->tooltip = L("The offset of the brim from the printed object. The offset is applied after the elephant foot compensation."); + def->tooltip = L("Offset of brim from the printed object. The offset is applied after the elephant foot compensation."); def->sidetext = L("mm"); def->min = 0; def->mode = comAdvanced; diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 64c8445f8c..f5070c54d9 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -449,7 +449,7 @@ protected: \ PRINT_CONFIG_CLASS_DEFINE( PrintObjectConfig, - ((ConfigOptionFloat, brim_offset)) + ((ConfigOptionFloat, brim_separation)) ((ConfigOptionEnum, brim_type)) ((ConfigOptionFloat, brim_width)) ((ConfigOptionBool, clip_multipart_objects)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index d8d26baa61..f0eaa982ab 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -500,7 +500,7 @@ bool PrintObject::invalidate_state_by_config_options( bool invalidated = false; for (const t_config_option_key &opt_key : opt_keys) { if ( opt_key == "brim_width" - || opt_key == "brim_offset" + || opt_key == "brim_separation" || opt_key == "brim_type") { // Brim is printed below supports, support invalidates brim and skirt. steps.emplace_back(posSupportMaterial); diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index 2e4a479543..1b66bcc533 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -2810,22 +2810,22 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf Polygons brim; if (object.has_brim()) { // Calculate the area covered by the brim. - const BrimType brim_type = object.config().brim_type; - const bool brim_outer = brim_type == btOuterOnly || brim_type == btOuterAndInner; - const bool brim_inner = brim_type == btInnerOnly || brim_type == btOuterAndInner; - const auto brim_offset = scaled(object.config().brim_offset.value + object.config().brim_width.value); + const BrimType brim_type = object.config().brim_type; + const bool brim_outer = brim_type == btOuterOnly || brim_type == btOuterAndInner; + const bool brim_inner = brim_type == btInnerOnly || brim_type == btOuterAndInner; + const auto brim_separation = scaled(object.config().brim_separation.value + object.config().brim_width.value); for (const ExPolygon &ex : object.layers().front()->lslices) { if (brim_outer && brim_inner) - polygons_append(brim, offset(ex, brim_offset)); + polygons_append(brim, offset(ex, brim_separation)); else { if (brim_outer) - polygons_append(brim, offset(ex.contour, brim_offset, ClipperLib::jtRound, float(scale_(0.1)))); + polygons_append(brim, offset(ex.contour, brim_separation, ClipperLib::jtRound, float(scale_(0.1)))); else brim.emplace_back(ex.contour); if (brim_inner) { Polygons holes = ex.holes; polygons_reverse(holes); - holes = offset(holes, - brim_offset, ClipperLib::jtRound, float(scale_(0.1))); + holes = offset(holes, - brim_separation, ClipperLib::jtRound, float(scale_(0.1))); polygons_reverse(holes); polygons_append(brim, std::move(holes)); } else diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 54b87786a5..72584e9389 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -281,7 +281,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) toggle_field(el, have_skirt); bool have_brim = config->opt_enum("brim_type") != btNoBrim; - for (auto el : { "brim_width", "brim_offset" }) + for (auto el : { "brim_width", "brim_separation" }) toggle_field(el, have_brim); // perimeter_extruder uses the same logic as in Print::extruders() toggle_field("perimeter_extruder", have_perimeters || have_brim); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 14350bddf1..743f275782 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1834,7 +1834,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) , main_frame(main_frame) , config(Slic3r::DynamicPrintConfig::new_from_defaults_keys({ "bed_shape", "bed_custom_texture", "bed_custom_model", "complete_objects", "duplicate_distance", "extruder_clearance_radius", "skirts", "skirt_distance", - "brim_width", "brim_offset", "brim_type", "variable_layer_height", "nozzle_diameter", "single_extruder_multi_material", + "brim_width", "brim_separation", "brim_type", "variable_layer_height", "nozzle_diameter", "single_extruder_multi_material", "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "extruder_colour", "filament_colour", "max_print_height", "printer_model", "printer_technology", // These values are necessary to construct SlicingParameters by the Canvas3D variable layer height editor. diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index bc4c6b7289..6bd295fdc9 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1509,7 +1509,7 @@ void TabPrint::build() optgroup = page->new_optgroup(L("Brim")); optgroup->append_single_option_line("brim_type", category_path + "brim"); optgroup->append_single_option_line("brim_width", category_path + "brim"); - optgroup->append_single_option_line("brim_offset", category_path + "brim"); + optgroup->append_single_option_line("brim_separation", category_path + "brim"); page = add_options_page(L("Support material"), "support"); category_path = "support-material_1698#"; From c797bed67d0db1281fb0820238aa811a4b66fcdf Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 31 Aug 2021 14:35:32 +0200 Subject: [PATCH 04/82] Changed vertex attributes syntax in gouraud_light_instanced.vs --- resources/shaders/gouraud_light_instanced.vs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/shaders/gouraud_light_instanced.vs b/resources/shaders/gouraud_light_instanced.vs index 69f58d6e14..a8931361d0 100644 --- a/resources/shaders/gouraud_light_instanced.vs +++ b/resources/shaders/gouraud_light_instanced.vs @@ -15,11 +15,11 @@ const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); #define INTENSITY_AMBIENT 0.3 // vertex attributes -in vec3 v_position; -in vec3 v_normal; +attribute vec3 v_position; +attribute vec3 v_normal; // instance attributes -in vec3 i_offset; -in vec2 i_scales; +attribute vec3 i_offset; +attribute vec2 i_scales; // x = tainted, y = specular; varying vec2 intensity; From 1835dae296f52f6704fbaee25f504d18dae589dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Mon, 30 Aug 2021 15:51:16 +0200 Subject: [PATCH 05/82] Fixed a bug that the skirt was generated too far from the brim for some objects. --- src/libslic3r/Brim.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/libslic3r/Brim.cpp b/src/libslic3r/Brim.cpp index f20404bc9f..db31975e35 100644 --- a/src/libslic3r/Brim.cpp +++ b/src/libslic3r/Brim.cpp @@ -137,7 +137,7 @@ static Polygons top_level_outer_brim_islands(const ConstPrintObjectPtrs &top_lev auto brim_separation = float(scale_(object->config().brim_separation.value)); Polygons islands_object; for (const ExPolygon &ex_poly : get_print_object_bottom_layer_expolygons(*object)) { - Polygons contour_offset = offset(ex_poly.contour, brim_separation); + Polygons contour_offset = offset(ex_poly.contour, brim_separation, ClipperLib::jtSquare); for (Polygon &poly : contour_offset) poly.douglas_peucker(SCALED_RESOLUTION); @@ -174,16 +174,16 @@ static ExPolygons top_level_outer_brim_area(const Print &print ExPolygons no_brim_area_object; for (const ExPolygon &ex_poly : bottom_layers_expolygons[print_object_idx]) { if ((brim_type == BrimType::btOuterOnly || brim_type == BrimType::btOuterAndInner) && is_top_outer_brim) - append(brim_area_object, diff_ex(offset(ex_poly.contour, brim_width + brim_separation), offset(ex_poly.contour, brim_separation))); + append(brim_area_object, diff_ex(offset(ex_poly.contour, brim_width + brim_separation, ClipperLib::jtSquare), offset(ex_poly.contour, brim_separation, ClipperLib::jtSquare))); if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btNoBrim) - append(no_brim_area_object, offset_ex(ex_poly.holes, -no_brim_offset)); + append(no_brim_area_object, offset_ex(ex_poly.holes, -no_brim_offset, ClipperLib::jtSquare)); if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btNoBrim) - append(no_brim_area_object, diff_ex(offset(ex_poly.contour, no_brim_offset), ex_poly.holes)); + append(no_brim_area_object, diff_ex(offset(ex_poly.contour, no_brim_offset, ClipperLib::jtSquare), ex_poly.holes)); if (brim_type != BrimType::btNoBrim) - append(no_brim_area_object, offset_ex(ExPolygon(ex_poly.contour), brim_separation)); + append(no_brim_area_object, offset_ex(ExPolygon(ex_poly.contour), brim_separation, ClipperLib::jtSquare)); no_brim_area_object.emplace_back(ex_poly.contour); } @@ -226,21 +226,21 @@ static ExPolygons inner_brim_area(const Print &print, if (top_outer_brim) no_brim_area_object.emplace_back(ex_poly); else - append(brim_area_object, diff_ex(offset(ex_poly.contour, brim_width + brim_separation), offset(ex_poly.contour, brim_separation))); + append(brim_area_object, diff_ex(offset(ex_poly.contour, brim_width + brim_separation, ClipperLib::jtSquare), offset(ex_poly.contour, brim_separation, ClipperLib::jtSquare))); } if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btOuterAndInner) - append(brim_area_object, diff_ex(offset_ex(ex_poly.holes, -brim_separation), offset_ex(ex_poly.holes, -brim_width - brim_separation))); + append(brim_area_object, diff_ex(offset_ex(ex_poly.holes, -brim_separation, ClipperLib::jtSquare), offset_ex(ex_poly.holes, -brim_width - brim_separation, ClipperLib::jtSquare))); if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btNoBrim) - append(no_brim_area_object, diff_ex(offset(ex_poly.contour, no_brim_offset), ex_poly.holes)); + append(no_brim_area_object, diff_ex(offset(ex_poly.contour, no_brim_offset, ClipperLib::jtSquare), ex_poly.holes)); if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btNoBrim) - append(no_brim_area_object, offset_ex(ex_poly.holes, -no_brim_offset)); + append(no_brim_area_object, offset_ex(ex_poly.holes, -no_brim_offset, ClipperLib::jtSquare)); append(holes_object, ex_poly.holes); } - append(no_brim_area_object, offset_ex(bottom_layers_expolygons[print_object_idx], brim_separation)); + append(no_brim_area_object, offset_ex(bottom_layers_expolygons[print_object_idx], brim_separation, ClipperLib::jtSquare)); for (const PrintInstance &instance : object->instances()) { append_and_translate(brim_area, brim_area_object, instance); @@ -356,12 +356,12 @@ static void make_inner_brim(const Print &print, Flow flow = print.brim_flow(); ExPolygons islands_ex = inner_brim_area(print, top_level_objects_with_brim, bottom_layers_expolygons, float(flow.scaled_spacing())); Polygons loops; - islands_ex = offset_ex(islands_ex, -0.5f * float(flow.scaled_spacing()), jtSquare); + islands_ex = offset_ex(islands_ex, -0.5f * float(flow.scaled_spacing()), ClipperLib::jtSquare); for (size_t i = 0; !islands_ex.empty(); ++i) { for (ExPolygon &poly_ex : islands_ex) poly_ex.douglas_peucker(SCALED_RESOLUTION); polygons_append(loops, to_polygons(islands_ex)); - islands_ex = offset_ex(islands_ex, -float(flow.scaled_spacing()), jtSquare); + islands_ex = offset_ex(islands_ex, -float(flow.scaled_spacing()), ClipperLib::jtSquare); } loops = union_pt_chained_outside_in(loops); @@ -385,7 +385,7 @@ ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cance size_t num_loops = size_t(floor(max_brim_width(print.objects()) / flow.spacing())); for (size_t i = 0; i < num_loops; ++i) { try_cancel(); - islands = offset(islands, float(flow.scaled_spacing()), jtSquare); + islands = offset(islands, float(flow.scaled_spacing()), ClipperLib::jtSquare); for (Polygon &poly : islands) poly.douglas_peucker(SCALED_RESOLUTION); polygons_append(loops, offset(islands, -0.5f * float(flow.scaled_spacing()))); From ccf671dcc983b63627fa61f3db6f594e0cb772ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Tue, 31 Aug 2021 08:03:09 +0200 Subject: [PATCH 06/82] Added versioning of the structure of stored data for all three painting gizmos (fdm supports, seam and multi-material). --- src/libslic3r/Format/3mf.cpp | 52 ++++++++++++++++++++++++++++++++++++ src/libslic3r/Model.cpp | 25 +++++++++++++++++ src/libslic3r/Model.hpp | 13 +++++++++ 3 files changed, 90 insertions(+) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 74969b5239..cde7d0a439 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -49,6 +49,17 @@ const unsigned int VERSION_3MF = 1; const unsigned int VERSION_3MF_COMPATIBLE = 2; const char* SLIC3RPE_3MF_VERSION = "slic3rpe:Version3mf"; // definition of the metadata name saved into .model file +// Painting gizmos data version numbers +// 0 : 3MF files saved by older PrusaSlicer or the painting gizmo wasn't used. No version definition in them. +// 1 : Introduction of painting gizmos data versioning. No other changes in painting gizmos data. +const unsigned int FDM_SUPPORTS_PAINTING_VERSION = 1; +const unsigned int SEAM_PAINTING_VERSION = 1; +const unsigned int MM_PAINTING_VERSION = 1; + +const std::string SLIC3RPE_FDM_SUPPORTS_PAINTING_VERSION = "slic3rpe:FdmSupportsPaintingVersion"; +const std::string SLIC3RPE_SEAM_PAINTING_VERSION = "slic3rpe:SeamPaintingVersion"; +const std::string SLIC3RPE_MM_PAINTING_VERSION = "slic3rpe:MmPaintingVersion"; + const std::string MODEL_FOLDER = "3D/"; const std::string MODEL_EXTENSION = ".model"; const std::string MODEL_FILE = "3D/3dmodel.model"; // << this is the only format of the string which works with CURA @@ -393,6 +404,10 @@ namespace Slic3r { unsigned int m_version; bool m_check_version; + unsigned int m_fdm_supports_painting_version = 0; + unsigned int m_seam_painting_version = 0; + unsigned int m_mm_painting_version = 0; + XML_Parser m_xml_parser; // Error code returned by the application side of the parser. In that case the expat may not reliably deliver the error state // after returning from XML_Parse() function, thus we keep the error state here. @@ -543,6 +558,9 @@ namespace Slic3r { bool _3MF_Importer::load_model_from_file(const std::string& filename, Model& model, DynamicPrintConfig& config, ConfigSubstitutionContext& config_substitutions, bool check_version) { m_version = 0; + m_fdm_supports_painting_version = 0; + m_seam_painting_version = 0; + m_mm_painting_version = 0; m_check_version = check_version; m_model = &model; m_unit_factor = 1.0f; @@ -1669,6 +1687,12 @@ namespace Slic3r { return true; } + inline static void check_painting_version(unsigned int loaded_version, unsigned int highest_supported_version, const std::string &error_msg) + { + if (loaded_version > highest_supported_version) + throw version_error(error_msg); + } + bool _3MF_Importer::_handle_end_metadata() { if (m_curr_metadata_name == SLIC3RPE_3MF_VERSION) { @@ -1681,6 +1705,24 @@ namespace Slic3r { } } + if (m_curr_metadata_name == SLIC3RPE_FDM_SUPPORTS_PAINTING_VERSION) { + m_fdm_supports_painting_version = (unsigned int) atoi(m_curr_characters.c_str()); + check_painting_version(m_fdm_supports_painting_version, FDM_SUPPORTS_PAINTING_VERSION, + _(L("The selected 3MF contains FDM supports painted object using a newer version of PrusaSlicer and is not compatible."))); + } + + if (m_curr_metadata_name == SLIC3RPE_SEAM_PAINTING_VERSION) { + m_seam_painting_version = (unsigned int) atoi(m_curr_characters.c_str()); + check_painting_version(m_seam_painting_version, SEAM_PAINTING_VERSION, + _(L("The selected 3MF contains seam painted object using a newer version of PrusaSlicer and is not compatible."))); + } + + if (m_curr_metadata_name == SLIC3RPE_MM_PAINTING_VERSION) { + m_mm_painting_version = (unsigned int) atoi(m_curr_characters.c_str()); + check_painting_version(m_mm_painting_version, MM_PAINTING_VERSION, + _(L("The selected 3MF contains multi-material painted object using a newer version of PrusaSlicer and is not compatible."))); + } + return true; } @@ -2294,6 +2336,16 @@ namespace Slic3r { stream << "\n"; stream << "<" << MODEL_TAG << " unit=\"millimeter\" xml:lang=\"en-US\" xmlns=\"http://schemas.microsoft.com/3dmanufacturing/core/2015/02\" xmlns:slic3rpe=\"http://schemas.slic3r.org/3mf/2017/06\">\n"; stream << " <" << METADATA_TAG << " name=\"" << SLIC3RPE_3MF_VERSION << "\">" << VERSION_3MF << "\n"; + + if (model.is_fdm_support_painted()) + stream << " <" << METADATA_TAG << " name=\"" << SLIC3RPE_FDM_SUPPORTS_PAINTING_VERSION << "\">" << FDM_SUPPORTS_PAINTING_VERSION << "\n"; + + if (model.is_seam_painted()) + stream << " <" << METADATA_TAG << " name=\"" << SLIC3RPE_SEAM_PAINTING_VERSION << "\">" << SEAM_PAINTING_VERSION << "\n"; + + if (model.is_mm_painted()) + stream << " <" << METADATA_TAG << " name=\"" << SLIC3RPE_MM_PAINTING_VERSION << "\">" << MM_PAINTING_VERSION << "\n"; + std::string name = xml_escape(boost::filesystem::path(filename).stem().string()); stream << " <" << METADATA_TAG << " name=\"Title\">" << name << "\n"; stream << " <" << METADATA_TAG << " name=\"Designer\">" << "\n"; diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 6f9e4fd4c1..dcffbb1f3a 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -557,6 +557,21 @@ std::string Model::propose_export_file_name_and_path(const std::string &new_exte return boost::filesystem::path(this->propose_export_file_name_and_path()).replace_extension(new_extension).string(); } +bool Model::is_fdm_support_painted() const +{ + return std::any_of(this->objects.cbegin(), this->objects.cend(), [](const ModelObject *mo) { return mo->is_fdm_support_painted(); }); +} + +bool Model::is_seam_painted() const +{ + return std::any_of(this->objects.cbegin(), this->objects.cend(), [](const ModelObject *mo) { return mo->is_seam_painted(); }); +} + +bool Model::is_mm_painted() const +{ + return std::any_of(this->objects.cbegin(), this->objects.cend(), [](const ModelObject *mo) { return mo->is_mm_painted(); }); +} + ModelObject::~ModelObject() { this->clear_volumes(); @@ -733,6 +748,16 @@ void ModelObject::clear_volumes() this->invalidate_bounding_box(); } +bool ModelObject::is_fdm_support_painted() const +{ + return std::any_of(this->volumes.cbegin(), this->volumes.cend(), [](const ModelVolume *mv) { return mv->is_fdm_support_painted(); }); +} + +bool ModelObject::is_seam_painted() const +{ + return std::any_of(this->volumes.cbegin(), this->volumes.cend(), [](const ModelVolume *mv) { return mv->is_seam_painted(); }); +} + bool ModelObject::is_mm_painted() const { return std::any_of(this->volumes.cbegin(), this->volumes.cend(), [](const ModelVolume *mv) { return mv->is_mm_painted(); }); diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index ec6fac8214..ba3156139a 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -285,6 +285,10 @@ public: void clear_volumes(); void sort_volumes(bool full_sort); bool is_multiparts() const { return volumes.size() > 1; } + // Checks if any of object volume is painted using the fdm support painting gizmo. + bool is_fdm_support_painted() const; + // Checks if any of object volume is painted using the seam painting gizmo. + bool is_seam_painted() const; // Checks if any of object volume is painted using the multi-material painting gizmo. bool is_mm_painted() const; @@ -723,6 +727,8 @@ public: this->mmu_segmentation_facets.set_new_unique_id(); } + bool is_fdm_support_painted() const { return !this->supported_facets.empty(); } + bool is_seam_painted() const { return !this->seam_facets.empty(); } bool is_mm_painted() const { return !this->mmu_segmentation_facets.empty(); } protected: @@ -1127,6 +1133,13 @@ public: // Propose an output path, replace extension. The new_extension shall contain the initial dot. std::string propose_export_file_name_and_path(const std::string &new_extension) const; + // Checks if any of objects is painted using the fdm support painting gizmo. + bool is_fdm_support_painted() const; + // Checks if any of objects is painted using the seam painting gizmo. + bool is_seam_painted() const; + // Checks if any of objects is painted using the multi-material painting gizmo. + bool is_mm_painted() const; + private: explicit Model(int) : ObjectBase(-1) { assert(this->id().invalid()); } void assign_new_unique_ids_recursive(); From b29c0ead7dfc1a997cad012b9f04e84cec1beb9a Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Tue, 31 Aug 2021 16:03:07 +0200 Subject: [PATCH 07/82] Implemented configurable speed and acceleration settings for the first object layer over raft interface: "first_layer_speed_over_raft", "first_layer_acceleration_over_raft". Fixes I have a question about the speed of the first layer after the raft. #6623 Fixes Layer After Raft Is Not Considered First Layer! #6166 --- src/libslic3r/GCode.cpp | 18 +++++++++++++++--- src/libslic3r/GCode.hpp | 11 ++++++++--- src/libslic3r/Preset.cpp | 4 ++-- src/libslic3r/Print.cpp | 2 ++ src/libslic3r/PrintConfig.cpp | 19 +++++++++++++++++++ src/libslic3r/PrintConfig.hpp | 2 ++ src/slic3r/GUI/ConfigManipulation.cpp | 3 ++- src/slic3r/GUI/Tab.cpp | 2 ++ 8 files changed, 52 insertions(+), 9 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 85e6f810b7..19909b2bcf 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1977,6 +1977,7 @@ void GCode::process_layer( } gcode += this->change_layer(print_z); // this will increase m_layer_index m_layer = &layer; + m_object_layer_over_raft = false; if (! print.config().layer_gcode.value.empty()) { DynamicConfig config; config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index)); @@ -2235,8 +2236,13 @@ void GCode::process_layer( gcode+="; PURGING FINISHED\n"; for (InstanceToPrint &instance_to_print : instances_to_print) { + const LayerToPrint &layer_to_print = layers[instance_to_print.layer_id]; + // To control print speed of the 1st object layer printed over raft interface. + bool object_layer_over_raft = layer_to_print.object_layer && layer_to_print.object_layer->id() > 0 && + instance_to_print.print_object.slicing_parameters().raft_layers() == layer_to_print.object_layer->id(); m_config.apply(instance_to_print.print_object.config(), true); - m_layer = layers[instance_to_print.layer_id].layer(); + m_layer = layer_to_print.layer(); + m_object_layer_over_raft = object_layer_over_raft; if (m_config.avoid_crossing_perimeters) m_avoid_crossing_perimeters.init_layer(*m_layer); if (this->config().gcode_label_objects) @@ -2249,11 +2255,13 @@ void GCode::process_layer( m_last_obj_copy = this_object_copy; this->set_origin(unscale(offset)); if (instance_to_print.object_by_extruder.support != nullptr && !print_wipe_extrusions) { - m_layer = layers[instance_to_print.layer_id].support_layer; + m_layer = layer_to_print.support_layer; + m_object_layer_over_raft = false; gcode += this->extrude_support( // support_extrusion_role is erSupportMaterial, erSupportMaterialInterface or erMixed for all extrusion paths. instance_to_print.object_by_extruder.support->chained_path_from(m_last_pos, instance_to_print.object_by_extruder.support_extrusion_role)); - m_layer = layers[instance_to_print.layer_id].layer(); + m_layer = layer_to_print.layer(); + m_object_layer_over_raft = object_layer_over_raft; } //FIXME order islands? // Sequential tool path ordering of multiple parts within the same object, aka. perimeter tracking (#5511) @@ -2705,6 +2713,8 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, double acceleration; if (this->on_first_layer() && m_config.first_layer_acceleration.value > 0) { acceleration = m_config.first_layer_acceleration.value; + } else if (this->object_layer_over_raft() && m_config.first_layer_acceleration_over_raft.value > 0) { + acceleration = m_config.first_layer_acceleration_over_raft.value; } else if (m_config.perimeter_acceleration.value > 0 && is_perimeter(path.role())) { acceleration = m_config.perimeter_acceleration.value; } else if (m_config.bridge_acceleration.value > 0 && is_bridge(path.role())) { @@ -2749,6 +2759,8 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, speed = m_volumetric_speed / path.mm3_per_mm; if (this->on_first_layer()) speed = m_config.get_abs_value("first_layer_speed", speed); + else if (this->object_layer_over_raft()) + speed = m_config.get_abs_value("first_layer_speed_over_raft", speed); if (m_config.max_volumetric_speed.value > 0) { // cap speed with max_volumetric_speed anyway (even if user is not using autospeed) speed = std::min( diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 08ab830024..d2d241054f 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -125,7 +125,8 @@ public: m_last_processor_extrusion_role(erNone), m_layer_count(0), m_layer_index(-1), - m_layer(nullptr), + m_layer(nullptr), + m_object_layer_over_raft(false), m_volumetric_speed(0), m_last_pos_defined(false), m_last_extrusion_role(erNone), @@ -138,7 +139,7 @@ public: m_silent_time_estimator_enabled(false), m_last_obj_copy(nullptr, Point(std::numeric_limits::max(), std::numeric_limits::max())) {} - ~GCode() {} + ~GCode() = default; // throws std::runtime_exception on error, // throws CanceledException through print->throw_if_canceled(). @@ -316,9 +317,11 @@ private: unsigned int m_layer_count; // Progress bar indicator. Increments from -1 up to layer_count. int m_layer_index; - // Current layer processed. Insequential printing mode, only a single copy will be printed. + // Current layer processed. In sequential printing mode, only a single copy will be printed. // In non-sequential mode, all its copies will be printed. const Layer* m_layer; + // m_layer is an object layer and it is being printed over raft surface. + bool m_object_layer_over_raft; double m_volumetric_speed; // Support for the extrusion role markers. Which marker is active? ExtrusionRole m_last_extrusion_role; @@ -373,6 +376,8 @@ private: void _print_first_layer_extruder_temperatures(FILE *file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait); // On the first printing layer. This flag triggers first layer speeds. bool on_first_layer() const { return m_layer != nullptr && m_layer->id() == 0; } + // To control print speed of 1st object layer over raft interface. + bool object_layer_over_raft() const { return m_object_layer_over_raft; } friend ObjectByExtruder& object_by_extruder( std::map> &by_extruder, diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 564300baf3..f5c8235ed5 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -428,8 +428,8 @@ static std::vector s_Preset_print_options { #endif /* HAS_PRESSURE_EQUALIZER */ "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed", "infill_speed", "solid_infill_speed", "top_solid_infill_speed", "support_material_speed", "support_material_xy_spacing", "support_material_interface_speed", - "bridge_speed", "gap_fill_speed", "gap_fill_enabled", "travel_speed", "travel_speed_z", "first_layer_speed", "perimeter_acceleration", "infill_acceleration", - "bridge_acceleration", "first_layer_acceleration", "default_acceleration", "skirts", "skirt_distance", "skirt_height", "draft_shield", + "bridge_speed", "gap_fill_speed", "gap_fill_enabled", "travel_speed", "travel_speed_z", "first_layer_speed", "first_layer_speed_over_raft", "perimeter_acceleration", "infill_acceleration", + "bridge_acceleration", "first_layer_acceleration", "first_layer_acceleration_over_raft", "default_acceleration", "skirts", "skirt_distance", "skirt_height", "draft_shield", "min_skirt_length", "brim_width", "brim_separation", "brim_type", "support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers", "raft_layers", "raft_first_layer_density", "raft_first_layer_expansion", "raft_contact_distance", "raft_expansion", "support_material_pattern", "support_material_with_sheath", "support_material_spacing", "support_material_closing_radius", "support_material_style", diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 48737f8302..06052a62f3 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -88,7 +88,9 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n "filament_cost", "filament_spool_weight", "first_layer_acceleration", + "first_layer_acceleration_over_raft", "first_layer_bed_temperature", + "first_layer_speed_over_raft", "gcode_comments", "gcode_label_objects", "infill_acceleration", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index b5c1cbeb33..2917a9a19d 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1152,6 +1152,15 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert; def->set_default_value(new ConfigOptionFloat(0)); + def = this->add("first_layer_acceleration_over_raft", coFloat); + def->label = L("First object layer over raft interface"); + def->tooltip = L("This is the acceleration your printer will use for first layer of object above raft interface. Set zero " + "to disable acceleration control for first layer of object above raft interface."); + def->sidetext = L("mm/s²"); + def->min = 0; + def->mode = comExpert; + def->set_default_value(new ConfigOptionFloat(0)); + def = this->add("first_layer_bed_temperature", coInts); def->label = L("First layer"); def->full_label = L("First layer bed temperature"); @@ -1194,6 +1203,16 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloatOrPercent(30, false)); + def = this->add("first_layer_speed_over_raft", coFloatOrPercent); + def->label = L("Speed of object first layer over raft interface"); + def->tooltip = L("If expressed as absolute value in mm/s, this speed will be applied to all the print moves " + "of the first object layer above raft interface, regardless of their type. If expressed as a percentage " + "(for example: 40%) it will scale the default speeds."); + def->sidetext = L("mm/s or %"); + def->min = 0; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloatOrPercent(30, false)); + def = this->add("first_layer_temperature", coInts); def->label = L("First layer"); def->full_label = L("First layer nozzle temperature"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index f5070c54d9..d7409d12ce 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -456,6 +456,8 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionBool, dont_support_bridges)) ((ConfigOptionFloat, elefant_foot_compensation)) ((ConfigOptionFloatOrPercent, extrusion_width)) + ((ConfigOptionFloat, first_layer_acceleration_over_raft)) + ((ConfigOptionFloatOrPercent, first_layer_speed_over_raft)) ((ConfigOptionBool, infill_only_where_needed)) // Force the generation of solid shells between adjacent materials/volumes. ((ConfigOptionBool, interface_shells)) diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 72584e9389..d4920d8364 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -312,7 +312,8 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) toggle_field("support_material_speed", have_support_material || have_brim || have_skirt); toggle_field("raft_contact_distance", have_raft && !have_support_soluble); - toggle_field("raft_expansion", have_raft); + for (auto el : { "raft_expansion", "first_layer_acceleration_over_raft", "first_layer_speed_over_raft" }) + toggle_field(el, have_raft); bool has_ironing = config->opt_bool("ironing"); for (auto el : { "ironing_type", "ironing_flowrate", "ironing_spacing", "ironing_speed" }) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 6bd295fdc9..86089f729e 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1565,12 +1565,14 @@ void TabPrint::build() optgroup = page->new_optgroup(L("Modifiers")); optgroup->append_single_option_line("first_layer_speed"); + optgroup->append_single_option_line("first_layer_speed_over_raft"); optgroup = page->new_optgroup(L("Acceleration control (advanced)")); optgroup->append_single_option_line("perimeter_acceleration"); optgroup->append_single_option_line("infill_acceleration"); optgroup->append_single_option_line("bridge_acceleration"); optgroup->append_single_option_line("first_layer_acceleration"); + optgroup->append_single_option_line("first_layer_acceleration_over_raft"); optgroup->append_single_option_line("default_acceleration"); optgroup = page->new_optgroup(L("Autospeed (advanced)")); From d7bb4c36f58dfb46834919a6625ea7637f374954 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 1 Sep 2021 09:34:07 +0200 Subject: [PATCH 08/82] Requires OpenGL 3.3 as a minimum to enable instanced rendering of seams and other options in preview --- src/slic3r/GUI/GCodeViewer.cpp | 2 +- src/slic3r/GUI/GLShadersManager.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 732403b03e..ad2e6e9737 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -807,7 +807,7 @@ void GCodeViewer::render() case EMoveType::Unretract: case EMoveType::Seam: { #if ENABLE_SEAMS_USING_MODELS - if (wxGetApp().is_gl_version_greater_or_equal_to(3, 1)) { + if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Model; buffer.shader = "gouraud_light_instanced"; buffer.model.model.init_from(diamond(16)); diff --git a/src/slic3r/GUI/GLShadersManager.cpp b/src/slic3r/GUI/GLShadersManager.cpp index c93f22f469..edbe2bb46d 100644 --- a/src/slic3r/GUI/GLShadersManager.cpp +++ b/src/slic3r/GUI/GLShadersManager.cpp @@ -39,7 +39,7 @@ std::pair GLShadersManager::init() valid &= append_shader("printbed", { "printbed.vs", "printbed.fs" }); // used to render options in gcode preview #if ENABLE_SEAMS_USING_MODELS - if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 1)) + if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) valid &= append_shader("gouraud_light_instanced", { "gouraud_light_instanced.vs", "gouraud_light_instanced.fs" }); else { #endif // ENABLE_SEAMS_USING_MODELS From 95c05aae3bb85b9da51e466578a0061c23e7881d Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 1 Sep 2021 09:54:59 +0200 Subject: [PATCH 09/82] Fixed typo which broke export of toolpaths to obj file --- src/slic3r/GUI/GCodeViewer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index ad2e6e9737..e6e391d370 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -1100,7 +1100,7 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const // save vertices to file fprintf(fp, "\n# vertices\n"); for (const Vec3f& v : out_vertices) { - fprintf(fp, "v %g %g %g\n", v.x(), v.y(), v.x()); + fprintf(fp, "v %g %g %g\n", v.x(), v.y(), v.z()); } // save normals to file From ab84da6c56767d9894eea925263966bdefdf0556 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 1 Sep 2021 11:08:08 +0200 Subject: [PATCH 10/82] Fix for #6803 - Illegal character in filename when STL opened direct from CAD app Follow-up to ea4e9b35a3e2084325fbaed4c5bedf310bcdef3e Win32 specific: Substitute slashes to back slashes in file paths when loading model files (STLs, 3MFS ...) --- src/slic3r/GUI/GUI_ObjectList.cpp | 3 +-- src/slic3r/GUI/Plater.cpp | 36 +++++++++++++------------------ 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 82f03f51ac..737c840834 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1702,8 +1702,7 @@ void ObjectList::load_shape_object_from_gallery(const wxArrayString& input_files snapshot_label += ", " + wxString::FromUTF8(paths[i].filename().string().c_str()); take_snapshot(snapshot_label); - std::vector res = wxGetApp().plater()->load_files(paths, true, false); - if (!res.empty()) + if (! wxGetApp().plater()->load_files(paths, true, false).empty()) wxGetApp().mainframe->update_title(); } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 743f275782..98eb73c896 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2221,7 +2221,14 @@ std::vector Plater::priv::load_files(const std::vector& input_ std::vector obj_idxs; for (size_t i = 0; i < input_files.size(); ++i) { +#ifdef _WIN32 + auto path = input_files[i]; + // On Windows, we swap slashes to back slashes, see GH #6803 as read_from_file() does not understand slashes on Windows thus it assignes full path to names of loaded objects. + path.make_preferred(); +#else // _WIN32 + // Don't make a copy on Posix. Slash is a path separator, back slashes are not accepted as a substitute. const auto &path = input_files[i]; +#endif // _WIN32 const auto filename = path.filename(); dlg.Update(static_cast(100.0f * static_cast(i) / static_cast(input_files.size())), _L("Loading file") + ": " + from_path(filename)); dlg.Fit(); @@ -2336,9 +2343,7 @@ std::vector Plater::priv::load_files(const std::vector& input_ else { model = Slic3r::Model::read_from_file(path.string(), nullptr, nullptr, only_if(load_config, Model::LoadAttribute::CheckVersion)); for (auto obj : model.objects) - if (obj->name.empty() || - obj->name.find_first_of("/") != std::string::npos) // When file is imported from Fusion360 the path containes "/" instead of "\\" (see https://github.com/prusa3d/PrusaSlicer/issues/6803) - // But read_from_file doesn't support that direction separator and as a result object name containes full path + if (obj->name.empty()) obj->name = fs::path(obj->input_file).filename().string(); } } catch (const ConfigurationError &e) { @@ -2457,7 +2462,7 @@ std::vector Plater::priv::load_files(const std::vector& input_ } if (load_model) { - wxGetApp().app_config->update_skein_dir(input_files[input_files.size() - 1].parent_path().string()); + wxGetApp().app_config->update_skein_dir(input_files[input_files.size() - 1].parent_path().make_preferred().string()); // XXX: Plater.pm had @loaded_files, but didn't seem to fill them with the filenames... statusbar()->set_status_text(_L("Loaded")); } @@ -4787,10 +4792,7 @@ void Plater::load_project(const wxString& filename) p->reset(); - std::vector input_paths; - input_paths.push_back(into_path(filename)); - - if (! load_files(input_paths).empty()) { + if (! load_files({ into_path(filename) }).empty()) { // At least one file was loaded. p->set_project_filename(filename); reset_project_dirty_initial_presets(); @@ -4807,7 +4809,7 @@ void Plater::add_model(bool imperial_units/* = false*/) std::vector paths; for (const auto &file : input_files) - paths.push_back(into_path(file)); + paths.emplace_back(into_path(file)); wxString snapshot_label; assert(! paths.empty()); @@ -4840,12 +4842,8 @@ void Plater::extract_config_from_project() wxString input_file; wxGetApp().load_project(this, input_file); - if (input_file.empty()) - return; - - std::vector input_paths; - input_paths.push_back(into_path(input_file)); - load_files(input_paths, false, true); + if (! input_file.empty()) + load_files({ into_path(input_file) }, false, true); } void Plater::load_gcode() @@ -5076,15 +5074,11 @@ bool Plater::load_files(const wxArrayString& filenames) } case LoadType::LoadGeometry: { Plater::TakeSnapshot snapshot(this, _L("Import Object")); - std::vector in_paths; - in_paths.emplace_back(*it); - load_files(in_paths, true, false); + load_files({ *it }, true, false); break; } case LoadType::LoadConfig: { - std::vector in_paths; - in_paths.emplace_back(*it); - load_files(in_paths, false, true); + load_files({ *it }, false, true); break; } case LoadType::Unknown : { From 73e8f5aed2cccb17c6dee29bd91f6636882be7a4 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 1 Sep 2021 12:58:25 +0200 Subject: [PATCH 11/82] Supress desktop integration of gcode viewer at ChromeOS --- src/slic3r/GUI/DesktopIntegrationDialog.cpp | 91 +++++++++++---------- 1 file changed, 49 insertions(+), 42 deletions(-) diff --git a/src/slic3r/GUI/DesktopIntegrationDialog.cpp b/src/slic3r/GUI/DesktopIntegrationDialog.cpp index 9351219355..24552ec585 100644 --- a/src/slic3r/GUI/DesktopIntegrationDialog.cpp +++ b/src/slic3r/GUI/DesktopIntegrationDialog.cpp @@ -382,40 +382,44 @@ void DesktopIntegrationDialog::perform_desktop_integration() app_config->set("desktop_integration_app_path", GUI::format("%1%/applications/PrusaSlicer%2%.desktop", target_dir_desktop, version_suffix)); // Repeat for Gcode viewer - use same paths as for slicer files - // Icon - if (!target_dir_icons.empty()) - { - std::string icon_path = GUI::format("%1%/icons/PrusaSlicer-gcodeviewer_192px.png",resources_dir()); - std::string dest_path = GUI::format("%1%/icons/%2%PrusaSlicer-gcodeviewer%3%.png", target_dir_icons, icon_theme_path, version_suffix); - if (copy_icon(icon_path, dest_path)) - // save path to icon - app_config->set("desktop_integration_icon_viewer_path", dest_path); - else - BOOST_LOG_TRIVIAL(error) << "Copying Gcode Viewer icon to icons directory failed."; - } + // Do NOT add gcode viewer desktop file on ChromeOS + if (platform_flavor() != PlatformFlavor::LinuxOnChromium) { + // Icon + if (!target_dir_icons.empty()) + { + std::string icon_path = GUI::format("%1%/icons/PrusaSlicer-gcodeviewer_192px.png",resources_dir()); + std::string dest_path = GUI::format("%1%/icons/%2%PrusaSlicer-gcodeviewer%3%.png", target_dir_icons, icon_theme_path, version_suffix); + if (copy_icon(icon_path, dest_path)) + // save path to icon + app_config->set("desktop_integration_icon_viewer_path", dest_path); + else + BOOST_LOG_TRIVIAL(error) << "Copying Gcode Viewer icon to icons directory failed."; + } - // Desktop file - std::string desktop_file = GUI::format( - "[Desktop Entry]\n" - "Name=Prusa Gcode Viewer%1%\n" - "GenericName=3D Printing Software\n" - "Icon=PrusaSlicer-gcodeviewer%2%\n" - "Exec=\"%3%\" --gcodeviewer %%F\n" - "Terminal=false\n" - "Type=Application\n" - "MimeType=text/x.gcode;\n" - "Categories=Graphics;3DGraphics;\n" - "Keywords=3D;Printing;Slicer;\n" - "StartupNotify=false\n", name_suffix, version_suffix, excutable_path); + // Desktop file + std::string desktop_file = GUI::format( + "[Desktop Entry]\n" + "Name=Prusa Gcode Viewer%1%\n" + "GenericName=3D Printing Software\n" + "Icon=PrusaSlicer-gcodeviewer%2%\n" + "Exec=\"%3%\" --gcodeviewer %%F\n" + "Terminal=false\n" + "Type=Application\n" + "MimeType=text/x.gcode;\n" + "Categories=Graphics;3DGraphics;\n" + "Keywords=3D;Printing;Slicer;\n" + "StartupNotify=false\n", name_suffix, version_suffix, excutable_path); - std::string desktop_path = GUI::format("%1%/applications/PrusaSlicerGcodeViewer%2%.desktop", target_dir_desktop, version_suffix); - if (create_desktop_file(desktop_path, desktop_file)) - // save path to desktop file - app_config->set("desktop_integration_app_viewer_path", desktop_path); - else { - BOOST_LOG_TRIVIAL(error) << "Performing desktop integration failed - could not create Gcodeviewer desktop file"; - show_error(nullptr, _L("Performing desktop integration failed - could not create Gcodeviewer desktop file. PrusaSlicer desktop file was probably created successfully.")); + std::string desktop_path = GUI::format("%1%/applications/PrusaSlicerGcodeViewer%2%.desktop", target_dir_desktop, version_suffix); + if (create_desktop_file(desktop_path, desktop_file)) + // save path to desktop file + app_config->set("desktop_integration_app_viewer_path", desktop_path); + else { + BOOST_LOG_TRIVIAL(error) << "Performing desktop integration failed - could not create Gcodeviewer desktop file"; + show_error(nullptr, _L("Performing desktop integration failed - could not create Gcodeviewer desktop file. PrusaSlicer desktop file was probably created successfully.")); + } } + wxGetApp().plater()->get_notification_manager()->push_notification(NotificationType::DesktopIntegrationSuccess); } void DesktopIntegrationDialog::undo_desktop_intgration() @@ -433,17 +437,20 @@ void DesktopIntegrationDialog::undo_desktop_intgration() BOOST_LOG_TRIVIAL(debug) << "removing " << path; std::remove(path.c_str()); } - // gcode viwer .desktop - path = std::string(app_config->get("desktop_integration_app_viewer_path")); - if (!path.empty()) { - BOOST_LOG_TRIVIAL(debug) << "removing " << path; - std::remove(path.c_str()); - } - // gcode viewer icon - path = std::string(app_config->get("desktop_integration_icon_viewer_path")); - if (!path.empty()) { - BOOST_LOG_TRIVIAL(debug) << "removing " << path; - std::remove(path.c_str()); + // No gcode viewer at ChromeOS + if (platform_flavor() != PlatformFlavor::LinuxOnChromium) { + // gcode viewer .desktop + path = std::string(app_config->get("desktop_integration_app_viewer_path")); + if (!path.empty()) { + BOOST_LOG_TRIVIAL(debug) << "removing " << path; + std::remove(path.c_str()); + } + // gcode viewer icon + path = std::string(app_config->get("desktop_integration_icon_viewer_path")); + if (!path.empty()) { + BOOST_LOG_TRIVIAL(debug) << "removing " << path; + std::remove(path.c_str()); + } } wxGetApp().plater()->get_notification_manager()->push_notification(NotificationType::UndoDesktopIntegrationSuccess); } From 229cf4b8b6aa341ca6ba2602b4cdc1e69d93d9ad Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 1 Sep 2021 10:25:46 +0200 Subject: [PATCH 12/82] Open menubar item by item index. Possible to call as hint notification hyperlink --- resources/data/hints.ini | 18 ++++++++---------- src/slic3r/GUI/HintNotification.cpp | 13 ++++++++----- src/slic3r/GUI/MainFrame.cpp | 21 +++++++++++++++++++++ src/slic3r/GUI/MainFrame.hpp | 2 ++ 4 files changed, 39 insertions(+), 15 deletions(-) diff --git a/resources/data/hints.ini b/resources/data/hints.ini index 95060f9ec6..af2e09209b 100644 --- a/resources/data/hints.ini +++ b/resources/data/hints.ini @@ -39,6 +39,10 @@ # Open gallery (no aditional var) # hypertext_type = gallery # +#Open top menubar item +#hypertext_menubar_menu_id = 4 (0 - 5, index of menu from left: File = 0, Edit = 1...) +#hypertext_menubar_item_id = 1 (index of item, starting at 0, Including separators! In Window: 0 = Plater Tab, 1 = SEPARATOR, 2 = Print Setting Tab...) +# # # Each notification can have disabled and enabled modes and techs - divided by ; and space # enabled_tags = ... @@ -77,18 +81,15 @@ hypertext_plater_item = arrange [hint:Negative volume] text = Negative volume\nDid you know that you can subtract one mesh from another using the Negative volume modifier? That way you can, for example, create easily resizable holes directly in PrusaSlicer. Read more in the documentation. (Requires Advanced or Expert mode.) -hypertext_type = link documentation_link = https://help.prusa3d.com/en/article/negative-volume_238503 disabled_tags = SLA; simple [hint:Simplify mesh] text = Simplify mesh\nDid you know that you can reduce the number of triangles in a mesh using the Simplify mesh feature? Right-click the model and select Simplify model. Read more in the documentation. -hypertext_type = link documentation_link = https://help.prusa3d.com/en/article/simplify-mesh_238941 [hint:Reload from disk] text = Reload from disk\nDid you know that if you created a newer version of your model, you can simply reload it in PrusaSlicer? Right-click the model in the 3D view and choose Reload from disk. Read more in the documentation. -hypertext_type = link documentation_link = https://help.prusa3d.com/en/article/reload-from-disk_120427 [hint:Hiding sidebar] @@ -131,7 +132,6 @@ hypertext_plater_item = undo [hint:Different layer height for each model] text = Different layer height for each model\nDid you know that you can print each model on the plater with a different layer height? Right-click the model in the 3D view, choose Layers and Perimeters and adjust the values in the right panel. Read more in the documentation. -hypertext_type = link documentation_link= https://help.prusa3d.com/en/article/per-model-settings_1674 disabled_tags = SLA @@ -168,7 +168,6 @@ text = Load config from G-code\nDid you know that you can use File-Import Config [hint:Ironing] text = Ironing\nDid you know that you can smooth top surfaces of prints using Ironing? The nozzle will run a special second infill phase at the same layer to fill in holes and flatten any lifted plastic. Read more in the documentation. (Requires Advanced or Expert mode.) -hypertext_type = link documentation_link = https://help.prusa3d.com/en/article/ironing_177488 disabled_tags = SLA; simple @@ -186,20 +185,20 @@ disabled_tags = SLA; simple [hint:Insert Pause] text = Insert Pause\nDid you know that you can schedule the print to pause at a specific layer? Right-click the layer slider in the Preview and select Add pause print (M601). This can be used to insert magnets, weights or nuts into your prints. Read more in the documentation. -hypertext_type = link documentation_link = https://help.prusa3d.com/en/article/insert-pause-or-custom-g-code-at-layer_120490#insert-pause-at-layer disabled_tags = SLA [hint:Insert Custom G-code] text = Insert Custom G-code\nDid you know that you can insert a custom G-code at a specific layer? Right-click the layer in the Preview and select Add custom G-code. With this function you can, for example, create a temperature tower. Read more in the documentation. -hypertext_type = link documentation_link = https://help.prusa3d.com/en/article/insert-pause-or-custom-g-code-at-layer_120490#insert-custom-g-code-at-layer disabled_tags = SLA [hint:Configuration snapshots] -text = Configuration snapshots\nDid you know that roll back to a complete backup of all system and user profiles? You can view and move back and forth between snapshots using the Configuration - Configuration snapshots menu. Read more in the documentation. -hypertext_type = link +text = Configuration snapshots\nDid you know that roll back to a complete backup of all system and user profiles? You can view and move back and forth between snapshots using the Configuration - Configuration snapshots menu. documentation_link = https://help.prusa3d.com/en/article/configuration-snapshots_1776 +hypertext_type = menubar +hypertext_menubar_menu_id = 4 +hypertext_menubar_item_id = 1 [hint:Minimum wall thickness] text = Minimum wall thickness\nDid you know that instead of the number of top and bottom layers, you can define theMinimum shell thicknessin millimeters? This feature is especially useful when using the variable layer height function. @@ -216,7 +215,6 @@ hypertext_preferences_page = 2 [hint:Adaptive infills] text = Adaptive infills\nDid you know that you can use the Adaptive cubic and Support cubic infills to decrease the print time and lower the filament consumption? Read more in the documentation. -hypertext_type = link documentation_link = https://help.prusa3d.com/en/article/infill-patterns_177130 disabled_tags = SLA diff --git a/src/slic3r/GUI/HintNotification.cpp b/src/slic3r/GUI/HintNotification.cpp index ead7a8f29a..0cdf441c03 100644 --- a/src/slic3r/GUI/HintNotification.cpp +++ b/src/slic3r/GUI/HintNotification.cpp @@ -4,6 +4,7 @@ #include "I18N.hpp" #include "GUI_ObjectList.hpp" #include "GLCanvas3D.hpp" +#include "MainFrame.hpp" #include "libslic3r/AppConfig.hpp" #include "libslic3r/Utils.hpp" #include "libslic3r/Config.hpp" @@ -57,10 +58,6 @@ inline void push_style_color(ImGuiCol idx, const ImVec4& col, bool fading_out, f ImGui::PushStyleColor(idx, col); } - - - - void write_used_binary(const std::vector& ids) { boost::filesystem::ofstream file((boost::filesystem::path(data_dir()) / "cache" / "hints.cereal"), std::ios::binary); @@ -379,7 +376,13 @@ void HintDatabase::load_hints_from_file(const boost::filesystem::path& path) HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, false, documentation_link, []() { // Deselect all objects, otherwise gallery wont show. wxGetApp().plater()->canvas3D()->deselect_all(); - wxGetApp().obj_list()->load_shape_object_from_gallery(); } }; + wxGetApp().obj_list()->load_shape_object_from_gallery(); } + }; + m_loaded_hints.emplace_back(hint_data); + } else if (dict["hypertext_type"] == "menubar") { + int menu = std::atoi(dict["hypertext_menubar_menu_id"].c_str()); + int item = std::atoi(dict["hypertext_menubar_item_id"].c_str()); + HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, true, documentation_link, [menu, item]() { wxGetApp().mainframe->open_menubar_item(menu, item); } }; m_loaded_hints.emplace_back(hint_data); } } else { diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index c6d176fd65..d7c0a25b2b 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -1479,6 +1479,27 @@ void MainFrame::init_menubar_as_editor() update_menubar(); } +void MainFrame::open_menubar_item(int menu_index, int item_index) +{ + if (m_menubar == nullptr) + return; + wxMenu* menu = m_menubar->GetMenu(menu_index); + if (menu == nullptr) { + BOOST_LOG_TRIVIAL(error) << "Mainframe open_menubar_item function couldn't find menu: " << menu_index; + return; + } + wxMenuItemList items = menu->GetMenuItems(); + if (items.size() <= item_index) { + BOOST_LOG_TRIVIAL(error) << "Mainframe open_menubar_item function couldn't find item: " << item_index; + return; + } + wxMenuItem* item = items[item_index]; + if (item == nullptr) { + BOOST_LOG_TRIVIAL(error) << "Mainframe open_menubar_item function couldn't find item: " << item_index; + return; + } + wxPostEvent((wxEvtHandler*)menu, wxCommandEvent(wxEVT_MENU, item->GetId())); +} void MainFrame::init_menubar_as_gcodeviewer() { wxMenu* fileMenu = new wxMenu; diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index aced5efbe4..e8d3c67a72 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -158,6 +158,8 @@ public: void init_menubar_as_editor(); void init_menubar_as_gcodeviewer(); void update_menubar(); + // Open item in menu by menu and item index (visible order of items including separators) + void open_menubar_item(int menu_index, int item_index); #ifdef _WIN32 void show_tabs_menu(bool show); #endif From d0e37aada876785aae029c46d6e08566241af850 Mon Sep 17 00:00:00 2001 From: rtyr <36745189+rtyr@users.noreply.github.com> Date: Wed, 1 Sep 2021 13:36:13 +0200 Subject: [PATCH 13/82] Updated raft_contact_distance values. --- resources/profiles/PrusaResearch.ini | 33 ++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/resources/profiles/PrusaResearch.ini b/resources/profiles/PrusaResearch.ini index 835e552a18..47a3883b4b 100644 --- a/resources/profiles/PrusaResearch.ini +++ b/resources/profiles/PrusaResearch.ini @@ -213,6 +213,7 @@ support_material_angle = 0 support_material_buildplate_only = 0 support_material_enforce_layers = 0 support_material_contact_distance = 0.2 +raft_contact_distance = 0.2 support_material_interface_contact_loops = 0 support_material_interface_layers = 2 support_material_interface_spacing = 0.2 @@ -432,6 +433,7 @@ solid_infill_speed = 30 support_material_extrusion_width = 0.33 support_material_spacing = 1.5 support_material_contact_distance = 0.15 +raft_contact_distance = 0.15 perimeter_acceleration = 300 perimeter_speed = 30 perimeters = 3 @@ -461,6 +463,7 @@ layer_height = 0.1 perimeter_acceleration = 800 top_solid_layers = 9 support_material_contact_distance = 0.17 +raft_contact_distance = 0.17 [print:*0.15mm*] inherits = *common* @@ -613,6 +616,7 @@ solid_infill_extrusion_width = 0.7 top_infill_extrusion_width = 0.45 support_material_extrusion_width = 0.37 support_material_contact_distance = 0.1 +raft_contact_distance = 0.2 top_solid_infill_speed = 40 thick_bridges = 1 @@ -669,6 +673,7 @@ small_perimeter_speed = 15 solid_infill_speed = 20 support_material_speed = 20 support_material_contact_distance = 0.07 +raft_contact_distance = 0.07 [print:0.10mm DETAIL @0.25 nozzle] inherits = *0.10mm*; *0.25nozzle* @@ -683,6 +688,7 @@ small_perimeter_speed = 15 solid_infill_speed = 40 top_solid_infill_speed = 30 support_material_contact_distance = 0.07 +raft_contact_distance = 0.07 [print:0.15mm OPTIMAL @0.25 nozzle] inherits = *0.15mm*; *0.25nozzle* @@ -698,6 +704,7 @@ small_perimeter_speed = 15 solid_infill_speed = 40 top_solid_infill_speed = 30 support_material_contact_distance = 0.08 +raft_contact_distance = 0.08 ## MK2 - 0.6mm nozzle @@ -923,6 +930,7 @@ solid_infill_extrusion_width = 0.5 top_infill_extrusion_width = 0.45 support_material_extrusion_width = 0.38 support_material_contact_distance = 0.2 +raft_contact_distance = 0.2 ## MK3 - MMU2 specific [print:0.15mm SOLUBLE FULL @MK3] @@ -977,6 +985,7 @@ compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and fill_pattern = grid fill_density = 20% support_material_contact_distance = 0.07 +raft_contact_distance = 0.07 [print:0.07mm ULTRADETAIL @0.25 nozzle MK3] inherits = *0.07mm*; *0.25nozzle*; *MK3* @@ -988,6 +997,7 @@ top_solid_infill_speed = 20 fill_pattern = grid fill_density = 20% support_material_contact_distance = 0.07 +raft_contact_distance = 0.07 [print:0.10mm DETAIL @0.25 nozzle MK3] inherits = *0.10mm*; *0.25nozzleMK3*; *MK3* @@ -995,6 +1005,7 @@ compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and fill_pattern = grid fill_density = 20% support_material_contact_distance = 0.07 +raft_contact_distance = 0.07 [print:0.15mm QUALITY @0.25 nozzle MK3] inherits = *0.15mm*; *0.25nozzleMK3*; *MK3* @@ -1002,6 +1013,7 @@ compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and fill_pattern = grid fill_density = 20% support_material_contact_distance = 0.08 +raft_contact_distance = 0.08 ## MK3 - 0.6mm nozzle @@ -1016,6 +1028,7 @@ perimeter_speed = 45 solid_infill_speed = 70 top_solid_infill_speed = 45 support_material_contact_distance = 0.22 +raft_contact_distance = 0.22 bridge_flow_ratio = 1 [print:0.20mm DETAIL @0.6 nozzle MK3] @@ -1029,6 +1042,7 @@ perimeter_speed = 45 solid_infill_speed = 70 top_solid_infill_speed = 45 support_material_contact_distance = 0.22 +raft_contact_distance = 0.22 bridge_flow_ratio = 1 [print:0.30mm QUALITY @0.6 nozzle MK3] @@ -1042,6 +1056,7 @@ perimeter_speed = 45 solid_infill_speed = 70 top_solid_infill_speed = 45 support_material_contact_distance = 0.25 +raft_contact_distance = 0.25 bridge_flow_ratio = 1 [print:0.35mm SPEED @0.6 nozzle MK3] @@ -1059,6 +1074,7 @@ perimeter_extrusion_width = 0.68 infill_extrusion_width = 0.68 solid_infill_extrusion_width = 0.68 support_material_contact_distance = 0.25 +raft_contact_distance = 0.25 bridge_flow_ratio = 0.95 [print:0.40mm DRAFT @0.6 nozzle MK3] @@ -1076,6 +1092,7 @@ perimeter_extrusion_width = 0.68 infill_extrusion_width = 0.68 solid_infill_extrusion_width = 0.68 support_material_contact_distance = 0.25 +raft_contact_distance = 0.25 bridge_flow_ratio = 0.95 ## MK3 - MMU2 specific @@ -1255,6 +1272,7 @@ solid_infill_extrusion_width = 0.45 top_infill_extrusion_width = 0.4 support_material_xy_spacing = 60% support_material_contact_distance = 0.2 +raft_contact_distance = 0.2 # MINI - 0.25mm nozzle @@ -1265,6 +1283,7 @@ fill_pattern = grid fill_density = 20% support_material_speed = 30 support_material_contact_distance = 0.07 +raft_contact_distance = 0.07 [print:0.07mm ULTRADETAIL @0.25 nozzle MINI] inherits = *0.07mm*; *0.25nozzle*; *MINI* @@ -1276,6 +1295,7 @@ top_solid_infill_speed = 20 fill_pattern = grid fill_density = 20% support_material_contact_distance = 0.07 +raft_contact_distance = 0.07 [print:0.10mm DETAIL @0.25 nozzle MINI] inherits = *0.10mm*; *0.25nozzleMINI*; *MINI* @@ -1283,6 +1303,7 @@ compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and fill_pattern = grid fill_density = 20% support_material_contact_distance = 0.07 +raft_contact_distance = 0.07 [print:0.15mm QUALITY @0.25 nozzle MINI] inherits = *0.15mm*; *0.25nozzleMINI*; *MINI* @@ -1290,6 +1311,7 @@ compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and fill_pattern = grid fill_density = 20% support_material_contact_distance = 0.08 +raft_contact_distance = 0.08 # MINI - 0.6mm nozzle @@ -1305,6 +1327,7 @@ top_solid_infill_speed = 45 infill_extrusion_width = 0.65 solid_infill_extrusion_width = 0.65 support_material_contact_distance = 0.22 +raft_contact_distance = 0.22 bridge_flow_ratio = 1 [print:0.20mm DETAIL @0.6 nozzle MINI] @@ -1319,6 +1342,7 @@ top_solid_infill_speed = 45 infill_extrusion_width = 0.65 solid_infill_extrusion_width = 0.65 support_material_contact_distance = 0.22 +raft_contact_distance = 0.22 bridge_flow_ratio = 1 [print:0.30mm QUALITY @0.6 nozzle MINI] @@ -1333,6 +1357,7 @@ top_solid_infill_speed = 45 external_perimeter_extrusion_width = 0.68 perimeter_extrusion_width = 0.68 support_material_contact_distance = 0.25 +raft_contact_distance = 0.25 bridge_flow_ratio = 1 [print:0.35mm SPEED @0.6 nozzle MINI] @@ -1347,6 +1372,7 @@ top_solid_infill_speed = 45 external_perimeter_extrusion_width = 0.68 perimeter_extrusion_width = 0.68 support_material_contact_distance = 0.25 +raft_contact_distance = 0.25 bridge_flow_ratio = 0.95 [print:0.40mm DRAFT @0.6 nozzle MINI] @@ -1363,6 +1389,7 @@ perimeter_extrusion_width = 0.68 infill_extrusion_width = 0.68 solid_infill_extrusion_width = 0.68 support_material_contact_distance = 0.25 +raft_contact_distance = 0.25 bridge_flow_ratio = 0.95 # MINI - 0.8mm nozzle @@ -1398,6 +1425,7 @@ infill_speed = 40 solid_infill_speed = 40 support_material_speed = 35 support_material_contact_distance = 0.25 +raft_contact_distance = 0.2 top_solid_infill_speed = 28 external_perimeter_extrusion_width = 1 perimeter_extrusion_width = 1 @@ -6522,7 +6550,7 @@ start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 end_gcode = G1 E-1 F2100 ; retract\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+2, max_print_height)} F720 ; Move print head up{endif}\nG1 X178 Y178 F4200 ; park print head\n{if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+30, max_print_height)} F720 ; Move print head further up{endif}\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nM221 S100 ; reset flow\nM900 K0 ; reset LA\nM84 ; disable motors printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MINI\n extruder_colour = -color_change_gcode = M600\nG1 E0.8 F1500 ; prime after color change +color_change_gcode = M600 [printer:Original Prusa MINI & MINI+ 0.25 nozzle] inherits = Original Prusa MINI & MINI+ @@ -6536,7 +6564,6 @@ retract_length = 3 retract_lift = 0.15 retract_before_travel = 1 start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S170 ; set extruder temp for bed leveling\nM140 S[first_layer_bed_temperature] ; set bed temp\nM109 R170 ; wait for bed leveling temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM204 T1250 ; set travel acceleration\nG28 ; home all without mesh bed level\nG29 ; mesh bed leveling \nM204 T[machine_max_acceleration_travel] ; restore travel acceleration\nM104 S[first_layer_temperature] ; set extruder temp\nG92 E0\nG1 Y-2 X179 F2400\nG1 Z3 F720\nM109 S[first_layer_temperature] ; wait for extruder temp\n\n; intro line\nG1 X170 F1000\nG1 Z0.2 F720\nG1 X110 E8 F600\nG1 X40 E10 F400\nG92 E0\n\nM221 S95 ; set flow -color_change_gcode = M600\nG1 E0.6 F1500 ; prime after color change [printer:Original Prusa MINI & MINI+ 0.6 nozzle] inherits = Original Prusa MINI & MINI+ @@ -6548,7 +6575,6 @@ min_layer_height = 0.15 default_print_profile = 0.30mm QUALITY @0.6 nozzle MINI retract_length = 3.5 retract_before_travel = 1.5 -color_change_gcode = M600\nG1 E1 F1500 ; prime after color change [printer:Original Prusa MINI & MINI+ 0.8 nozzle] inherits = Original Prusa MINI & MINI+ @@ -6560,7 +6586,6 @@ default_print_profile = 0.40mm QUALITY @0.8 nozzle MINI default_filament_profile = Prusament PLA @0.8 nozzle retract_length = 3.5 retract_before_travel = 1.5 -color_change_gcode = M600\nG1 E1.2 F1500 ; prime after color change [printer:Original Prusa SL1] printer_technology = SLA From 20453f412b557ba9e75388077dca6bf6f3497176 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 1 Sep 2021 13:48:07 +0200 Subject: [PATCH 14/82] Check unsaved changes before opening of the ConfigWizard --- src/libslic3r/PresetBundle.cpp | 1 - src/slic3r/GUI/GUI_App.cpp | 13 ++++++++----- src/slic3r/GUI/GUI_App.hpp | 2 +- src/slic3r/GUI/PresetComboBoxes.cpp | 3 +-- src/slic3r/GUI/UnsavedChangesDialog.cpp | 4 ++-- src/slic3r/GUI/UnsavedChangesDialog.hpp | 2 +- 6 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/libslic3r/PresetBundle.cpp b/src/libslic3r/PresetBundle.cpp index 9ac8864f91..63f9f27f22 100644 --- a/src/libslic3r/PresetBundle.cpp +++ b/src/libslic3r/PresetBundle.cpp @@ -240,7 +240,6 @@ PresetsConfigSubstitutions PresetBundle::load_presets(AppConfig &config, Forward if (! errors_cummulative.empty()) throw Slic3r::RuntimeError(errors_cummulative); - // ysToDo : set prefered filament or sla_material (relates to print technology) and force o use of preffered printer model if it was added this->load_selections(config, preferred_selection); return substitutions; diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 102026a0cb..3d5e56b462 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -2082,10 +2082,10 @@ std::vector> GUI_App::get_selected_presets( // This is called when closing the application, when loading a config file or when starting the config wizard // to notify the user whether he is aware that some preset changes will be lost. -bool GUI_App::check_and_save_current_preset_changes(const wxString& header) +bool GUI_App::check_and_save_current_preset_changes(const wxString& header, const wxString& caption) { if (/*this->plater()->model().objects.empty() && */has_current_preset_changes()) { - UnsavedChangesDialog dlg(header); + UnsavedChangesDialog dlg(header, caption); if (wxGetApp().app_config->get("default_action_on_close_application") == "none" && dlg.ShowModal() == wxID_CANCEL) return false; @@ -2334,10 +2334,13 @@ bool GUI_App::run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage { wxCHECK_MSG(mainframe != nullptr, false, "Internal error: Main frame not created / null"); - if (reason == ConfigWizard::RR_USER) - if (PresetUpdater::UpdateResult result = preset_updater->config_update(app_config->orig_version(), PresetUpdater::UpdateParams::FORCED_BEFORE_WIZARD); - result == PresetUpdater::R_ALL_CANCELED) + if (reason == ConfigWizard::RR_USER) { + wxString header = _L("Updates to Configuration Wizard may cause an another preset selection and lost of preset modification as a result.\n" + "So, check unsaved changes and save them if necessary.") + "\n"; + if (!check_and_save_current_preset_changes(header, _L("ConfigWizard is opening")) || + preset_updater->config_update(app_config->orig_version(), PresetUpdater::UpdateParams::FORCED_BEFORE_WIZARD) == PresetUpdater::R_ALL_CANCELED) return false; + } if (! m_wizard) { wxBusyCursor wait; diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 1d8c2fcf75..a088e10d4c 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -247,7 +247,7 @@ public: bool has_current_preset_changes() const; void update_saved_preset_from_current_preset(); std::vector> get_selected_presets() const; - bool check_and_save_current_preset_changes(const wxString& header = wxString()); + bool check_and_save_current_preset_changes(const wxString& header = wxString(), const wxString& caption = wxString()); bool check_print_host_queue(); bool checked_tab(Tab* tab); void load_current_presets(bool check_printer_presets = true); diff --git a/src/slic3r/GUI/PresetComboBoxes.cpp b/src/slic3r/GUI/PresetComboBoxes.cpp index b8d4ead509..5da3594582 100644 --- a/src/slic3r/GUI/PresetComboBoxes.cpp +++ b/src/slic3r/GUI/PresetComboBoxes.cpp @@ -636,8 +636,7 @@ PlaterPresetComboBox::~PlaterPresetComboBox() static void run_wizard(ConfigWizard::StartPage sp) { - if (wxGetApp().check_and_save_current_preset_changes()) - wxGetApp().run_wizard(ConfigWizard::RR_USER, sp); + wxGetApp().run_wizard(ConfigWizard::RR_USER, sp); } void PlaterPresetComboBox::OnSelect(wxCommandEvent &evt) diff --git a/src/slic3r/GUI/UnsavedChangesDialog.cpp b/src/slic3r/GUI/UnsavedChangesDialog.cpp index 9fb8a1e642..2b63bc79b6 100644 --- a/src/slic3r/GUI/UnsavedChangesDialog.cpp +++ b/src/slic3r/GUI/UnsavedChangesDialog.cpp @@ -752,8 +752,8 @@ std::vector DiffViewCtrl::selected_options() // UnsavedChangesDialog //------------------------------------------ -UnsavedChangesDialog::UnsavedChangesDialog(const wxString& header) - : DPIDialog(static_cast(wxGetApp().mainframe), wxID_ANY, _L("PrusaSlicer is closing: Unsaved Changes"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) +UnsavedChangesDialog::UnsavedChangesDialog(const wxString& header, const wxString& caption/* = wxString()*/) + : DPIDialog(static_cast(wxGetApp().mainframe), wxID_ANY, (caption.IsEmpty() ? _L("PrusaSlicer is closing") : caption) + ": " + _L("Unsaved Changes"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { m_app_config_key = "default_action_on_close_application"; diff --git a/src/slic3r/GUI/UnsavedChangesDialog.hpp b/src/slic3r/GUI/UnsavedChangesDialog.hpp index 06838d9361..9667430334 100644 --- a/src/slic3r/GUI/UnsavedChangesDialog.hpp +++ b/src/slic3r/GUI/UnsavedChangesDialog.hpp @@ -263,7 +263,7 @@ class UnsavedChangesDialog : public DPIDialog std::vector> names_and_types; public: - UnsavedChangesDialog(const wxString& header); + UnsavedChangesDialog(const wxString& header, const wxString& caption = wxString()); UnsavedChangesDialog(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset); ~UnsavedChangesDialog() {} From 8ad109235b86ca6d3f8e65be03f4b26edaa198d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Wed, 1 Sep 2021 14:28:42 +0200 Subject: [PATCH 15/82] Added a missing include (GCC 11.1). --- src/slic3r/GUI/MainFrame.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index d7c0a25b2b..7d51985c57 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -14,6 +14,7 @@ #include #include +#include #include "libslic3r/Print.hpp" #include "libslic3r/Polygon.hpp" From 3b4d10656cb8626b539551c74cd50e0c925f2b94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Wed, 1 Sep 2021 14:32:34 +0200 Subject: [PATCH 16/82] Renamed 'Seed fill' to 'Smart fill'. --- .../GUI/Gizmos/GLGizmoMmuSegmentation.cpp | 37 +++++++++---------- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp | 20 +++++----- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp | 10 ++--- 3 files changed, 33 insertions(+), 34 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index a69319d3b6..a30ac377e8 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -124,13 +124,12 @@ bool GLGizmoMmuSegmentation::on_init() m_desc["sphere"] = _L("Sphere"); m_desc["pointer"] = _L("Pointer"); - m_desc["tool_type"] = _L("Tool type"); + m_desc["tool_type"] = _L("Tool type"); m_desc["tool_brush"] = _L("Brush"); - m_desc["tool_seed_fill"] = _L("Seed fill"); + m_desc["tool_smart_fill"] = _L("Smart fill"); m_desc["tool_bucket_fill"] = _L("Bucket fill"); - m_desc["seed_fill"] = _L("Seed fill"); - m_desc["seed_fill_angle"] = _L("Seed fill angle"); + m_desc["smart_fill_angle"] = _L("Smart fill angle"); init_extruders_data(); @@ -246,10 +245,10 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott const float clipping_slider_left = std::max(m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x, m_imgui->calc_text_size(m_desc.at("reset_direction")).x) + m_imgui->scaled(1.5f); const float cursor_slider_left = m_imgui->calc_text_size(m_desc.at("cursor_size")).x + m_imgui->scaled(1.f); - const float seed_fill_slider_left = m_imgui->calc_text_size(m_desc.at("seed_fill_angle")).x + m_imgui->scaled(1.f); + const float smart_fill_slider_left = m_imgui->calc_text_size(m_desc.at("smart_fill_angle")).x + m_imgui->scaled(1.f); - const float cursor_type_radio_circle = m_imgui->calc_text_size(m_desc["circle"]).x + m_imgui->scaled(2.5f); - const float cursor_type_radio_sphere = m_imgui->calc_text_size(m_desc["sphere"]).x + m_imgui->scaled(2.5f); + const float cursor_type_radio_circle = m_imgui->calc_text_size(m_desc["circle"]).x + m_imgui->scaled(2.5f); + const float cursor_type_radio_sphere = m_imgui->calc_text_size(m_desc["sphere"]).x + m_imgui->scaled(2.5f); const float cursor_type_radio_pointer = m_imgui->calc_text_size(m_desc["pointer"]).x + m_imgui->scaled(2.5f); const float button_width = m_imgui->calc_text_size(m_desc.at("remove_all")).x + m_imgui->scaled(1.f); @@ -259,9 +258,9 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott const float combo_label_width = std::max(m_imgui->calc_text_size(m_desc.at("first_color")).x, m_imgui->calc_text_size(m_desc.at("second_color")).x) + m_imgui->scaled(1.f); - const float tool_type_radio_brush = m_imgui->calc_text_size(m_desc["tool_brush"]).x + m_imgui->scaled(2.5f); + const float tool_type_radio_brush = m_imgui->calc_text_size(m_desc["tool_brush"]).x + m_imgui->scaled(2.5f); const float tool_type_radio_bucket_fill = m_imgui->calc_text_size(m_desc["tool_bucket_fill"]).x + m_imgui->scaled(2.5f); - const float tool_type_radio_seed_fill = m_imgui->calc_text_size(m_desc["tool_seed_fill"]).x + m_imgui->scaled(2.5f); + const float tool_type_radio_smart_fill = m_imgui->calc_text_size(m_desc["tool_smart_fill"]).x + m_imgui->scaled(2.5f); float caption_max = 0.f; float total_text_max = 0.; @@ -272,12 +271,12 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott caption_max += m_imgui->scaled(1.f); total_text_max += m_imgui->scaled(1.f); - float sliders_width = std::max(seed_fill_slider_left, std::max(cursor_slider_left, clipping_slider_left)); + float sliders_width = std::max(smart_fill_slider_left, std::max(cursor_slider_left, clipping_slider_left)); float window_width = minimal_slider_width + sliders_width; window_width = std::max(window_width, total_text_max); window_width = std::max(window_width, button_width); window_width = std::max(window_width, cursor_type_radio_circle + cursor_type_radio_sphere + cursor_type_radio_pointer); - window_width = std::max(window_width, tool_type_radio_brush + tool_type_radio_bucket_fill + tool_type_radio_seed_fill); + window_width = std::max(window_width, tool_type_radio_brush + tool_type_radio_bucket_fill + tool_type_radio_smart_fill); window_width = std::max(window_width, 2.f * buttons_width + m_imgui->scaled(1.f)); auto draw_text_with_caption = [this, &caption_max](const wxString &caption, const wxString &text) { @@ -321,7 +320,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott ImGui::AlignTextToFramePadding(); m_imgui->text(m_desc.at("tool_type")); - float tool_type_offset = (window_width - tool_type_radio_brush - tool_type_radio_bucket_fill - tool_type_radio_seed_fill + m_imgui->scaled(2.f)) / 2.f; + float tool_type_offset = (window_width - tool_type_radio_brush - tool_type_radio_bucket_fill - tool_type_radio_smart_fill + m_imgui->scaled(2.f)) / 2.f; ImGui::NewLine(); @@ -345,9 +344,9 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott } ImGui::SameLine(tool_type_offset + tool_type_radio_brush + m_imgui->scaled(0.f)); - ImGui::PushItemWidth(tool_type_radio_seed_fill); - if (m_imgui->radio_button(m_desc["tool_seed_fill"], m_tool_type == GLGizmoMmuSegmentation::ToolType::SEED_FILL)) { - m_tool_type = GLGizmoMmuSegmentation::ToolType::SEED_FILL; + ImGui::PushItemWidth(tool_type_radio_smart_fill); + if (m_imgui->radio_button(m_desc["tool_smart_fill"], m_tool_type == GLGizmoMmuSegmentation::ToolType::SMART_FILL)) { + m_tool_type = GLGizmoMmuSegmentation::ToolType::SMART_FILL; for (auto &triangle_selector : m_triangle_selectors) { triangle_selector->seed_fill_unselect_all_triangles(); triangle_selector->request_update_render_data(); @@ -362,7 +361,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott ImGui::EndTooltip(); } - ImGui::SameLine(tool_type_offset + tool_type_radio_brush + tool_type_radio_seed_fill + m_imgui->scaled(0.f)); + ImGui::SameLine(tool_type_offset + tool_type_radio_brush + tool_type_radio_smart_fill + m_imgui->scaled(0.f)); ImGui::PushItemWidth(tool_type_radio_bucket_fill); if (m_imgui->radio_button(m_desc["tool_bucket_fill"], m_tool_type == GLGizmoMmuSegmentation::ToolType::BUCKET_FILL)) { m_tool_type = GLGizmoMmuSegmentation::ToolType::BUCKET_FILL; @@ -458,14 +457,14 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott m_imgui->disabled_end(); ImGui::Separator(); - } else if(m_tool_type == ToolType::SEED_FILL) { - m_imgui->text(m_desc["seed_fill_angle"] + ":"); + } else if(m_tool_type == ToolType::SMART_FILL) { + m_imgui->text(m_desc["smart_fill_angle"] + ":"); ImGui::AlignTextToFramePadding(); std::string format_str = std::string("%.f") + I18N::translate_utf8("°", "Degree sign to use in the respective slider in MMU gizmo," "placed after the number with no whitespace in between."); ImGui::SameLine(sliders_width); ImGui::PushItemWidth(window_width - sliders_width); - if(m_imgui->slider_float("##seed_fill_angle", &m_seed_fill_angle, SeedFillAngleMin, SeedFillAngleMax, format_str.data())) + if(m_imgui->slider_float("##smart_fill_angle", &m_smart_fill_angle, SmartFillAngleMin, SmartFillAngleMax, format_str.data())) for (auto &triangle_selector : m_triangle_selectors) { triangle_selector->seed_fill_unselect_all_triangles(); triangle_selector->request_update_render_data(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index 9477b89c7e..155738b327 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -282,12 +282,12 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous : std::min(m_cursor_radius + CursorRadiusStep, CursorRadiusMax); m_parent.set_as_dirty(); return true; - } else if (m_tool_type == ToolType::SEED_FILL) { - m_seed_fill_angle = action == SLAGizmoEventType::MouseWheelDown ? std::max(m_seed_fill_angle - SeedFillAngleStep, SeedFillAngleMin) - : std::min(m_seed_fill_angle + SeedFillAngleStep, SeedFillAngleMax); + } else if (m_tool_type == ToolType::SMART_FILL) { + m_smart_fill_angle = action == SLAGizmoEventType::MouseWheelDown ? std::max(m_smart_fill_angle - SmartFillAngleStep, SmartFillAngleMin) + : std::min(m_smart_fill_angle + SmartFillAngleStep, SmartFillAngleMax); m_parent.set_as_dirty(); if (m_rr.mesh_id != -1) { - m_triangle_selectors[m_rr.mesh_id]->seed_fill_select_triangles(m_rr.hit, int(m_rr.facet), m_seed_fill_angle, true); + m_triangle_selectors[m_rr.mesh_id]->seed_fill_select_triangles(m_rr.hit, int(m_rr.facet), m_smart_fill_angle, true); m_triangle_selectors[m_rr.mesh_id]->request_update_render_data(); m_seed_fill_last_mesh_id = m_rr.mesh_id; } @@ -379,10 +379,10 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous Vec3f camera_pos = (trafo_matrix.inverse() * camera.get_position()).cast(); assert(m_rr.mesh_id < int(m_triangle_selectors.size())); - if (m_tool_type == ToolType::SEED_FILL || m_tool_type == ToolType::BUCKET_FILL || (m_tool_type == ToolType::BRUSH && m_cursor_type == TriangleSelector::CursorType::POINTER)) { + if (m_tool_type == ToolType::SMART_FILL || m_tool_type == ToolType::BUCKET_FILL || (m_tool_type == ToolType::BRUSH && m_cursor_type == TriangleSelector::CursorType::POINTER)) { m_triangle_selectors[m_rr.mesh_id]->seed_fill_apply_on_triangles(new_state); - if (m_tool_type == ToolType::SEED_FILL) - m_triangle_selectors[m_rr.mesh_id]->seed_fill_select_triangles(m_rr.hit, int(m_rr.facet), m_seed_fill_angle, true); + if (m_tool_type == ToolType::SMART_FILL) + m_triangle_selectors[m_rr.mesh_id]->seed_fill_select_triangles(m_rr.hit, int(m_rr.facet), m_smart_fill_angle, true); else if (m_tool_type == ToolType::BRUSH && m_cursor_type == TriangleSelector::CursorType::POINTER) m_triangle_selectors[m_rr.mesh_id]->bucket_fill_select_triangles(m_rr.hit, int(m_rr.facet), false, true); else if (m_tool_type == ToolType::BUCKET_FILL) @@ -400,7 +400,7 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous return true; } - if (action == SLAGizmoEventType::Moving && (m_tool_type == ToolType::SEED_FILL || m_tool_type == ToolType::BUCKET_FILL || (m_tool_type == ToolType::BRUSH && m_cursor_type == TriangleSelector::CursorType::POINTER))) { + if (action == SLAGizmoEventType::Moving && (m_tool_type == ToolType::SMART_FILL || m_tool_type == ToolType::BUCKET_FILL || (m_tool_type == ToolType::BRUSH && m_cursor_type == TriangleSelector::CursorType::POINTER))) { if (m_triangle_selectors.empty()) return false; @@ -440,8 +440,8 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous seed_fill_unselect_all(); assert(m_rr.mesh_id < int(m_triangle_selectors.size())); - if (m_tool_type == ToolType::SEED_FILL) - m_triangle_selectors[m_rr.mesh_id]->seed_fill_select_triangles(m_rr.hit, int(m_rr.facet), m_seed_fill_angle); + if (m_tool_type == ToolType::SMART_FILL) + m_triangle_selectors[m_rr.mesh_id]->seed_fill_select_triangles(m_rr.hit, int(m_rr.facet), m_smart_fill_angle); else if (m_tool_type == ToolType::BRUSH && m_cursor_type == TriangleSelector::CursorType::POINTER) m_triangle_selectors[m_rr.mesh_id]->bucket_fill_select_triangles(m_rr.hit, int(m_rr.facet), false); else if (m_tool_type == ToolType::BUCKET_FILL) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index c20c8140d0..6a15ab2a52 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -109,16 +109,16 @@ protected: enum class ToolType { BRUSH, BUCKET_FILL, - SEED_FILL + SMART_FILL }; bool m_triangle_splitting_enabled = true; ToolType m_tool_type = ToolType::BRUSH; - float m_seed_fill_angle = 30.f; + float m_smart_fill_angle = 30.f; - static constexpr float SeedFillAngleMin = 0.0f; - static constexpr float SeedFillAngleMax = 90.f; - static constexpr float SeedFillAngleStep = 1.f; + static constexpr float SmartFillAngleMin = 0.0f; + static constexpr float SmartFillAngleMax = 90.f; + static constexpr float SmartFillAngleStep = 1.f; // It stores the value of the previous mesh_id to which the seed fill was applied. // It is used to detect when the mouse has moved from one volume to another one. From 61583473792222221295c3ac0c8e1fd5a72049af Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 1 Sep 2021 14:37:14 +0200 Subject: [PATCH 17/82] Follow-up to #6817 1) Activate installed filament or SLA material profile after update_compatible(), so that the compatiblity and visibility flags of presets are updated. 2) Only activate the first newly installed filament / SLA material profile if the active printer did not change. This also means that if no filament profile was active before Wizard was open or it became incompatible with the newly installed Printer profile, the default filament profile assigned to the activated Printer is activated preferably, which may or may not be one of the newly installed filament profiles. --- src/libslic3r/PresetBundle.cpp | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/libslic3r/PresetBundle.cpp b/src/libslic3r/PresetBundle.cpp index 63f9f27f22..cb9f04e456 100644 --- a/src/libslic3r/PresetBundle.cpp +++ b/src/libslic3r/PresetBundle.cpp @@ -465,20 +465,9 @@ void PresetBundle::load_selections(AppConfig &config, const PresetPreferences& p // will be selected by the following call of this->update_compatible(PresetSelectCompatibleType::Always). const Preset *initial_printer = printers.find_preset(initial_printer_profile_name); + // If executed due to a Config Wizard update, preferred_printer contains the first newly installed printer, otherwise nullptr. const Preset *preferred_printer = printers.find_system_preset_by_model_and_variant(preferred_selection.printer_model_id, preferred_selection.printer_variant); - printers.select_preset_by_name( - (preferred_printer != nullptr /*&& (initial_printer == nullptr || !initial_printer->is_visible)*/) ? - preferred_printer->name : - initial_printer_profile_name, - true); - - // select preferred filament/sla_material profile if any exists and is visible - if (!preferred_selection.filament.empty()) - if (auto it = filaments.find_preset_internal(preferred_selection.filament); it != filaments.end() && it->is_visible) - initial_filament_profile_name = it->name; - if (!preferred_selection.sla_material.empty()) - if (auto it = sla_materials.find_preset_internal(preferred_selection.sla_material); it != sla_materials.end() && it->is_visible) - initial_sla_material_profile_name = it->name; + printers.select_preset_by_name(preferred_printer ? preferred_printer->name : initial_printer_profile_name, true); // Selects the profile, leaves it to -1 if the initial profile name is empty or if it was not found. prints.select_preset_by_name_strict(initial_print_profile_name); @@ -506,6 +495,21 @@ void PresetBundle::load_selections(AppConfig &config, const PresetPreferences& p this->update_compatible(PresetSelectCompatibleType::Always); this->update_multi_material_filament_presets(); + if (initial_printer != nullptr && (preferred_printer == nullptr || initial_printer == preferred_printer)) { + // Don't run the following code, as we want to activate default filament / SLA material profiles when installing and selecting a new printer. + // Only run this code if just a filament / SLA material was installed by Config Wizard for an active Printer. + auto printer_technology = printers.get_selected_preset().printer_technology(); + if (printer_technology == ptFFF && ! preferred_selection.filament.empty()) { + if (auto it = filaments.find_preset_internal(preferred_selection.filament); it != filaments.end() && it->is_visible) { + filaments.select_preset_by_name_strict(preferred_selection.filament); + this->filament_presets.front() = filaments.get_selected_preset_name(); + } + } else if (printer_technology == ptSLA && ! preferred_selection.sla_material.empty()) { + if (auto it = sla_materials.find_preset_internal(preferred_selection.sla_material); it != sla_materials.end() && it->is_visible) + sla_materials.select_preset_by_name_strict(preferred_selection.sla_material); + } + } + // Parse the initial physical printer name. std::string initial_physical_printer_name = remove_ini_suffix(config.get("presets", "physical_printer")); From 950c216239866a0ed917e8d4a680264109778646 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 1 Sep 2021 15:11:26 +0200 Subject: [PATCH 18/82] Commented out AMF export. The format never took off, we don't want to keep supporting it. Let's wait for user feedback. --- src/slic3r/GUI/MainFrame.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 7d51985c57..469c3b0f65 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -1239,9 +1239,10 @@ void MainFrame::init_menubar_as_editor() append_menu_item(export_menu, wxID_ANY, _L("Export plate as STL &including supports") + dots, _L("Export current plate as STL including supports"), [this](wxCommandEvent&) { if (m_plater) m_plater->export_stl(true); }, "export_plater", nullptr, [this](){return can_export_supports(); }, this); - append_menu_item(export_menu, wxID_ANY, _L("Export plate as &AMF") + dots, _L("Export current plate as AMF"), - [this](wxCommandEvent&) { if (m_plater) m_plater->export_amf(); }, "export_plater", nullptr, - [this](){return can_export_model(); }, this); +// Deprecating AMF export. Let's wait for user feedback. +// append_menu_item(export_menu, wxID_ANY, _L("Export plate as &AMF") + dots, _L("Export current plate as AMF"), +// [this](wxCommandEvent&) { if (m_plater) m_plater->export_amf(); }, "export_plater", nullptr, +// [this](){return can_export_model(); }, this); export_menu->AppendSeparator(); append_menu_item(export_menu, wxID_ANY, _L("Export &toolpaths as OBJ") + dots, _L("Export toolpaths as OBJ"), [this](wxCommandEvent&) { if (m_plater) m_plater->export_toolpaths_to_obj(); }, "export_plater", nullptr, From 876e6fdddd8e3d1f78cd3c7e4e07be28430154b2 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 1 Sep 2021 15:12:36 +0200 Subject: [PATCH 19/82] Commented opening menubar item until its properly implemented. --- resources/data/hints.ini | 8 ++++---- src/slic3r/GUI/HintNotification.cpp | 4 ++-- src/slic3r/GUI/MainFrame.cpp | 3 ++- src/slic3r/GUI/MainFrame.hpp | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/resources/data/hints.ini b/resources/data/hints.ini index af2e09209b..5c89e93e07 100644 --- a/resources/data/hints.ini +++ b/resources/data/hints.ini @@ -194,11 +194,11 @@ documentation_link = https://help.prusa3d.com/en/article/insert-pause-or-custom- disabled_tags = SLA [hint:Configuration snapshots] -text = Configuration snapshots\nDid you know that roll back to a complete backup of all system and user profiles? You can view and move back and forth between snapshots using the Configuration - Configuration snapshots menu. +text = Configuration snapshots\nDid you know that roll back to a complete backup of all system and user profiles? You can view and move back and forth between snapshots using the Configuration - Configuration snapshots menu. documentation_link = https://help.prusa3d.com/en/article/configuration-snapshots_1776 -hypertext_type = menubar -hypertext_menubar_menu_id = 4 -hypertext_menubar_item_id = 1 +#hypertext_type = menubar +#hypertext_menubar_menu_id = 4 +#hypertext_menubar_item_id = 1 [hint:Minimum wall thickness] text = Minimum wall thickness\nDid you know that instead of the number of top and bottom layers, you can define theMinimum shell thicknessin millimeters? This feature is especially useful when using the variable layer height function. diff --git a/src/slic3r/GUI/HintNotification.cpp b/src/slic3r/GUI/HintNotification.cpp index 0cdf441c03..cf35022c2a 100644 --- a/src/slic3r/GUI/HintNotification.cpp +++ b/src/slic3r/GUI/HintNotification.cpp @@ -379,12 +379,12 @@ void HintDatabase::load_hints_from_file(const boost::filesystem::path& path) wxGetApp().obj_list()->load_shape_object_from_gallery(); } }; m_loaded_hints.emplace_back(hint_data); - } else if (dict["hypertext_type"] == "menubar") { + } /*else if (dict["hypertext_type"] == "menubar") { int menu = std::atoi(dict["hypertext_menubar_menu_id"].c_str()); int item = std::atoi(dict["hypertext_menubar_item_id"].c_str()); HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, true, documentation_link, [menu, item]() { wxGetApp().mainframe->open_menubar_item(menu, item); } }; m_loaded_hints.emplace_back(hint_data); - } + }*/ } else { // plain text without hypertext HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, false, documentation_link }; diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 469c3b0f65..3d486f052d 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -1480,7 +1480,7 @@ void MainFrame::init_menubar_as_editor() if (plater()->printer_technology() == ptSLA) update_menubar(); } - +/* void MainFrame::open_menubar_item(int menu_index, int item_index) { if (m_menubar == nullptr) @@ -1502,6 +1502,7 @@ void MainFrame::open_menubar_item(int menu_index, int item_index) } wxPostEvent((wxEvtHandler*)menu, wxCommandEvent(wxEVT_MENU, item->GetId())); } +*/ void MainFrame::init_menubar_as_gcodeviewer() { wxMenu* fileMenu = new wxMenu; diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index e8d3c67a72..093e9e5c47 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -159,7 +159,7 @@ public: void init_menubar_as_gcodeviewer(); void update_menubar(); // Open item in menu by menu and item index (visible order of items including separators) - void open_menubar_item(int menu_index, int item_index); + //void open_menubar_item(int menu_index, int item_index); #ifdef _WIN32 void show_tabs_menu(bool show); #endif From c25ca3015ab3701574c39ddb94e82fa6eaba64d6 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 1 Sep 2021 15:15:23 +0200 Subject: [PATCH 20/82] Bumped up version number --- version.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.inc b/version.inc index 4e7aab2355..d981d620ab 100644 --- a/version.inc +++ b/version.inc @@ -3,7 +3,7 @@ set(SLIC3R_APP_NAME "PrusaSlicer") set(SLIC3R_APP_KEY "PrusaSlicer") -set(SLIC3R_VERSION "2.4.0-alpha0") +set(SLIC3R_VERSION "2.4.0-alpha1") set(SLIC3R_BUILD_ID "PrusaSlicer-${SLIC3R_VERSION}+UNKNOWN") set(SLIC3R_RC_VERSION "2,4,0,0") set(SLIC3R_RC_VERSION_DOTS "2.4.0.0") From e6eae6258487ad15d05b621557968d8c49239f86 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 1 Sep 2021 16:08:03 +0200 Subject: [PATCH 21/82] MSW specific: Fixed a typo caused extension of PresetComboBox's height on SettingsTabs, added comment for workaround --- src/slic3r/GUI/Tab.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 86089f729e..5effa35990 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -492,17 +492,15 @@ void Tab::OnActivate() activate_selected_page([](){}); m_hsizer->Layout(); - // Workaroud for Menu instead of NoteBook #ifdef _MSW_DARK_MODE -// if (wxGetApp().tabs_as_menu()) - { - wxSize sz = m_presets_choice->GetSize(); - wxSize ok_sz = wxSize(35 * m_em_unit, m_presets_choice->GetBestSize().y+1); - if (sz != ok_sz) { - m_presets_choice->SetMinSize(ok_sz); - m_presets_choice->SetSize(ok_sz); - GetSizer()->GetItem(size_t(0))->GetSizer()->Layout(); - } + // Because of DarkMode we use our own Notebook (inherited from wxSiplebook) instead of wxNotebook + // And it looks like first Layout of the page doesn't update a size of the m_presets_choice + // So we have to set correct size explicitely + if (wxSize ok_sz = wxSize(35 * m_em_unit, m_presets_choice->GetBestSize().y); + ok_sz != m_presets_choice->GetSize()) { + m_presets_choice->SetMinSize(ok_sz); + m_presets_choice->SetSize(ok_sz); + GetSizer()->GetItem(size_t(0))->GetSizer()->Layout(); } #endif // _MSW_DARK_MODE Refresh(); From 25feacfd9583d5629656dee162c0ab99457470b0 Mon Sep 17 00:00:00 2001 From: Filip Sykala Date: Wed, 1 Sep 2021 19:15:16 +0200 Subject: [PATCH 22/82] FIX Creation of non volume place in mode during simplification --- src/libslic3r/QuadricEdgeCollapse.cpp | 130 ++++++++++++++---- tests/libslic3r/test_indexed_triangle_set.cpp | 9 ++ 2 files changed, 114 insertions(+), 25 deletions(-) diff --git a/src/libslic3r/QuadricEdgeCollapse.cpp b/src/libslic3r/QuadricEdgeCollapse.cpp index 6efc5f4a9d..2e1b7089be 100644 --- a/src/libslic3r/QuadricEdgeCollapse.cpp +++ b/src/libslic3r/QuadricEdgeCollapse.cpp @@ -7,6 +7,8 @@ using namespace Slic3r; +#define NDEBUG + // only private namespace not neccessary be in .hpp namespace QuadricEdgeCollapse { using Vertices = std::vector; @@ -79,10 +81,13 @@ namespace QuadricEdgeCollapse { init(const indexed_triangle_set &its, ThrowOnCancel& throw_on_cancel, StatusFn& status_fn); std::optional find_triangle_index1(uint32_t vi, const VertexInfo& v_info, uint32_t ti, const EdgeInfos& e_infos, const Indices& indices); + void reorder_edges(EdgeInfos &e_infos, const VertexInfo &v_info, uint32_t ti0, uint32_t ti1); bool is_flipped(const Vec3f &new_vertex, uint32_t ti0, uint32_t ti1, const VertexInfo& v_info, const TriangleInfos &t_infos, const EdgeInfos &e_infos, const indexed_triangle_set &its); bool degenerate(uint32_t vi, uint32_t ti0, uint32_t ti1, const VertexInfo &v_info, const EdgeInfos &e_infos, const Indices &indices); + bool create_no_volume(uint32_t vi0, uint32_t vi1, uint32_t ti0, uint32_t ti1, + const VertexInfo &v_info0, const VertexInfo &v_info1, const EdgeInfos &e_infos, const Indices &indices); // find edge with smallest error in triangle Vec3d calculate_3errors(const Triangle &t, const Vertices &vertices, const VertexInfos &v_infos); Error calculate_error(uint32_t ti, const Triangle& t,const Vertices &vertices, const VertexInfos& v_infos, unsigned char& min_index); @@ -99,6 +104,10 @@ namespace QuadricEdgeCollapse { const VertexInfos &v_infos, const EdgeInfos &e_infos); #endif /* NDEBUG */ + // constants --> may be move to config + const int status_init_size = 10; // in percents + const uint32_t check_cancel_period = 16; // how many edge to reduce before call throw_on_cancel + const size_t max_triangle_count_for_one_vertex = 50; } // namespace QuadricEdgeCollapse using namespace QuadricEdgeCollapse; @@ -110,10 +119,6 @@ void Slic3r::its_quadric_edge_collapse( std::function throw_on_cancel, std::function status_fn) { - // constants --> may be move to config - const int status_init_size = 10; // in percents - const int check_cancel_period = 16; // how many edge to reduce before call throw_on_cancel - // check input if (triangle_count >= its.indices.size()) return; float maximal_error = (max_error == nullptr)? std::numeric_limits::max() : *max_error; @@ -122,7 +127,8 @@ void Slic3r::its_quadric_edge_collapse( if (status_fn == nullptr) status_fn = [](int) {}; StatusFn init_status_fn = [&](int percent) { - status_fn(std::round((percent * status_init_size) / 100.)); + float n_percent = percent * status_init_size / 100.f; + status_fn(static_cast(std::round(n_percent))); }; TriangleInfos t_infos; // only normals with information about deleted triangle @@ -145,7 +151,6 @@ void Slic3r::its_quadric_edge_collapse( mpq.reserve(its.indices.size()); for (Error &error :errors) mpq.push(error); - const size_t max_triangle_count_for_one_vertex = 50; CopyEdgeInfos ceis; ceis.reserve(max_triangle_count_for_one_vertex); EdgeInfos e_infos_swap; @@ -162,8 +167,9 @@ void Slic3r::its_quadric_edge_collapse( (1. - reduced); status_fn(static_cast(std::round(status))); }; - // modulo for update status - uint32_t status_mod = std::max(uint32_t(16), count_triangle_to_reduce / 100); + // modulo for update status, call each percent only once + uint32_t status_mod = std::max(uint32_t(16), + count_triangle_to_reduce / (100 - status_init_size)); uint32_t iteration_number = 0; float last_collapsed_error = 0.f; @@ -195,14 +201,21 @@ void Slic3r::its_quadric_edge_collapse( q += v_info1.q; Vec3f new_vertex0 = calculate_vertex(vi0, vi1, q, its.vertices); // set of triangle indices that change quadric + uint32_t ti1 = -1; // triangle 1 index auto ti1_opt = (v_info0.count < v_info1.count)? find_triangle_index1(vi1, v_info0, ti0, e_infos, its.indices) : find_triangle_index1(vi0, v_info1, ti0, e_infos, its.indices) ; + if (ti1_opt.has_value()) { + ti1 = *ti1_opt; + reorder_edges(e_infos, v_info0, ti0, ti1); + reorder_edges(e_infos, v_info1, ti0, ti1); + } if (!ti1_opt.has_value() || // edge has only one triangle - degenerate(vi0, ti0, *ti1_opt, v_info1, e_infos, its.indices) || - degenerate(vi1, ti0, *ti1_opt, v_info0, e_infos, its.indices) || - is_flipped(new_vertex0, ti0, *ti1_opt, v_info0, t_infos, e_infos, its) || - is_flipped(new_vertex0, ti0, *ti1_opt, v_info1, t_infos, e_infos, its)) { + degenerate(vi0, ti0, ti1, v_info1, e_infos, its.indices) || + degenerate(vi1, ti0, ti1, v_info0, e_infos, its.indices) || + create_no_volume(vi0, vi1, ti0, ti1, v_info0, v_info1, e_infos, its.indices) || + is_flipped(new_vertex0, ti0, ti1, v_info0, t_infos, e_infos, its) || + is_flipped(new_vertex0, ti0, ti1, v_info1, t_infos, e_infos, its)) { // try other triangle's edge Vec3d errors = calculate_3errors(t0, its.vertices, v_infos); Vec3i ord = (errors[0] < errors[1]) ? @@ -227,29 +240,25 @@ void Slic3r::its_quadric_edge_collapse( mpq.push(e); continue; } - uint32_t ti1 = *ti1_opt; + last_collapsed_error = e.value; changed_triangle_indices.clear(); changed_triangle_indices.reserve(v_info0.count + v_info1.count - 4); // for each vertex0 triangles - uint32_t v_info0_end = v_info0.start + v_info0.count; + uint32_t v_info0_end = v_info0.start + v_info0.count - 2; for (uint32_t di = v_info0.start; di < v_info0_end; ++di) { assert(di < e_infos.size()); uint32_t ti = e_infos[di].t_index; - if (ti == ti0) continue; // ti0 will be deleted - if (ti == ti1) continue; // ti1 will be deleted changed_triangle_indices.emplace_back(ti); } // for each vertex1 triangles - uint32_t v_info1_end = v_info1.start + v_info1.count; + uint32_t v_info1_end = v_info1.start + v_info1.count - 2; for (uint32_t di = v_info1.start; di < v_info1_end; ++di) { assert(di < e_infos.size()); EdgeInfo &e_info = e_infos[di]; uint32_t ti = e_info.t_index; - if (ti == ti0) continue; // ti0 will be deleted - if (ti == ti1) continue; // ti1 will be deleted Triangle &t = its.indices[ti]; t[e_info.edge] = vi0; // change index changed_triangle_indices.emplace_back(ti); @@ -282,7 +291,9 @@ void Slic3r::its_quadric_edge_collapse( t_info1.set_deleted(); // triangle counter decrementation actual_triangle_count-=2; +#ifndef NDEBUG assert(check_neighbors(its, t_infos, v_infos, e_infos)); +#endif // NDEBUG } // compact triangle @@ -506,6 +517,38 @@ std::optional QuadricEdgeCollapse::find_triangle_index1(uint32_t return {}; } +void QuadricEdgeCollapse::reorder_edges(EdgeInfos & e_infos, + const VertexInfo &v_info, + uint32_t ti0, + uint32_t ti1) +{ + // swap edge info of ti0 and ti1 to end(last one and one before) + size_t v_info_end = v_info.start + v_info.count - 2; + EdgeInfo &e_info_ti0 = e_infos[v_info_end]; + EdgeInfo &e_info_ti1 = e_infos[v_info_end+1]; + bool is_swaped = false; + for (size_t ei = v_info.start; ei < v_info_end; ++ei) { + EdgeInfo &e_info = e_infos[ei]; + if (e_info.t_index == ti0) { + std::swap(e_info, e_info_ti0); + if (is_swaped) return; + if (e_info.t_index == ti1) { + std::swap(e_info, e_info_ti1); + return; + } + is_swaped = true; + } else if (e_info.t_index == ti1) { + std::swap(e_info, e_info_ti1); + if (is_swaped) return; + if (e_info.t_index == ti0) { + std::swap(e_info, e_info_ti0); + return; + } + is_swaped = true; + } + } +} + bool QuadricEdgeCollapse::is_flipped(const Vec3f & new_vertex, uint32_t ti0, uint32_t ti1, @@ -519,12 +562,10 @@ bool QuadricEdgeCollapse::is_flipped(const Vec3f & new_vertex, static const float dot_thr = 0.2f; // Value from simplify mesh cca 80 DEG // for each vertex triangles - size_t v_info_end = v_info.start + v_info.count; + size_t v_info_end = v_info.start + v_info.count-2; for (size_t ei = v_info.start; ei < v_info_end; ++ei) { assert(ei < e_infos.size()); const EdgeInfo &e_info = e_infos[ei]; - if (e_info.t_index == ti0) continue; // ti0 will be deleted - if (e_info.t_index == ti1) continue; // ti1 will be deleted const Triangle &t = its.indices[e_info.t_index]; const Vec3f &normal = t_infos[e_info.t_index].n; const Vec3f &vf = its.vertices[t[(e_info.edge + 1) % 3]]; @@ -554,12 +595,10 @@ bool QuadricEdgeCollapse::degenerate(uint32_t vi, { // check surround triangle do not contain vertex index // protect from creation of triangle with two same vertices inside - size_t v_info_end = v_info.start + v_info.count; + size_t v_info_end = v_info.start + v_info.count - 2; for (size_t ei = v_info.start; ei < v_info_end; ++ei) { assert(ei < e_infos.size()); const EdgeInfo &e_info = e_infos[ei]; - if (e_info.t_index == ti0) continue; // ti0 will be deleted - if (e_info.t_index == ti1) continue; // ti1 will be deleted const Triangle &t = indices[e_info.t_index]; for (size_t i = 0; i < 3; ++i) if (static_cast(t[i]) == vi) return true; @@ -567,6 +606,47 @@ bool QuadricEdgeCollapse::degenerate(uint32_t vi, return false; } +bool QuadricEdgeCollapse::create_no_volume( + uint32_t vi0 , uint32_t vi1, + uint32_t ti0 , uint32_t ti1, + const VertexInfo &v_info0, const VertexInfo &v_info1, + const EdgeInfos & e_infos, const Indices &indices) +{ + // check that triangles around vertex0 doesn't have half edge + // with opposit order in set of triangles around vertex1 + // protect from creation of two triangles with oposit order - no volume space + size_t v_info0_end = v_info0.start + v_info0.count - 2; + size_t v_info1_end = v_info1.start + v_info1.count - 2; + for (size_t ei0 = v_info0.start; ei0 < v_info0_end; ++ei0) { + const EdgeInfo &e_info0 = e_infos[ei0]; + const Triangle &t0 = indices[e_info0.t_index]; + // edge CCW vertex indices are t0vi0, t0vi1 + size_t t0i = 0; + if (t0[t0i] == vi0) ++t0i; + uint32_t t0vi0 = t0[t0i]; + ++t0i; + if (t0[t0i] == vi0) ++t0i; + uint32_t t0vi1 = t0[t0i]; + + for (size_t ei1 = v_info1.start; ei1 < v_info1_end; ++ei1) { + const EdgeInfo &e_info1 = e_infos[ei1]; + const Triangle &t1 = indices[e_info1.t_index]; + size_t t1i = 0; + for (; t1i < 3; ++t1i) if (t1[t1i] == t0vi1) break; + if (t1i >= 3) continue; // without vertex index from triangle 0 + // check if second index is same too + ++t1i; + if (t1i == 3) t1i = 0; // triangle loop(modulo 3) + if (t1[t1i] == vi1) { + ++t1i; + if (t1i == 3) t1i = 0; // triangle loop(modulo 3) + } + if (t1[t1i] == t0vi0) return true; + } + } + return false; +} + Vec3d QuadricEdgeCollapse::calculate_3errors(const Triangle & t, const Vertices & vertices, const VertexInfos &v_infos) diff --git a/tests/libslic3r/test_indexed_triangle_set.cpp b/tests/libslic3r/test_indexed_triangle_set.cpp index a3996e6519..bbb22e778c 100644 --- a/tests/libslic3r/test_indexed_triangle_set.cpp +++ b/tests/libslic3r/test_indexed_triangle_set.cpp @@ -288,3 +288,12 @@ TEST_CASE("Simplify trouble case", "[its]") its_quadric_edge_collapse(tm.its, wanted_count, &max_error); CHECK(tm.its.indices.size() <= 8); } + +TEST_CASE("Simplified cube should not be empty.", "[its]") +{ + auto its = its_make_cube(1, 2, 3); + float max_error = std::numeric_limits::max(); + uint32_t wanted_count = 0; + its_quadric_edge_collapse(its, wanted_count, &max_error); + CHECK(!its.indices.empty()); +} From f6f70f6fd4115b205d462ca14234810157d1bbb5 Mon Sep 17 00:00:00 2001 From: Filip Sykala Date: Wed, 1 Sep 2021 20:19:55 +0200 Subject: [PATCH 23/82] Fix Crash when delete model during simplification --- src/libslic3r/QuadricEdgeCollapse.cpp | 21 ++++++++++++--------- src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp | 21 +++++++++++++++++++-- src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp | 1 + 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/libslic3r/QuadricEdgeCollapse.cpp b/src/libslic3r/QuadricEdgeCollapse.cpp index 2e1b7089be..6609879cd5 100644 --- a/src/libslic3r/QuadricEdgeCollapse.cpp +++ b/src/libslic3r/QuadricEdgeCollapse.cpp @@ -7,7 +7,10 @@ using namespace Slic3r; +// Faster debug, comment when you want deep check +#ifndef NDEBUG #define NDEBUG +#endif // !NDEBUG // only private namespace not neccessary be in .hpp namespace QuadricEdgeCollapse { @@ -105,10 +108,17 @@ namespace QuadricEdgeCollapse { #endif /* NDEBUG */ // constants --> may be move to config - const int status_init_size = 10; // in percents const uint32_t check_cancel_period = 16; // how many edge to reduce before call throw_on_cancel const size_t max_triangle_count_for_one_vertex = 50; -} // namespace QuadricEdgeCollapse + // change speed of progress bargraph + const int status_init_size = 10; // in percents + // parts of init size + const int status_normal_size = 25; + const int status_sum_quadric = 25; + const int status_set_offsets = 10; + const int status_calc_errors = 30; + const int status_create_refs = 10; + } // namespace QuadricEdgeCollapse using namespace QuadricEdgeCollapse; @@ -395,13 +405,6 @@ SymMat QuadricEdgeCollapse::create_quadric(const Triangle &t, std::tuple QuadricEdgeCollapse::init(const indexed_triangle_set &its, ThrowOnCancel& throw_on_cancel, StatusFn& status_fn) { - // change speed of progress bargraph - const int status_normal_size = 25; - const int status_sum_quadric = 25; - const int status_set_offsets = 10; - const int status_calc_errors = 30; - const int status_create_refs = 10; - int status_offset = 0; TriangleInfos t_infos(its.indices.size()); VertexInfos v_infos(its.vertices.size()); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp index b9e5d111b0..f70e3f93e2 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp @@ -55,6 +55,7 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi create_gui_cfg(); const Selection &selection = m_parent.get_selection(); int object_idx = selection.get_object_idx(); + if (!is_selected_object(&object_idx)) return; ModelObject *obj = wxGetApp().plater()->model().objects[object_idx]; ModelVolume *act_volume = obj->volumes.front(); @@ -329,9 +330,9 @@ void GLGizmoSimplify::on_set_state() { // Closing gizmo. e.g. selecting another one if (GLGizmoBase::m_state == GLGizmoBase::Off) { - // refuse outgoing during simlification - if (m_state != State::settings) { + // object is not selected when it is deleted(cancel and close gizmo) + if (m_state != State::settings && is_selected_object()) { GLGizmoBase::m_state = GLGizmoBase::On; auto notification_manager = wxGetApp().plater()->get_notification_manager(); notification_manager->push_notification( @@ -383,4 +384,20 @@ void GLGizmoSimplify::request_rerender() { }); } +bool GLGizmoSimplify::is_selected_object(int *object_idx) +{ + int index = (object_idx != nullptr) ? *object_idx : + m_parent.get_selection().get_object_idx(); + // no selected object --> can appear after delete model + if (index < 0) { + switch (m_state) { + case State::settings: close(); break; + case State::canceling: break; + default: m_state = State::canceling; + } + return false; + } + return true; +} + } // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp index 0f5bd5991f..856b6298d0 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp @@ -38,6 +38,7 @@ private: void set_its(indexed_triangle_set &its); void create_gui_cfg(); void request_rerender(); + bool is_selected_object(int *object_idx = nullptr); std::atomic_bool m_is_valid_result; // differ what to do in apply std::atomic_bool m_exist_preview; // set when process end From 2bb14849f46dc0bc49b9b9ee8bc05c7aea509c39 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 2 Sep 2021 08:32:05 +0200 Subject: [PATCH 24/82] #6866 - Do not clear plater when pressing Cancel button in the New Project confirmation dialog --- src/slic3r/GUI/Plater.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index f8bcafdd8b..f80f2cc3b5 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -4759,7 +4759,7 @@ SLAPrint& Plater::sla_print() { return p->sla_print; } void Plater::new_project() { - if (!p->save_project_if_dirty()) + if (p->save_project_if_dirty() == wxID_CANCEL) return; p->select_view_3D("3D"); From 5f7a4982f6ab241a5576df1ced11fddbe6ccdafb Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 1 Sep 2021 16:49:23 +0200 Subject: [PATCH 25/82] Open menubar item by name with translations --- resources/data/hints.ini | 10 ++++----- src/slic3r/GUI/HintNotification.cpp | 6 +++--- src/slic3r/GUI/MainFrame.cpp | 33 +++++++++++++++++------------ src/slic3r/GUI/MainFrame.hpp | 4 ++-- 4 files changed, 29 insertions(+), 24 deletions(-) diff --git a/resources/data/hints.ini b/resources/data/hints.ini index 5c89e93e07..e7b1bb6814 100644 --- a/resources/data/hints.ini +++ b/resources/data/hints.ini @@ -40,8 +40,8 @@ # hypertext_type = gallery # #Open top menubar item -#hypertext_menubar_menu_id = 4 (0 - 5, index of menu from left: File = 0, Edit = 1...) -#hypertext_menubar_item_id = 1 (index of item, starting at 0, Including separators! In Window: 0 = Plater Tab, 1 = SEPARATOR, 2 = Print Setting Tab...) +#hypertext_menubar_menu_name = (Name in english visible as menu name: File, ) +#hypertext_menubar_item_name = (Name of item in english, if there are three dots at the end of name, put name without three dots) # # # Each notification can have disabled and enabled modes and techs - divided by ; and space @@ -196,9 +196,9 @@ disabled_tags = SLA [hint:Configuration snapshots] text = Configuration snapshots\nDid you know that roll back to a complete backup of all system and user profiles? You can view and move back and forth between snapshots using the Configuration - Configuration snapshots menu. documentation_link = https://help.prusa3d.com/en/article/configuration-snapshots_1776 -#hypertext_type = menubar -#hypertext_menubar_menu_id = 4 -#hypertext_menubar_item_id = 1 +hypertext_type = menubar +hypertext_menubar_menu_name = Configuration +hypertext_menubar_item_name = Configuration Snapshots [hint:Minimum wall thickness] text = Minimum wall thickness\nDid you know that instead of the number of top and bottom layers, you can define theMinimum shell thicknessin millimeters? This feature is especially useful when using the variable layer height function. diff --git a/src/slic3r/GUI/HintNotification.cpp b/src/slic3r/GUI/HintNotification.cpp index cf35022c2a..75bb69a656 100644 --- a/src/slic3r/GUI/HintNotification.cpp +++ b/src/slic3r/GUI/HintNotification.cpp @@ -379,9 +379,9 @@ void HintDatabase::load_hints_from_file(const boost::filesystem::path& path) wxGetApp().obj_list()->load_shape_object_from_gallery(); } }; m_loaded_hints.emplace_back(hint_data); - } /*else if (dict["hypertext_type"] == "menubar") { - int menu = std::atoi(dict["hypertext_menubar_menu_id"].c_str()); - int item = std::atoi(dict["hypertext_menubar_item_id"].c_str()); + } else if (dict["hypertext_type"] == "menubar") { + wxString menu(_L("&" + dict["hypertext_menubar_menu_name"])); + wxString item(_L(dict["hypertext_menubar_item_name"])); HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, true, documentation_link, [menu, item]() { wxGetApp().mainframe->open_menubar_item(menu, item); } }; m_loaded_hints.emplace_back(hint_data); }*/ diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 3d486f052d..eb309b1afb 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -1480,29 +1480,34 @@ void MainFrame::init_menubar_as_editor() if (plater()->printer_technology() == ptSLA) update_menubar(); } -/* -void MainFrame::open_menubar_item(int menu_index, int item_index) + +void MainFrame::open_menubar_item(const wxString& menu_name,const wxString& item_name) { if (m_menubar == nullptr) return; - wxMenu* menu = m_menubar->GetMenu(menu_index); + // Get menu object from menubar + int menu_index = m_menubar->FindMenu(menu_name); + wxMenu* menu = m_menubar->GetMenu(menu_index); if (menu == nullptr) { - BOOST_LOG_TRIVIAL(error) << "Mainframe open_menubar_item function couldn't find menu: " << menu_index; + BOOST_LOG_TRIVIAL(error) << "Mainframe open_menubar_item function couldn't find menu: " << menu_name; return; } - wxMenuItemList items = menu->GetMenuItems(); - if (items.size() <= item_index) { - BOOST_LOG_TRIVIAL(error) << "Mainframe open_menubar_item function couldn't find item: " << item_index; - return; - } - wxMenuItem* item = items[item_index]; - if (item == nullptr) { - BOOST_LOG_TRIVIAL(error) << "Mainframe open_menubar_item function couldn't find item: " << item_index; + // Get item id from menu + int item_id = menu->FindItem(item_name); + if (item_id == wxNOT_FOUND) + { + // try adding three dots char + item_id = menu->FindItem(item_name + dots); + } + if (item_id == wxNOT_FOUND) + { + BOOST_LOG_TRIVIAL(error) << "Mainframe open_menubar_item function couldn't find item: " << item_name; return; } - wxPostEvent((wxEvtHandler*)menu, wxCommandEvent(wxEVT_MENU, item->GetId())); + // wxEVT_MENU will trigger item + wxPostEvent((wxEvtHandler*)menu, wxCommandEvent(wxEVT_MENU, item_id)); } -*/ + void MainFrame::init_menubar_as_gcodeviewer() { wxMenu* fileMenu = new wxMenu; diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index 093e9e5c47..e87f94f650 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -158,8 +158,8 @@ public: void init_menubar_as_editor(); void init_menubar_as_gcodeviewer(); void update_menubar(); - // Open item in menu by menu and item index (visible order of items including separators) - //void open_menubar_item(int menu_index, int item_index); + // Open item in menu by menu and item name (in actual language) + void open_menubar_item(const wxString& menu_name,const wxString& item_name); #ifdef _WIN32 void show_tabs_menu(bool show); #endif From 42f4de94dfd416d8b4b5718eaba4f43225a55ada Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 1 Sep 2021 17:58:55 +0200 Subject: [PATCH 26/82] Calling destructor of notifications manager and hint database Ensures to translate hints after change of language --- src/slic3r/GUI/HintNotification.cpp | 7 +++++++ src/slic3r/GUI/HintNotification.hpp | 3 +++ src/slic3r/GUI/NotificationManager.cpp | 4 ++++ src/slic3r/GUI/NotificationManager.hpp | 1 + src/slic3r/GUI/Plater.cpp | 2 ++ 5 files changed, 17 insertions(+) diff --git a/src/slic3r/GUI/HintNotification.cpp b/src/slic3r/GUI/HintNotification.cpp index 75bb69a656..d1a2328e9a 100644 --- a/src/slic3r/GUI/HintNotification.cpp +++ b/src/slic3r/GUI/HintNotification.cpp @@ -242,6 +242,13 @@ HintDatabase::~HintDatabase() write_used_binary(m_used_ids); } } +void HintDatabase::uninit() +{ + if (m_initialized) { + write_used_binary(m_used_ids); + } + m_initialized = false; +} void HintDatabase::init() { load_hints_from_file(std::move(boost::filesystem::path(resources_dir()) / "data" / "hints.ini")); diff --git a/src/slic3r/GUI/HintNotification.hpp b/src/slic3r/GUI/HintNotification.hpp index c1e7c0ed3c..e5dd90bdbd 100644 --- a/src/slic3r/GUI/HintNotification.hpp +++ b/src/slic3r/GUI/HintNotification.hpp @@ -47,6 +47,9 @@ public: return 0; return m_loaded_hints.size(); } + // resets m_initiailized to false and writes used if was initialized + // used when reloading in runtime - like change language + void uninit(); private: void init(); void load_hints_from_file(const boost::filesystem::path& path); diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index 219faf42ef..4e94d82608 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -1107,6 +1107,10 @@ NotificationManager::NotificationManager(wxEvtHandler* evt_handler) : m_evt_handler(evt_handler) { } +NotificationManager::~NotificationManager() +{ + HintDatabase::get_instance().uninit(); +} void NotificationManager::push_notification(const NotificationType type, int timestamp) { auto it = std::find_if(std::begin(basic_notifications), std::end(basic_notifications), diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index 4aba35f4cb..1e667e4525 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -121,6 +121,7 @@ public: }; NotificationManager(wxEvtHandler* evt_handler); + ~NotificationManager(); // Push a prefabricated notification from basic_notifications (see the table at the end of this file). void push_notification(const NotificationType type, int timestamp = 0); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index f80f2cc3b5..b86092795d 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2073,6 +2073,8 @@ Plater::priv::~priv() { if (config != nullptr) delete config; + if (notification_manager != nullptr) + delete notification_manager; } void Plater::priv::update(unsigned int flags) From 795ac7f297ecc339bec26c2eb3e704d15393e4d1 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 2 Sep 2021 09:49:04 +0200 Subject: [PATCH 27/82] Follow-up of 2bb14849f46dc0bc49b9b9ee8bc05c7aea509c39 - Similar fix for Open Project command --- src/slic3r/GUI/Plater.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index f80f2cc3b5..0bdbae8f41 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -4772,7 +4772,7 @@ void Plater::new_project() void Plater::load_project() { - if (!p->save_project_if_dirty()) + if (p->save_project_if_dirty() == wxID_CANCEL) return; // Ask user for a project file name. From 0cb08ebda401228251603d47527227cecb0d92b0 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Thu, 2 Sep 2021 09:54:20 +0200 Subject: [PATCH 28/82] fix of b45ae0170bebf6fd564bf12fede3013f3bf94e7a --- src/slic3r/GUI/HintNotification.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/HintNotification.cpp b/src/slic3r/GUI/HintNotification.cpp index d1a2328e9a..33ccdc4ae3 100644 --- a/src/slic3r/GUI/HintNotification.cpp +++ b/src/slic3r/GUI/HintNotification.cpp @@ -391,7 +391,7 @@ void HintDatabase::load_hints_from_file(const boost::filesystem::path& path) wxString item(_L(dict["hypertext_menubar_item_name"])); HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, true, documentation_link, [menu, item]() { wxGetApp().mainframe->open_menubar_item(menu, item); } }; m_loaded_hints.emplace_back(hint_data); - }*/ + } } else { // plain text without hypertext HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, false, documentation_link }; From d45ab1c484c9699a596bf40e21e04d25fe645bda Mon Sep 17 00:00:00 2001 From: Filip Sykala Date: Thu, 2 Sep 2021 11:17:07 +0200 Subject: [PATCH 29/82] Fix trouble case test --- tests/libslic3r/test_indexed_triangle_set.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/libslic3r/test_indexed_triangle_set.cpp b/tests/libslic3r/test_indexed_triangle_set.cpp index bbb22e778c..7e2d511c77 100644 --- a/tests/libslic3r/test_indexed_triangle_set.cpp +++ b/tests/libslic3r/test_indexed_triangle_set.cpp @@ -279,14 +279,23 @@ TEST_CASE("Simplify mesh by Quadric edge collapse to 5%", "[its]") CHECK(is_similar(its, mesh.its, cfg)); } +bool exist_triangle_with_twice_vertices(const std::vector& indices) +{ + for (const auto &face : indices) + if (face[0] == face[1] || + face[0] == face[2] || + face[1] == face[2]) return true; + return false; +} + TEST_CASE("Simplify trouble case", "[its]") { TriangleMesh tm = load_model("simplification.obj"); REQUIRE_FALSE(tm.empty()); float max_error = std::numeric_limits::max(); - uint32_t wanted_count = 8; + uint32_t wanted_count = 0; its_quadric_edge_collapse(tm.its, wanted_count, &max_error); - CHECK(tm.its.indices.size() <= 8); + CHECK(!exist_triangle_with_twice_vertices(tm.its.indices)); } TEST_CASE("Simplified cube should not be empty.", "[its]") From 746300eafd2a2655ca8d872cfdadd4d6577f9bb8 Mon Sep 17 00:00:00 2001 From: Filip Sykala Date: Thu, 2 Sep 2021 11:24:33 +0200 Subject: [PATCH 30/82] Fix @(Lukas Matena) note about using NDEBUG --- src/libslic3r/QuadricEdgeCollapse.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/libslic3r/QuadricEdgeCollapse.cpp b/src/libslic3r/QuadricEdgeCollapse.cpp index 6609879cd5..37cd6965de 100644 --- a/src/libslic3r/QuadricEdgeCollapse.cpp +++ b/src/libslic3r/QuadricEdgeCollapse.cpp @@ -7,10 +7,9 @@ using namespace Slic3r; -// Faster debug, comment when you want deep check #ifndef NDEBUG -#define NDEBUG -#endif // !NDEBUG +// #define EXPENSIVE_DEBUG_CHECKS +#endif // NDEBUG // only private namespace not neccessary be in .hpp namespace QuadricEdgeCollapse { @@ -100,12 +99,12 @@ namespace QuadricEdgeCollapse { const Triangle &t1, CopyEdgeInfos& infos, EdgeInfos &e_infos1); void compact(const VertexInfos &v_infos, const TriangleInfos &t_infos, const EdgeInfos &e_infos, indexed_triangle_set &its); -#ifndef NDEBUG +#ifdef EXPENSIVE_DEBUG_CHECKS void store_surround(const char *obj_filename, size_t triangle_index, int depth, const indexed_triangle_set &its, const VertexInfos &v_infos, const EdgeInfos &e_infos); bool check_neighbors(const indexed_triangle_set &its, const TriangleInfos &t_infos, const VertexInfos &v_infos, const EdgeInfos &e_infos); -#endif /* NDEBUG */ +#endif /* EXPENSIVE_DEBUG_CHECKS */ // constants --> may be move to config const uint32_t check_cancel_period = 16; // how many edge to reduce before call throw_on_cancel @@ -301,9 +300,9 @@ void Slic3r::its_quadric_edge_collapse( t_info1.set_deleted(); // triangle counter decrementation actual_triangle_count-=2; -#ifndef NDEBUG +#ifdef EXPENSIVE_DEBUG_CHECKS assert(check_neighbors(its, t_infos, v_infos, e_infos)); -#endif // NDEBUG +#endif // EXPENSIVE_DEBUG_CHECKS } // compact triangle @@ -815,7 +814,8 @@ void QuadricEdgeCollapse::compact(const VertexInfos & v_infos, its.indices.erase(its.indices.begin() + ti_new, its.indices.end()); } -#ifndef NDEBUG +#ifdef EXPENSIVE_DEBUG_CHECKS + // store triangle surrounding to file void QuadricEdgeCollapse::store_surround(const char *obj_filename, size_t triangle_index, @@ -925,4 +925,4 @@ bool QuadricEdgeCollapse::check_neighbors(const indexed_triangle_set &its, } return true; } -#endif /* NDEBUG */ +#endif /* EXPENSIVE_DEBUG_CHECKS */ From 3f923628aaf3a8700e2779e6ad4b7d80a42cc823 Mon Sep 17 00:00:00 2001 From: Filip Sykala Date: Thu, 2 Sep 2021 11:41:11 +0200 Subject: [PATCH 31/82] fix ../src/libslic3r/QuadricEdgeCollapse.cpp:628:21: warning: comparison of integer expressions of different signedness: 'const int' and 'uint32_t' {aka 'unsigned int'} [-Wsign-compare] ../src/libslic3r/QuadricEdgeCollapse.cpp:631:21: warning: comparison of integer expressions of different signedness: 'const int' and 'uint32_t' {aka 'unsigned int'} [-Wsign-compare] ../src/libslic3r/QuadricEdgeCollapse.cpp:638:48: warning: comparison of integer expressions of different signedness: 'const int' and 'uint32_t' {aka 'unsigned int'} [-Wsign-compare] ../src/libslic3r/QuadricEdgeCollapse.cpp:643:25: warning: comparison of integer expressions of different signedness: 'const int' and 'uint32_t' {aka 'unsigned int'} [-Wsign-compare] ../src/libslic3r/QuadricEdgeCollapse.cpp:647:25: warning: comparison of integer expressions of different signedness: 'const int' and 'uint32_t' {aka 'unsigned int'} [-Wsign-compare] --- src/libslic3r/QuadricEdgeCollapse.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/libslic3r/QuadricEdgeCollapse.cpp b/src/libslic3r/QuadricEdgeCollapse.cpp index 37cd6965de..7efe15bb24 100644 --- a/src/libslic3r/QuadricEdgeCollapse.cpp +++ b/src/libslic3r/QuadricEdgeCollapse.cpp @@ -624,26 +624,31 @@ bool QuadricEdgeCollapse::create_no_volume( const Triangle &t0 = indices[e_info0.t_index]; // edge CCW vertex indices are t0vi0, t0vi1 size_t t0i = 0; - if (t0[t0i] == vi0) ++t0i; - uint32_t t0vi0 = t0[t0i]; + uint32_t t0vi0 = static_cast(t0[t0i]); + if (t0vi0 == vi0) { + ++t0i; + t0vi0 = static_cast(t0[t0i]); + } ++t0i; - if (t0[t0i] == vi0) ++t0i; - uint32_t t0vi1 = t0[t0i]; - + uint32_t t0vi1 = static_cast(t0[t0i]); + if (t0vi1 == vi0) { + ++t0i; + t0vi1 = static_cast(t0[t0i]); + } for (size_t ei1 = v_info1.start; ei1 < v_info1_end; ++ei1) { const EdgeInfo &e_info1 = e_infos[ei1]; const Triangle &t1 = indices[e_info1.t_index]; size_t t1i = 0; - for (; t1i < 3; ++t1i) if (t1[t1i] == t0vi1) break; + for (; t1i < 3; ++t1i) if (static_cast(t1[t1i]) == t0vi1) break; if (t1i >= 3) continue; // without vertex index from triangle 0 // check if second index is same too ++t1i; if (t1i == 3) t1i = 0; // triangle loop(modulo 3) - if (t1[t1i] == vi1) { + if (static_cast(t1[t1i]) == vi1) { ++t1i; if (t1i == 3) t1i = 0; // triangle loop(modulo 3) } - if (t1[t1i] == t0vi0) return true; + if (static_cast(t1[t1i]) == t0vi0) return true; } } return false; From b20bd26e84f9a31a56a14c5372d9c285908ca667 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Mat=C4=9Bna?= <33929324+lukasmatena@users.noreply.github.com> Date: Thu, 2 Sep 2021 12:27:07 +0200 Subject: [PATCH 32/82] Update How to build - Linux et al.md --- doc/How to build - Linux et al.md | 120 +++++++++++++++++------------- 1 file changed, 67 insertions(+), 53 deletions(-) diff --git a/doc/How to build - Linux et al.md b/doc/How to build - Linux et al.md index 559536f143..704ceb46aa 100644 --- a/doc/How to build - Linux et al.md +++ b/doc/How to build - Linux et al.md @@ -1,87 +1,101 @@ # Building PrusaSlicer on UNIX/Linux -Please understand that PrusaSlicer team cannot support compilation on all possible Linux distros. Namely, we cannot help trouble shooting OpenGL driver issues or dependency issues if compiled against distro provided libraries. We can only support PrusaSlicer compiled the same way we do compile PrusaSlicer for our [binary builds](https://github.com/prusa3d/PrusaSlicer/releases), that means linked statically agains the dependencies compiled with the `deps` scripts. +Please understand that PrusaSlicer team cannot support compilation on all possible Linux distros. Namely, we cannot help troubleshoot OpenGL driver issues or dependency issues if compiled against distro provided libraries. **We can only support PrusaSlicer statically linked against the dependencies compiled with the `deps` scripts**, the same way we compile PrusaSlicer for our [binary builds](https://github.com/prusa3d/PrusaSlicer/releases). -Instead of compiling PrusaSlicer from source code, one may consider to install PrusaSlicer [pre-compiled by contributors](https://github.com/prusa3d/PrusaSlicer/wiki/PrusaSlicer-on-Linux---binary-distributions). +If you have some reason to link dynamically to your system libraries, you are free to do so, but we can not and will not troubleshoot any issues you possibly run into. -### How to build +Instead of compiling PrusaSlicer from source code, one may also consider to install PrusaSlicer [pre-compiled by contributors](https://github.com/prusa3d/PrusaSlicer/wiki/PrusaSlicer-on-Linux---binary-distributions). -PrusaSlicer uses the CMake build system and requires several dependencies. -The dependencies can be listed in the `deps` directory in individual subdirectories, although they don't necessarily need to be as recent -as the versions listed - generally versions available on conservative Linux distros such as Debian stable, Ubuntu LTS releases or Fedora are likely sufficient. +## Step by step guide -Perl is not required anymore. +This guide describes building PrusaSlicer statically against dependencies pulled by our `deps` script. Running all the listed commands in order should result in successful build. -In a typical situation, one would open a command line, go to the PrusaSlicer sources (**the root directory of the repository**), create a directory called `build` or similar, -`cd` into it and call: +#### 0. Prerequisities +You must have CMake, GNU build tools and git. If you don't already have them, install them as usual from your distribution packages (e.g. on Ubuntu, you would run `sudo apt-get install cmake build-essential git`, etc.) + +#### 1. Cloning the repository + + +Cloning the repository is simple thanks to git and Github. Simply `cd` into wherever you want to clone PrusaSlicer code base and run +``` +git clone https://www.github.com/prusa3d/PrusaSlicer +cd PrusaSlicer +``` +This will download the source code into a new directory and `cd` into it. You can now optionally select a tag/branch/commit to build using `git checkout`. Otherwise, `master` branch will be built. + + +#### 2. Building dependencies + +PrusaSlicer uses CMake and the build is quite simple, the only tricky part is resolution of dependencies. The supported and recommended way is to build the dependencies first and link to them statically. The source base contains a CMake script that automatically downloads and builds the required dependencies. All that is needed is to run the following (from the top of the cloned repository): + + cd deps + mkdir build + cd build cmake .. - make -jN + make + cd ../.. -where `N` is the number of CPU cores available. -Additional CMake flags may be applicable as explained below. +**Warning**: Once the dependency bundle is installed in a destdir, the destdir cannot be moved elsewhere. This is because wxWidgets hardcode the installation path. -### Dependency resolution -By default PrusaSlicer looks for dependencies the default way CMake looks for them, i.e. in default system locations. -On Linux this will typically make PrusaSlicer depend on dynamically loaded libraries from the system, however, PrusaSlicer can be told -to specifically look for static libraries with the `SLIC3R_STATIC` flag passed to cmake: +#### 3. Building PrusaSlicer - cmake .. -DSLIC3R_STATIC=1 +Now when you have the dependencies compiled, all that is needed is to tell CMake that we are interested in static build and point it to the dependencies. From the top of the repository, run -Additionally, PrusaSlicer can be built in a static manner mostly independent of the system libraries with a dependencies bundle -created using CMake script in the `deps` directory (these are not interconnected with the rest of the CMake scripts). + mkdir build + cd build + cmake .. -DSLIC3R_STATIC=1 -DSLIC3R_PCH=OFF -DCMAKE_PREFIX_PATH=$(pwd)/../deps/build/destdir/usr/local + make -j4 -Note: We say _mostly independent_ because it's still expected the system will provide some transitive dependencies, such as GTK for wxWidgets. +And that's it. You can now run the freshly built PrusaSlicer binary: -To do this, go to the `deps` directory, create a `build` subdirectory (or the like) and use: + cd src + ./prusa-slicer - cmake .. -DDESTDIR= -DDEP_DOWNLOAD_DIR= -where the target destdir is a directory of your choosing where the dependencies will be installed. -You can also omit the `DESTDIR` option to use the default, in that case the `destdir` will be created inside the `build` directory where `cmake` is run. The optional `DEP_DOWNLOAD_DIR` argument specifies a directory to cache the downloaded -source packages for each dependent library. Can be useful for repeated builds, to avoid unnecessary network traffic. -Once the dependencies have been built, in order to pass the destdir path to the **top-level** PrusaSlicer `CMakeLists.txt` script, use the `CMAKE_PREFIX_PATH` option along with turning on `SLIC3R_STATIC`: +#### Troubleshooting - cmake .. -DSLIC3R_STATIC=1 -DCMAKE_PREFIX_PATH=/usr/local +Although most of the dependencies are handled by the build script, we still rely on some system libraries (such as GTK, GL, etc). It is quite likely that you have them already installed, but in case that CMake reports any library missing, install the respective package from your distribution and run CMake again. -Note that `/usr/local` needs to be appended to the destdir path and also the prefix path should be absolute. -**Warning**: Once the dependency bundle is installed in a destdir, the destdir cannot be moved elsewhere. -This is because wxWidgets hardcode the installation path. +## Useful CMake flags when building dependencies -### wxWidgets version +- `-DDESTDIR=` allows to specify a directory where the dependencies will be installed. When not provided, the script creates and uses `destdir` directory where cmake is run. -By default, PrusaSlicer looks for wxWidgets 3.1, this is because the 3.1 version has -a number of bugfixes and improvements not found in 3.0. However, it can also be built with wxWidgets 3.0. -This is done by passing this option to CMake: +- `-DDEP_DOWNLOAD_DIR=` specifies a directory to cache the downloaded source packages for each library. Can be useful for repeated builds, to avoid unnecessary network traffic. - -DSLIC3R_WX_STABLE=1 -Note that PrusaSlicer is tested with wxWidgets 3.0 somewhat sporadically and so there may be bugs in bleeding edge releases. +## Useful CMake flags when building PrusaSlicer +- `-DSLIC3R_ASAN=ON` enables gcc/clang address sanitizer (defaults to `OFF`, requires gcc>4.8 or clang>3.1) +- `-DSLIC3R_GTK=3` to use GTK3 (defaults to `2`) +- `-DSLIC3R_STATIC=ON` for static build (defaults to `OFF`) +- `-DSLIC3R_WX_STABLE=ON` to look for wxWidgets 3.0 (defaults to `OFF`) +- `-DCMAKE_BUILD_TYPE=Debug` to build in debug mode (defaults to `Release`) + +See the CMake files to get the complete list. + + + +## Building dynamically + +As already mentioned above, dynamic linking of dependencies is possible, but PrusaSlicer team is unable to troubleshoot (Linux world is way too complex). Feel free to do so, but you are on your own. Several remarks though: + +The list of dependencies can be easily obtained by inspecting the CMake scripts in the `deps/` directory. Many don't necessarily need to be as recent +as the versions listed - generally versions available on conservative Linux distros such as Debian stable, Ubuntu LTS releases or Fedora are likely sufficient. If you decide to build this way, it is your responsibility to make sure that CMake finds all required dependencies. It is possible to look at your distribution PrusaSlicer package to see how the package maintainers solved the dependency issues. + +#### wxWidgets +By default, PrusaSlicer looks for wxWidgets 3.1. Our build script in fact downloads specific patched version of wxWidgets. If you want to link against wxWidgets 3.0 (which are still provided by most distributions because wxWidgets 3.1 have not yet been declared stable), you must set `-DSLIC3R_WX_STABLE=ON` when running CMake. Note that while PrusaSlicer can be linked against wWidgets 3.0, the combination is not well tested and there might be bugs in the resulting application. When building on ubuntu 20.04 focal fossa, the package libwxgtk3.0-gtk3-dev needs to be installed instead of libwxgtk3.0-dev and you should use: +``` +-DSLIC3R_WX_STABLE=1 -DSLIC3R_GTK=3 +``` - -DSLIC3R_WX_STABLE=1 -DSLIC3R_GTK=3 - -### Build variant - -By default PrusaSlicer builds the release variant. -To create a debug build, use the following CMake flag: - - -DCMAKE_BUILD_TYPE=Debug - -### Enabling address sanitizer - -If you're using GCC/Clang compiler, it is possible to build PrusaSlicer with the built-in address sanitizer enabled to help detect memory-corruption issues. -To enable it, simply use the following CMake flag: - - -DSLIC3R_ASAN=1 - -This requires GCC>4.8 or Clang>3.1. +## Miscellaneous ### Installation From b69d03ad4abbe324683f1e751a3caaef6a8d61f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Mat=C4=9Bna?= <33929324+lukasmatena@users.noreply.github.com> Date: Thu, 2 Sep 2021 12:56:24 +0200 Subject: [PATCH 33/82] Update How to build - Linux et al.md --- doc/How to build - Linux et al.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/How to build - Linux et al.md b/doc/How to build - Linux et al.md index 704ceb46aa..090a97e6c3 100644 --- a/doc/How to build - Linux et al.md +++ b/doc/How to build - Linux et al.md @@ -68,10 +68,12 @@ Although most of the dependencies are handled by the build script, we still rely - `-DDEP_DOWNLOAD_DIR=` specifies a directory to cache the downloaded source packages for each library. Can be useful for repeated builds, to avoid unnecessary network traffic. +- `-DDEP_WX_GTK3=ON` builds wxWidgets (one of the dependencies) against GTK3 (defaults to OFF) + ## Useful CMake flags when building PrusaSlicer - `-DSLIC3R_ASAN=ON` enables gcc/clang address sanitizer (defaults to `OFF`, requires gcc>4.8 or clang>3.1) -- `-DSLIC3R_GTK=3` to use GTK3 (defaults to `2`) +- `-DSLIC3R_GTK=3` to use GTK3 (defaults to `2`). Note that wxWidgets must be built against the same GTK version. - `-DSLIC3R_STATIC=ON` for static build (defaults to `OFF`) - `-DSLIC3R_WX_STABLE=ON` to look for wxWidgets 3.0 (defaults to `OFF`) - `-DCMAKE_BUILD_TYPE=Debug` to build in debug mode (defaults to `Release`) From cc480afe9b54b3126bafb37f2afa785a9cda0303 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 2 Sep 2021 13:42:37 +0200 Subject: [PATCH 34/82] Fixed build when tech ENABLE_GCODE_VIEWER_STATISTICS is enabled --- src/slic3r/GUI/GCodeViewer.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index e6e391d370..3fc6242648 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -2665,7 +2665,11 @@ void GCodeViewer::render_toolpaths() }; #if ENABLE_SEAMS_USING_MODELS +#if ENABLE_GCODE_VIEWER_STATISTICS + auto render_as_instanced_model = [this] +#else auto render_as_instanced_model = [] +#endif // ENABLE_GCODE_VIEWER_STATISTICS (TBuffer& buffer, GLShaderProgram & shader) { for (auto& range : buffer.model.instances.render_ranges.ranges) { if (range.vbo == 0 && range.count > 0) { From 0efa0fc512094d134fca71b1961ef2d6d9f638aa Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 2 Sep 2021 14:20:04 +0200 Subject: [PATCH 35/82] Fixed a crash when 'Repair by Netfabb' was called with multiple object selection, the bug was introduced with 1eebaa4 and possibly manifested in other scenarios as well. --- src/slic3r/GUI/GUI_ObjectList.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 737c840834..096836f23e 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -2561,6 +2561,9 @@ wxDataViewItem ObjectList::add_settings_item(wxDataViewItem parent_item, const D void ObjectList::update_info_items(size_t obj_idx, wxDataViewItemArray* selections/* = nullptr*/, bool added_object/* = false*/) { + if (obj_idx >= m_objects->size()) + return; + const ModelObject* model_object = (*m_objects)[obj_idx]; wxDataViewItem item_obj = m_objects_model->GetItemById(obj_idx); assert(item_obj.IsOk()); From 18c8204837502d3103f793e863c44c6bdc7eca93 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 2 Sep 2021 14:37:29 +0200 Subject: [PATCH 36/82] Fix of #6873: Bed texture located in a directory that user has no permission to (crashed) --- src/slic3r/GUI/3DBed.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp index 7b08b5f793..eaf75ba5b6 100644 --- a/src/slic3r/GUI/3DBed.cpp +++ b/src/slic3r/GUI/3DBed.cpp @@ -141,11 +141,13 @@ void Bed3D::Axes::render() const bool Bed3D::set_shape(const Pointfs& shape, const std::string& custom_texture, const std::string& custom_model, bool force_as_custom) { auto check_texture = [](const std::string& texture) { - return !texture.empty() && (boost::algorithm::iends_with(texture, ".png") || boost::algorithm::iends_with(texture, ".svg")) && boost::filesystem::exists(texture); + boost::system::error_code ec; // so the exists call does not throw (e.g. after a permission problem) + return !texture.empty() && (boost::algorithm::iends_with(texture, ".png") || boost::algorithm::iends_with(texture, ".svg")) && boost::filesystem::exists(texture, ec); }; auto check_model = [](const std::string& model) { - return !model.empty() && boost::algorithm::iends_with(model, ".stl") && boost::filesystem::exists(model); + boost::system::error_code ec; + return !model.empty() && boost::algorithm::iends_with(model, ".stl") && boost::filesystem::exists(model, ec); }; EType type; From 298825672bf985b7467fe4cb033db1835d9abd88 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 2 Sep 2021 15:18:05 +0200 Subject: [PATCH 37/82] Fix painted seam on vertical surfaces (broken since 8dfc042) --- src/libslic3r/PrintObject.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index f0eaa982ab..29b2ece41e 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -2294,13 +2294,12 @@ void PrintObject::project_and_append_custom_facets( ? mv->seam_facets.get_facets_strict(*mv, type) : mv->supported_facets.get_facets_strict(*mv, type); if (! custom_facets.indices.empty()) -#if 0 - project_triangles_to_slabs(this->layers(), custom_facets, - (this->trafo_centered() * mv->get_matrix()).cast(), - seam, out); -#else - slice_mesh_slabs(custom_facets, zs_from_layers(this->layers()), this->trafo_centered() * mv->get_matrix(), nullptr, &out, [](){}); -#endif + if (seam) + project_triangles_to_slabs(this->layers(), custom_facets, + (this->trafo_centered() * mv->get_matrix()).cast(), + seam, out); + else + slice_mesh_slabs(custom_facets, zs_from_layers(this->layers()), this->trafo_centered() * mv->get_matrix(), nullptr, &out, [](){}); } } From d89f01c71795e324f510939e2cece05b9586291c Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Thu, 2 Sep 2021 16:29:21 +0200 Subject: [PATCH 38/82] Fix of "Support on build plate only" no longer overridden by support painting (#6863) This is a regression to a late PrusaSlicer 2.4.0-alpha0 change 8dfc0422a878c5e44d4233c6ce522c77a0c3280f Faster and hopefully more reliable projection of paint-on support blockers and enforcers on a sliced mesh. --- src/libslic3r/PrintObject.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 29b2ece41e..526b7b874a 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -2298,8 +2298,11 @@ void PrintObject::project_and_append_custom_facets( project_triangles_to_slabs(this->layers(), custom_facets, (this->trafo_centered() * mv->get_matrix()).cast(), seam, out); - else - slice_mesh_slabs(custom_facets, zs_from_layers(this->layers()), this->trafo_centered() * mv->get_matrix(), nullptr, &out, [](){}); + else { + std::vector projected; + slice_mesh_slabs(custom_facets, zs_from_layers(this->layers()), this->trafo_centered() * mv->get_matrix(), nullptr, &projected, [](){}); + append(out, std::move(projected)); + } } } From 7c074d5a99c762064634088bf945637eef441bda Mon Sep 17 00:00:00 2001 From: Jason Scurtu Date: Thu, 2 Sep 2021 16:40:17 +0200 Subject: [PATCH 39/82] update PrusaSlicer icon for macOS (#6874) --- resources/icons/PrusaSlicer.icns | Bin 225060 -> 299502 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/resources/icons/PrusaSlicer.icns b/resources/icons/PrusaSlicer.icns index 051477dc37bf1556d700d89c58939b905ced40a0..5f6a7feb273e962489ed01e55d1be856c1c76a8c 100644 GIT binary patch literal 299502 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Ð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
qAKHr@(6HPqhhg=* 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 AmjD0& literal 225060 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 z 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 CVr Date: Thu, 2 Sep 2021 16:41:50 +0200 Subject: [PATCH 40/82] Flatpak changes for 2.4 (#6875) * add gcodeviewer desktop file * update metainfo * add actions for GCodeViewer + DE translation --- ...om.prusa3d.PrusaSlicer.GCodeViewer.desktop | 10 +++++ .../flatpak/com.prusa3d.PrusaSlicer.desktop | 10 ++++- .../com.prusa3d.PrusaSlicer.metainfo.xml | 44 +++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 src/platform/unix/flatpak/com.prusa3d.PrusaSlicer.GCodeViewer.desktop diff --git a/src/platform/unix/flatpak/com.prusa3d.PrusaSlicer.GCodeViewer.desktop b/src/platform/unix/flatpak/com.prusa3d.PrusaSlicer.GCodeViewer.desktop new file mode 100644 index 0000000000..3177854734 --- /dev/null +++ b/src/platform/unix/flatpak/com.prusa3d.PrusaSlicer.GCodeViewer.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Name=Prusa GCode viewer +Name[de]=Prusa GCode Vorschau +Exec=prusa-slicer --gcodeviewer %F +Icon=com.prusa3d.PrusaSlicer.GCodeViewer +Terminal=false +Type=Application +MimeType=text/x.gcode; +Categories=Graphics;3DGraphics; +Keywords=3D;Printing;Slicer; diff --git a/src/platform/unix/flatpak/com.prusa3d.PrusaSlicer.desktop b/src/platform/unix/flatpak/com.prusa3d.PrusaSlicer.desktop index 8987222984..1ea3e157e7 100755 --- a/src/platform/unix/flatpak/com.prusa3d.PrusaSlicer.desktop +++ b/src/platform/unix/flatpak/com.prusa3d.PrusaSlicer.desktop @@ -1,5 +1,6 @@ [Desktop Entry] Name=PrusaSlicer +Name[de]=PrusaSlicer GenericName=3D Printing Software Icon=com.prusa3d.PrusaSlicer Exec=prusa-slicer %F @@ -9,4 +10,11 @@ MimeType=model/stl;model/x-wavefront-obj;model/3mf;model/x-geomview-off;applicat Categories=Graphics;3DGraphics;Engineering; Keywords=3D;Printing;Slicer;slice;3D;printer;convert;gcode;stl;obj;amf;SLA StartupNotify=false -StartupWMClass=prusa-slicer \ No newline at end of file +StartupWMClass=prusa-slicer +Actions=GCodeViewer; + +[Desktop Action GCodeViewer] +Exec=prusa-slicer --gcodeviewer %F +Name=G-Code Viewer +Name[de]=G-Code Vorschau +Icon=com.prusa3d.PrusaSlicer.GCodeViewer diff --git a/src/platform/unix/flatpak/com.prusa3d.PrusaSlicer.metainfo.xml b/src/platform/unix/flatpak/com.prusa3d.PrusaSlicer.metainfo.xml index b62a57e480..c37f43d69f 100755 --- a/src/platform/unix/flatpak/com.prusa3d.PrusaSlicer.metainfo.xml +++ b/src/platform/unix/flatpak/com.prusa3d.PrusaSlicer.metainfo.xml @@ -50,6 +50,50 @@ + + +

This is the first alpha release of PrusaSlicer 2.4.0, introducing Multi-material painting tool, improved FDM supports and raft, + Windows dark mode, Fuzzy Skin, per object Brim configuration, Negative volumes, automatic Color Print for signs, Shape Gallery, + "Tip of the day" notifications, Model simplification, support for Marlin 2 acceleration control, support of 3DLabPrint airplane models, + new 3rd party printer profiles and many more new features, improvements and bugfixes.

+
+
+ + +

PrusaSlicer 2.3.3 is a patch release following PrusaSlicer 2.3.2 release, fixing an unfortunate bug in handling FDM multi-material + project and configuration files #6711.

+
+
+ + +

This is a final release of PrusaSlicer 2.3.2, following 2.3.2-beta and 2.3.2-rc. + For the new features in the 2.3.2 series, please read the change logs of the beta and release candidate. + The final release is functionally equal to the release candidate, with a single additional improvement: + Before installing profile updates, a configuration snapshot is taken. In rare circumstances when the current configuration is not consistent, + taking a configuration snapshot fails. PrusaSlicer 2.3.2 newly informs about the issue and offers either to install the configuration updates + even if taking the configuration snapshot failed or to abort update of the profiles.

+
+
+ + +

This a final release of PrusaSlicer 2.3.1, introducing native builds for the new Apple Silicon MacBooks, Chrome OS support, performance improvements + in G-code rendering, security fixes and new 3rd party printer profiles. For full changelog on PrusaSlicer 2.3.1 series, please check the PrusaSlicer + 2.3.1-rc change log.

+
+
+ + +

This a final release of PrusaSlicer 2.3.0, introducing paint-on supports, ironing, monotonic infill, seam painting, adaptive and support cubic infill, + print time per feature analysis, standalone G-code viewer application, better auto-arrange with a customizable gap and rotation, + search function for the settings, reworked "Avoid crossing perimeters" function, physical printers (network settings), + many new 3rd party printer profiles and much, much more.

+
+
+ + +

Development/Unstable Snapshot

+
+

This is final release of PrusaSlicer 2.2.0 introducing SLA hollowing and hole drilling, support for 3rd party printer vendors, 3Dconnexion support, From e630332e245b4773beea7c77b54c1062c7a3b3b9 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Fri, 3 Sep 2021 09:28:02 +0200 Subject: [PATCH 41/82] Added SS2OSD.dll to blacklist. Raises warning dialog for issue #6864 --- src/libslic3r/BlacklistedLibraryCheck.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/BlacklistedLibraryCheck.cpp b/src/libslic3r/BlacklistedLibraryCheck.cpp index 3d2ee34827..d9dea188f5 100644 --- a/src/libslic3r/BlacklistedLibraryCheck.cpp +++ b/src/libslic3r/BlacklistedLibraryCheck.cpp @@ -12,7 +12,7 @@ namespace Slic3r { #ifdef WIN32 //only dll name with .dll suffix - currently case sensitive -const std::vector BlacklistedLibraryCheck::blacklist({ L"NahimicOSD.dll" }); +const std::vector BlacklistedLibraryCheck::blacklist({ L"NahimicOSD.dll", L"SS2OSD.dll" }); bool BlacklistedLibraryCheck::get_blacklisted(std::vector& names) { From cd4155a890d6a69e749e0079fb0d86c4d5a7a397 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Fri, 3 Sep 2021 10:19:06 +0200 Subject: [PATCH 42/82] Hints.cereal file existence check --- src/slic3r/GUI/HintNotification.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/HintNotification.cpp b/src/slic3r/GUI/HintNotification.cpp index 33ccdc4ae3..fe5eeb67c2 100644 --- a/src/slic3r/GUI/HintNotification.cpp +++ b/src/slic3r/GUI/HintNotification.cpp @@ -74,7 +74,12 @@ void write_used_binary(const std::vector& ids) } void read_used_binary(std::vector& ids) { - boost::filesystem::ifstream file((boost::filesystem::path(data_dir()) / "cache" / "hints.cereal")); + boost::filesystem::path path(boost::filesystem::path(data_dir()) / "cache" / "hints.cereal"); + if (!boost::filesystem::exists(path)) { + BOOST_LOG_TRIVIAL(warning) << "Failed to load to hints.cereal. File does not exists. " << path.string(); + return; + } + boost::filesystem::ifstream file(path); cereal::BinaryInputArchive archive(file); HintsCerealData cd; try From 79784d1a2e3772b51c661a2dc144f7ea142acbb5 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Fri, 3 Sep 2021 11:45:01 +0200 Subject: [PATCH 43/82] Fix of "Support on build plate only" no longer overridden by support painting (#6863) This is a regression to a late PrusaSlicer 2.4.0-alpha0 change 8dfc0422a878c5e44d4233c6ce522c77a0c3280f Faster and hopefully more reliable projection of paint-on support blockers and enforcers on a sliced mesh. Previous d89f01c71795e324f510939e2cece05b9586291c did not fix it. --- src/libslic3r/PrintObject.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 526b7b874a..808bdd8a1b 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -2301,7 +2301,14 @@ void PrintObject::project_and_append_custom_facets( else { std::vector projected; slice_mesh_slabs(custom_facets, zs_from_layers(this->layers()), this->trafo_centered() * mv->get_matrix(), nullptr, &projected, [](){}); - append(out, std::move(projected)); + // Merge these projections with the output, layer by layer. + assert(! projected.empty()); + assert(out.empty() || out.size() == projected.size()); + if (out.empty()) + out = std::move(projected); + else + for (size_t i = 0; i < out.size(); ++ i) + append(out[i], std::move(projected[i])); } } } From ed7ebf15d97970597d871ea31b464e6538354529 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 3 Sep 2021 12:13:01 +0200 Subject: [PATCH 44/82] Added logging when bed texture/model is not found --- src/libslic3r/PrintObject.cpp | 3 ++- src/slic3r/GUI/3DBed.cpp | 8 ++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 808bdd8a1b..d9a4f2670a 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -2293,7 +2293,7 @@ void PrintObject::project_and_append_custom_facets( const indexed_triangle_set custom_facets = seam ? mv->seam_facets.get_facets_strict(*mv, type) : mv->supported_facets.get_facets_strict(*mv, type); - if (! custom_facets.indices.empty()) + if (! custom_facets.indices.empty()) { if (seam) project_triangles_to_slabs(this->layers(), custom_facets, (this->trafo_centered() * mv->get_matrix()).cast(), @@ -2310,6 +2310,7 @@ void PrintObject::project_and_append_custom_facets( for (size_t i = 0; i < out.size(); ++ i) append(out[i], std::move(projected[i])); } + } } } diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp index eaf75ba5b6..5b7218c87e 100644 --- a/src/slic3r/GUI/3DBed.cpp +++ b/src/slic3r/GUI/3DBed.cpp @@ -163,12 +163,16 @@ bool Bed3D::set_shape(const Pointfs& shape, const std::string& custom_texture, c } std::string texture_filename = custom_texture.empty() ? texture : custom_texture; - if (!check_texture(texture_filename)) + if (! texture_filename.empty() && ! check_texture(texture_filename)) { + BOOST_LOG_TRIVIAL(error) << "Unable to load bed texture: " << texture_filename; texture_filename.clear(); + } std::string model_filename = custom_model.empty() ? model : custom_model; - if (!check_model(model_filename)) + if (! model_filename.empty() && ! check_model(model_filename)) { + BOOST_LOG_TRIVIAL(error) << "Unable to load bed model: " << model_filename; model_filename.clear(); + } if (m_shape == shape && m_type == type && m_texture_filename == texture_filename && m_model_filename == model_filename) // No change, no need to update the UI. From 4c80d9ed01bc0fdcda9235224f50caeb77d86d77 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 27 Aug 2021 09:04:15 +0200 Subject: [PATCH 45/82] Fix taking entering/leaving snapshots in SLA gizmo: This was broken between 2.2.0 and 2.3.0. The 'entering' snapshot should be taken before the gizmo opens, not after. Otherwise it is in fact the same as the next snapshot. --- src/slic3r/GUI/Gizmos/GLGizmoBase.hpp | 1 + src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 11 ------- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp | 2 ++ src/slic3r/GUI/Gizmos/GLGizmosManager.cpp | 34 +++++++++++--------- 4 files changed, 22 insertions(+), 26 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp index 8b033ce732..1c6e00c070 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp @@ -135,6 +135,7 @@ public: bool is_activable() const { return on_is_activable(); } bool is_selectable() const { return on_is_selectable(); } CommonGizmosDataID get_requirements() const { return on_get_requirements(); } + virtual bool wants_enter_leave_snapshots() const { return false; } void set_common_data_pool(CommonGizmosDataPool* ptr) { m_c = ptr; } unsigned int get_sprite_id() const { return m_sprite_id; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 8c90d20d31..c7faab3bf5 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -901,15 +901,6 @@ void GLGizmoSlaSupports::on_set_state() return; if (m_state == On && m_old_state != On) { // the gizmo was just turned on - if (! m_parent.get_gizmos_manager().is_serializing()) { - // Only take the snapshot when the USER opens the gizmo. Common gizmos - // data are not yet available, the CallAfter will postpone taking the - // snapshot until they are. No, it does not feel right. - wxGetApp().CallAfter([]() { - Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Entering SLA gizmo")); - }); - } - // Set default head diameter from config. const DynamicPrintConfig& cfg = wxGetApp().preset_bundle->sla_prints.get_edited_preset().config; m_new_point_head_diameter = static_cast(cfg.option("support_head_front_diameter"))->value; @@ -925,8 +916,6 @@ void GLGizmoSlaSupports::on_set_state() else { // we are actually shutting down disable_editing_mode(); // so it is not active next time the gizmo opens - Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Leaving SLA gizmo")); - m_normal_cache.clear(); m_old_mo_id = -1; } } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp index cb60c0e258..8e30aa6b85 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp @@ -67,6 +67,8 @@ public: bool has_backend_supports() const; void reslice_SLA_supports(bool postpone_error_messages = false) const; + bool wants_enter_leave_snapshots() const override { return true; } + private: bool on_init() override; void on_update(const UpdateData& data) override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index 6d9a039772..080991859b 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -22,6 +22,7 @@ #include "slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp" #include "slic3r/GUI/Gizmos/GLGizmoSimplify.hpp" +#include "libslic3r/format.hpp" #include "libslic3r/Model.hpp" #include "libslic3r/PresetBundle.hpp" @@ -1198,26 +1199,29 @@ void GLGizmosManager::activate_gizmo(EType type) if (m_gizmos.empty() || m_current == type) return; - if (m_current != Undefined) { - m_gizmos[m_current]->set_state(GLGizmoBase::Off); - if (m_gizmos[m_current]->get_state() != GLGizmoBase::Off) + GLGizmoBase* old_gizmo = m_current == Undefined ? nullptr : m_gizmos[m_current].get(); + GLGizmoBase* new_gizmo = type == Undefined ? nullptr : m_gizmos[type].get(); + + if (old_gizmo) { + old_gizmo->set_state(GLGizmoBase::Off); + if (old_gizmo->get_state() != GLGizmoBase::Off) return; // gizmo refused to be turned off, do nothing. + + if (! m_parent.get_gizmos_manager().is_serializing() + && old_gizmo->wants_enter_leave_snapshots()) + Plater::TakeSnapshot snapshot(wxGetApp().plater(), + Slic3r::format(_utf8("Leaving %1%"), old_gizmo->get_name())); } + if (new_gizmo && ! m_parent.get_gizmos_manager().is_serializing() + && new_gizmo->wants_enter_leave_snapshots()) + Plater::TakeSnapshot snapshot(wxGetApp().plater(), + Slic3r::format(_utf8("Entering %1%"), new_gizmo->get_name())); + m_current = type; - // Updating common data should be left to the update_data function, which - // is always called after this one. activate_gizmo can be called by undo/redo, - // when selection is not yet deserialized, so the common data would update - // incorrectly (or crash if relying on unempty selection). Undo/redo stack - // will also call update_data, after selection is restored. - - //m_common_gizmos_data->update(get_current() - // ? get_current()->get_requirements() - // : CommonGizmosDataID(0)); - - if (type != Undefined) - m_gizmos[type]->set_state(GLGizmoBase::On); + if (new_gizmo) + new_gizmo->set_state(GLGizmoBase::On); } From a4300b8e6411d42ce73f3ff2cd23785a3f172d8f Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 27 Aug 2021 09:04:33 +0200 Subject: [PATCH 46/82] Naming of the entering/leaving snapshots is now more generic, it uses the actual name of the gizmo. Also, the keyboard shortcut is now appended to the name, instead of being duplicated in it. --- src/slic3r/GUI/Gizmos/GLGizmoBase.cpp | 14 ++++++++++++++ src/slic3r/GUI/Gizmos/GLGizmoBase.hpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoCut.cpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp | 4 ++-- src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp | 4 ++-- src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp | 4 ++-- src/slic3r/GUI/Gizmos/GLGizmoMove.cpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoScale.cpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp | 4 ++-- src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp | 4 ++-- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 4 ++-- src/slic3r/GUI/Gizmos/GLGizmosManager.cpp | 4 ++-- 14 files changed, 34 insertions(+), 20 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index cc089e26ef..64479a39e2 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -232,6 +232,20 @@ void GLGizmoBase::render_input_window(float x, float y, float bottom_limit) } } + + +std::string GLGizmoBase::get_name(bool include_shortcut) const +{ + int key = get_shortcut_key(); + assert( key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z); + std::string out = on_get_name(); + if (include_shortcut) + out += std::string(" [") + char(int('A') + key - int(WXK_CONTROL_A)) + "]"; + return out; +} + + + // Produce an alpha channel checksum for the red green blue components. The alpha channel may then be used to verify, whether the rgb components // were not interpolated by alpha blending or multi sampling. unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char green, unsigned char blue) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp index 1c6e00c070..05f6adb5e8 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp @@ -120,7 +120,7 @@ public: void load(cereal::BinaryInputArchive& ar) { m_state = On; on_load(ar); } void save(cereal::BinaryOutputArchive& ar) const { on_save(ar); } - std::string get_name() const { return on_get_name(); } + std::string get_name(bool include_shortcut = true) const; int get_group_id() const { return m_group_id; } void set_group_id(int id) { m_group_id = id; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index 641258ca44..3dcb9e2b10 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -49,7 +49,7 @@ bool GLGizmoCut::on_init() std::string GLGizmoCut::on_get_name() const { - return (_L("Cut") + " [C]").ToUTF8().data(); + return _u8L("Cut"); } void GLGizmoCut::on_set_state() diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index 99c010bf1d..1ebba4d11f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -28,7 +28,7 @@ void GLGizmoFdmSupports::on_shutdown() std::string GLGizmoFdmSupports::on_get_name() const { - return (_L("Paint-on supports") + " [L]").ToUTF8().data(); + return _u8L("Paint-on supports"); } @@ -85,7 +85,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l y = std::min(y, bottom_limit - approx_height); m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); - m_imgui->begin(on_get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse); + m_imgui->begin(get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse); // First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that: const float clipping_slider_left = std::max(m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x, diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp index 3e5c12eec4..b8c7d9f92e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp @@ -37,7 +37,7 @@ CommonGizmosDataID GLGizmoFlatten::on_get_requirements() const std::string GLGizmoFlatten::on_get_name() const { - return (_L("Place on face") + " [F]").ToUTF8().data(); + return _u8L("Place on face"); } bool GLGizmoFlatten::on_is_activable() const diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index 05e0be1410..f405f457d1 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -505,7 +505,7 @@ RENDER_AGAIN: y = std::min(y, bottom_limit - approx_height); m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); - m_imgui->begin(on_get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse); + m_imgui->begin(get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse); // First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that: const float settings_sliders_left = @@ -773,7 +773,7 @@ bool GLGizmoHollow::on_is_selectable() const std::string GLGizmoHollow::on_get_name() const { - return (_(L("Hollow and drill")) + " [H]").ToUTF8().data(); + return _u8L("Hollow and drill"); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index a30ac377e8..608e7bd1fa 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -42,7 +42,7 @@ void GLGizmoMmuSegmentation::on_shutdown() std::string GLGizmoMmuSegmentation::on_get_name() const { // FIXME Lukas H.: Discuss and change shortcut - return (_L("Multimaterial painting") + " [N]").ToUTF8().data(); + return _u8L("Multimaterial painting"); } bool GLGizmoMmuSegmentation::on_is_selectable() const @@ -239,7 +239,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott y = std::min(y, bottom_limit - approx_height); m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); - m_imgui->begin(on_get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse); + m_imgui->begin(get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse); // First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that: const float clipping_slider_left = std::max(m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x, diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp index 9a056adcb3..e7b6a0ad6e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp @@ -52,7 +52,7 @@ bool GLGizmoMove3D::on_init() std::string GLGizmoMove3D::on_get_name() const { - return (_L("Move") + " [M]").ToUTF8().data(); + return _u8L("Move"); } bool GLGizmoMove3D::on_is_activable() const diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index 36759d2eca..54fcfc2c7c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -463,7 +463,7 @@ bool GLGizmoRotate3D::on_init() std::string GLGizmoRotate3D::on_get_name() const { - return (_L("Rotate") + " [R]").ToUTF8().data(); + return _u8L("Rotate"); } bool GLGizmoRotate3D::on_is_activable() const diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp index 894d844d83..b97507166b 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp @@ -76,7 +76,7 @@ bool GLGizmoScale3D::on_init() std::string GLGizmoScale3D::on_get_name() const { - return (_L("Scale") + " [S]").ToUTF8().data(); + return _u8L("Scale"); } bool GLGizmoScale3D::on_is_activable() const diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp index 5b84bbaba4..a2ee56d9ae 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp @@ -48,7 +48,7 @@ bool GLGizmoSeam::on_init() std::string GLGizmoSeam::on_get_name() const { - return (_L("Seam painting") + " [P]").ToUTF8().data(); + return _u8L("Seam painting"); } @@ -79,7 +79,7 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) const float approx_height = m_imgui->scaled(14.0f); y = std::min(y, bottom_limit - approx_height); m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); - m_imgui->begin(on_get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse); + m_imgui->begin(get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse); // First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that: const float clipping_slider_left = std::max(m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x, diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp index f70e3f93e2..9f49f9734a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp @@ -44,7 +44,7 @@ bool GLGizmoSimplify::on_init() std::string GLGizmoSimplify::on_get_name() const { - return (_L("Simplify")).ToUTF8().data(); + return _u8L("Simplify"); } void GLGizmoSimplify::on_render() {} @@ -97,7 +97,7 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi int flag = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse; - m_imgui->begin(on_get_name(), flag); + m_imgui->begin(get_name(), flag); size_t triangle_count = m_volume->mesh().its.indices.size(); // already reduced mesh diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index c7faab3bf5..11446d6d78 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -625,7 +625,7 @@ RENDER_AGAIN: //ImGui::SetNextWindowPos(ImVec2(x, y - std::max(0.f, y+window_size.y-bottom_limit) )); //ImGui::SetNextWindowSize(ImVec2(window_size)); - m_imgui->begin(on_get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse); + m_imgui->begin(get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse); // adjust window position to avoid overlap the view toolbar float win_h = ImGui::GetWindowHeight(); @@ -863,7 +863,7 @@ bool GLGizmoSlaSupports::on_is_selectable() const std::string GLGizmoSlaSupports::on_get_name() const { - return (_L("SLA Support Points") + " [L]").ToUTF8().data(); + return _u8L("SLA Support Points"); } CommonGizmosDataID GLGizmoSlaSupports::on_get_requirements() const diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index 080991859b..dfe6de746c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -1210,13 +1210,13 @@ void GLGizmosManager::activate_gizmo(EType type) if (! m_parent.get_gizmos_manager().is_serializing() && old_gizmo->wants_enter_leave_snapshots()) Plater::TakeSnapshot snapshot(wxGetApp().plater(), - Slic3r::format(_utf8("Leaving %1%"), old_gizmo->get_name())); + Slic3r::format(_utf8("Leaving %1%"), old_gizmo->get_name(false))); } if (new_gizmo && ! m_parent.get_gizmos_manager().is_serializing() && new_gizmo->wants_enter_leave_snapshots()) Plater::TakeSnapshot snapshot(wxGetApp().plater(), - Slic3r::format(_utf8("Entering %1%"), new_gizmo->get_name())); + Slic3r::format(_utf8("Entering %1%"), new_gizmo->get_name(false))); m_current = type; From 315663980bf1f567e110cdcb72a2f2b694f4c5e5 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 31 Aug 2021 13:48:22 +0200 Subject: [PATCH 47/82] Do not allow 'replace by stl' when a gizmo is active, some of the gizmos might not cope well. ALso avoided code duplication in all such cases (currently fix by Netfabb, simplify, replace by stl). --- src/slic3r/GUI/GUI_ObjectList.cpp | 13 ++++------ src/slic3r/GUI/Gizmos/GLGizmosManager.cpp | 29 ++++++++++++++++------- src/slic3r/GUI/Gizmos/GLGizmosManager.hpp | 3 ++- src/slic3r/GUI/Plater.cpp | 11 ++++----- 4 files changed, 31 insertions(+), 25 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 096836f23e..c99d9090cb 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -4030,17 +4030,12 @@ void ObjectList::simplify() // Do not simplify when a gizmo is open. There might be issues with updates // and what is worse, the snapshot time would refer to the internal stack. - auto current_type = gizmos_mgr.get_current_type(); - if (current_type == GLGizmosManager::Simplify) { + if (! gizmos_mgr.check_gizmos_closed_except(GLGizmosManager::EType::Simplify)) + return; + + if (gizmos_mgr.get_current_type() == GLGizmosManager::Simplify) { // close first gizmos_mgr.open_gizmo(GLGizmosManager::EType::Simplify); - }else if (current_type != GLGizmosManager::Undefined) { - plater->get_notification_manager()->push_notification( - NotificationType::CustomSupportsAndSeamRemovedAfterRepair, - NotificationManager::NotificationLevel::RegularNotification, - _u8L("ERROR: Please close all manipulators available from " - "the left toolbar before start simplify the mesh.")); - return; } gizmos_mgr.open_gizmo(GLGizmosManager::EType::Simplify); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index dfe6de746c..93eba3042c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -164,10 +164,8 @@ void GLGizmosManager::refresh_on_off_state() return; if (m_current != Undefined - && ! m_gizmos[m_current]->is_activable()) { - activate_gizmo(Undefined); + && ! m_gizmos[m_current]->is_activable() && activate_gizmo(Undefined)) update_data(); - } } void GLGizmosManager::reset_all_states() @@ -182,14 +180,28 @@ void GLGizmosManager::reset_all_states() bool GLGizmosManager::open_gizmo(EType type) { int idx = int(type); - if (m_gizmos[idx]->is_activable()) { - activate_gizmo(m_current == idx ? Undefined : (EType)idx); + if (m_gizmos[idx]->is_activable() + && activate_gizmo(m_current == idx ? Undefined : (EType)idx)) { update_data(); return true; } return false; } + +bool GLGizmosManager::check_gizmos_closed_except(EType type) const +{ + if (get_current_type() != type && get_current_type() != Undefined) { + wxGetApp().plater()->get_notification_manager()->push_notification( + NotificationType::CustomSupportsAndSeamRemovedAfterRepair, + NotificationManager::NotificationLevel::RegularNotification, + _u8L("ERROR: Please close all manipulators available from " + "the left toolbar first")); + return false; + } + return true; +} + void GLGizmosManager::set_hover_id(int id) { if (!m_enabled || m_current == Undefined) @@ -1194,10 +1206,10 @@ std::string GLGizmosManager::update_hover_state(const Vec2d& mouse_pos) return name; } -void GLGizmosManager::activate_gizmo(EType type) +bool GLGizmosManager::activate_gizmo(EType type) { if (m_gizmos.empty() || m_current == type) - return; + return true; GLGizmoBase* old_gizmo = m_current == Undefined ? nullptr : m_gizmos[m_current].get(); GLGizmoBase* new_gizmo = type == Undefined ? nullptr : m_gizmos[type].get(); @@ -1205,7 +1217,7 @@ void GLGizmosManager::activate_gizmo(EType type) if (old_gizmo) { old_gizmo->set_state(GLGizmoBase::Off); if (old_gizmo->get_state() != GLGizmoBase::Off) - return; // gizmo refused to be turned off, do nothing. + return false; // gizmo refused to be turned off, do nothing. if (! m_parent.get_gizmos_manager().is_serializing() && old_gizmo->wants_enter_leave_snapshots()) @@ -1222,6 +1234,7 @@ void GLGizmosManager::activate_gizmo(EType type) if (new_gizmo) new_gizmo->set_state(GLGizmoBase::On); + return true; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp index 188c9e9141..ed02574dfa 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp @@ -104,7 +104,7 @@ private: std::vector get_selectable_idxs() const; size_t get_gizmo_idx_from_mouse(const Vec2d& mouse_pos) const; - void activate_gizmo(EType type); + bool activate_gizmo(EType type); struct MouseCapture { @@ -176,6 +176,7 @@ public: void reset_all_states(); bool is_serializing() const { return m_serializing; } bool open_gizmo(EType type); + bool check_gizmos_closed_except(EType) const; void set_hover_id(int id); void enable_grabber(EType type, unsigned int id, bool enable); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 4236ee4501..af8734184f 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -3186,6 +3186,9 @@ void Plater::priv::update_sla_scene() void Plater::priv::replace_with_stl() { + if (! q->canvas3D()->get_gizmos_manager().check_gizmos_closed_except(GLGizmosManager::EType::Undefined)) + return; + const Selection& selection = get_selection(); if (selection.is_wipe_tower() || get_selection().get_volume_idxs().size() != 1) @@ -3530,14 +3533,8 @@ void Plater::priv::fix_through_netfabb(const int obj_idx, const int vol_idx/* = // Do not fix anything when a gizmo is open. There might be issues with updates // and what is worse, the snapshot time would refer to the internal stack. - if (q->canvas3D()->get_gizmos_manager().get_current_type() != GLGizmosManager::Undefined) { - notification_manager->push_notification( - NotificationType::CustomSupportsAndSeamRemovedAfterRepair, - NotificationManager::NotificationLevel::RegularNotification, - _u8L("ERROR: Please close all manipulators available from " - "the left toolbar before fixing the mesh.")); + if (! q->canvas3D()->get_gizmos_manager().check_gizmos_closed_except(GLGizmosManager::Undefined)) return; - } // size_t snapshot_time = undo_redo_stack().active_snapshot_time(); Plater::TakeSnapshot snapshot(q, _L("Fix through NetFabb")); From 7f2d1522ce31f2467c238ca330d342d5eb37d872 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 3 Sep 2021 15:35:44 +0200 Subject: [PATCH 48/82] Rendering seams (and other options) in preview using batched models on systems not supporting OpenGL 3.3 --- src/libslic3r/Technologies.hpp | 27 ++-- src/slic3r/GUI/GCodeViewer.cpp | 243 +++++++++++++++++++++++++++- src/slic3r/GUI/GCodeViewer.hpp | 56 +++++++ src/slic3r/GUI/GLModel.cpp | 20 +++ src/slic3r/GUI/GLModel.hpp | 9 ++ src/slic3r/GUI/GLShadersManager.cpp | 9 ++ 6 files changed, 351 insertions(+), 13 deletions(-) diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 6132430f1a..d031b9527d 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -37,24 +37,33 @@ //==================== -// 2.4.0.alpha0 techs +// 2.4.0.alpha1 techs //==================== -#define ENABLE_2_4_0_ALPHA0 1 +#define ENABLE_2_4_0_ALPHA1 1 // Enable delayed rendering of transparent volumes -#define ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING (1 && ENABLE_2_4_0_ALPHA0) +#define ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING (1 && ENABLE_2_4_0_ALPHA1) // Enable the fix of importing color print view from gcode files into GCodeViewer -#define ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER (1 && ENABLE_2_4_0_ALPHA0) +#define ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER (1 && ENABLE_2_4_0_ALPHA1) // Enable drawing contours, at cut level, for sinking volumes -#define ENABLE_SINKING_CONTOURS (1 && ENABLE_2_4_0_ALPHA0) +#define ENABLE_SINKING_CONTOURS (1 && ENABLE_2_4_0_ALPHA1) // Enable implementation of retract acceleration in gcode processor -#define ENABLE_RETRACT_ACCELERATION (1 && ENABLE_2_4_0_ALPHA0) +#define ENABLE_RETRACT_ACCELERATION (1 && ENABLE_2_4_0_ALPHA1) // Enable the fix for exporting and importing to/from 3mf file of mirrored volumes -#define ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT (1 && ENABLE_2_4_0_ALPHA0) +#define ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT (1 && ENABLE_2_4_0_ALPHA1) // Enable rendering seams (and other options) in preview using models -#define ENABLE_SEAMS_USING_MODELS (1 && ENABLE_2_4_0_ALPHA0) +#define ENABLE_SEAMS_USING_MODELS (1 && ENABLE_2_4_0_ALPHA1) // Enable save and save as commands to be enabled also when the plater is empty and allow to load empty projects -#define ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED (1 && ENABLE_2_4_0_ALPHA0) +#define ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED (1 && ENABLE_2_4_0_ALPHA1) + + +//==================== +// 2.4.0.alpha2 techs +//==================== +#define ENABLE_2_4_0_ALPHA2 1 + +// Enable rendering seams (and other options) in preview using batched models on systems not supporting OpenGL 3.3 +#define ENABLE_SEAMS_USING_BATCHED_MODELS (1 && ENABLE_SEAMS_USING_MODELS && ENABLE_2_4_0_ALPHA2) #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 3fc6242648..1e0b9b1242 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -807,6 +807,25 @@ void GCodeViewer::render() case EMoveType::Unretract: case EMoveType::Seam: { #if ENABLE_SEAMS_USING_MODELS +#if ENABLE_SEAMS_USING_BATCHED_MODELS + if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { + buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::InstancedModel; + buffer.shader = "gouraud_light_instanced"; + buffer.model.model.init_from(diamond(16)); + buffer.model.color = option_color(type); + buffer.model.instances.format = InstanceVBuffer::EFormat::InstancedModel; + } + else { + buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::BatchedModel; + buffer.vertices.format = VBuffer::EFormat::PositionNormal3; + buffer.shader = "gouraud_light"; + + buffer.model.data = diamond(16); + buffer.model.color = option_color(type); + buffer.model.instances.format = InstanceVBuffer::EFormat::BatchedModel; + } + break; +#else if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Model; buffer.shader = "gouraud_light_instanced"; @@ -819,6 +838,7 @@ void GCodeViewer::render() buffer.shader = wxGetApp().is_glsl_version_greater_or_equal_to(1, 20) ? "options_120" : "options_110"; } break; +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #else buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Point; buffer.vertices.format = VBuffer::EFormat::Position; @@ -1221,7 +1241,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) unsigned int ibuffer_id, IndexBuffer& indices, size_t move_id) { if (prev.type != curr.type || !buffer.paths.back().matches(curr)) { // add starting index - indices.push_back(static_cast(indices.size())); + indices.push_back(static_cast(indices.size())); buffer.add_path(curr, ibuffer_id, indices.size() - 1, move_id - 1); buffer.paths.back().sub_paths.front().first.position = prev.position; } @@ -1229,11 +1249,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) Path& last_path = buffer.paths.back(); if (last_path.sub_paths.front().first.i_id != last_path.sub_paths.back().last.i_id) { // add previous index - indices.push_back(static_cast(indices.size())); + indices.push_back(static_cast(indices.size())); } // add current index - indices.push_back(static_cast(indices.size())); + indices.push_back(static_cast(indices.size())); last_path.sub_paths.back().last = { ibuffer_id, indices.size() - 1, move_id, curr.position }; }; @@ -1436,7 +1456,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) }; #if ENABLE_SEAMS_USING_MODELS - // format data into the buffers to be rendered as model + // format data into the buffers to be rendered as instanced model auto add_model_instance = [](const GCodeProcessor::MoveVertex& curr, InstanceBuffer& instances, InstanceIdBuffer& instances_ids, size_t move_id) { // append position instances.push_back(curr.position.x()); @@ -1450,6 +1470,49 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // append id instances_ids.push_back(move_id); }; + +#if ENABLE_SEAMS_USING_BATCHED_MODELS + // format data into the buffers to be rendered as batched model + auto add_vertices_as_model_batch = [](const GCodeProcessor::MoveVertex& curr, const GLModel::InitializationData& data, VertexBuffer& vertices, InstanceBuffer& instances, InstanceIdBuffer& instances_ids, size_t move_id) { + const double width = static_cast(1.5f * curr.width); + const double height = static_cast(1.5f * curr.height); + + const Transform3d trafo = Geometry::assemble_transform(curr.position.cast(), Vec3d::Zero(), { width, width, height }); + const Eigen::Matrix normal_matrix = trafo.matrix().template block<3, 3>(0, 0).inverse().transpose(); + + for (const auto& entity : data.entities) { + // append vertices + for (size_t i = 0; i < entity.positions.size(); ++i) { + // append position + const Vec3d position = trafo * entity.positions[i].cast(); + vertices.push_back(static_cast(position.x())); + vertices.push_back(static_cast(position.y())); + vertices.push_back(static_cast(position.z())); + + // append normal + const Vec3d normal = normal_matrix * entity.normals[i].cast(); + vertices.push_back(static_cast(normal.x())); + vertices.push_back(static_cast(normal.y())); + vertices.push_back(static_cast(normal.z())); + } + } + + // append instance position + instances.push_back(curr.position.x()); + instances.push_back(curr.position.y()); + instances.push_back(curr.position.z()); + // append instance id + instances_ids.push_back(move_id); + }; + + auto add_indices_as_model_batch = [](const GLModel::InitializationData& data, IndexBuffer& indices, IBufferType base_index) { + for (const auto& entity : data.entities) { + for (size_t i = 0; i < entity.indices.size(); ++i) { + indices.push_back(static_cast(entity.indices[i] + base_index)); + } + } + }; +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #endif // ENABLE_SEAMS_USING_MODELS #if ENABLE_GCODE_VIEWER_STATISTICS @@ -1533,7 +1596,12 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // if adding the vertices for the current segment exceeds the threshold size of the current vertex buffer // add another vertex buffer +#if ENABLE_SEAMS_USING_BATCHED_MODELS + size_t vertices_size_to_add = (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) ? t_buffer.model.data.vertices_size_bytes() : t_buffer.max_vertices_per_segment_size_bytes(); + if (v_multibuffer.back().size() * sizeof(float) > t_buffer.vertices.max_size_bytes() - vertices_size_to_add) { +#else if (v_multibuffer.back().size() * sizeof(float) > t_buffer.vertices.max_size_bytes() - t_buffer.max_vertices_per_segment_size_bytes()) { +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS v_multibuffer.push_back(VertexBuffer()); if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle) { Path& last_path = t_buffer.paths.back(); @@ -1550,6 +1618,24 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) case TBuffer::ERenderPrimitiveType::Line: { add_vertices_as_line(prev, curr, v_buffer); break; } case TBuffer::ERenderPrimitiveType::Triangle: { add_vertices_as_solid(prev, curr, t_buffer, static_cast(v_multibuffer.size()) - 1, v_buffer, i); break; } #if ENABLE_SEAMS_USING_MODELS +#if ENABLE_SEAMS_USING_BATCHED_MODELS + case TBuffer::ERenderPrimitiveType::InstancedModel: + { + add_model_instance(curr, inst_buffer, inst_id_buffer, i); +#if ENABLE_GCODE_VIEWER_STATISTICS + ++m_statistics.instances_count; +#endif // ENABLE_GCODE_VIEWER_STATISTICS + break; + } + case TBuffer::ERenderPrimitiveType::BatchedModel: + { + add_vertices_as_model_batch(curr, t_buffer.model.data, v_buffer, inst_buffer, inst_id_buffer, i); +#if ENABLE_GCODE_VIEWER_STATISTICS + ++m_statistics.batched_count; +#endif // ENABLE_GCODE_VIEWER_STATISTICS + break; + } +#else case TBuffer::ERenderPrimitiveType::Model: { add_model_instance(curr, inst_buffer, inst_id_buffer, i); @@ -1559,6 +1645,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) break; } #endif // ENABLE_SEAMS_USING_MODELS +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS } // collect options zs for later use @@ -1741,6 +1828,23 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) for (size_t i = 0; i < m_buffers.size(); ++i) { TBuffer& t_buffer = m_buffers[i]; #if ENABLE_SEAMS_USING_MODELS +#if ENABLE_SEAMS_USING_BATCHED_MODELS + if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::InstancedModel) { + const InstanceBuffer& inst_buffer = instances[i]; + if (!inst_buffer.empty()) { + t_buffer.model.instances.buffer = inst_buffer; + t_buffer.model.instances.s_ids = instances_ids[i]; + } + } + else { + if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) { + const InstanceBuffer& inst_buffer = instances[i]; + if (!inst_buffer.empty()) { + t_buffer.model.instances.buffer = inst_buffer; + t_buffer.model.instances.s_ids = instances_ids[i]; + } + } +#else if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { const InstanceBuffer& inst_buffer = instances[i]; if (!inst_buffer.empty()) { @@ -1749,6 +1853,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) } } else { +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #endif // ENABLE_SEAMS_USING_MODELS const MultiVertexBuffer& v_multibuffer = vertices[i]; for (const VertexBuffer& v_buffer : v_multibuffer) { @@ -1842,10 +1947,20 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // if adding the indices for the current segment exceeds the threshold size of the current index buffer // create another index buffer +#if ENABLE_SEAMS_USING_BATCHED_MODELS + size_t indiced_size_to_add = (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) ? t_buffer.model.data.indices_size_bytes() : t_buffer.max_indices_per_segment_size_bytes(); + if (i_multibuffer.back().size() * sizeof(IBufferType) >= IBUFFER_THRESHOLD_BYTES - indiced_size_to_add) { +#else if (i_multibuffer.back().size() * sizeof(IBufferType) >= IBUFFER_THRESHOLD_BYTES - t_buffer.max_indices_per_segment_size_bytes()) { +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS i_multibuffer.push_back(IndexBuffer()); vbo_index_list.push_back(t_buffer.vertices.vbos[curr_vertex_buffer.first]); +#if ENABLE_SEAMS_USING_BATCHED_MODELS + if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point && + t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::BatchedModel) { +#else if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point) { +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS Path& last_path = t_buffer.paths.back(); last_path.add_sub_path(prev, static_cast(i_multibuffer.size()) - 1, 0, i - 1); } @@ -1853,14 +1968,24 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // if adding the vertices for the current segment exceeds the threshold size of the current vertex buffer // create another index buffer +#if ENABLE_SEAMS_USING_BATCHED_MODELS + size_t vertices_size_to_add = (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) ? t_buffer.model.data.vertices_size_bytes() : t_buffer.max_vertices_per_segment_size_bytes(); + if (curr_vertex_buffer.second * t_buffer.vertices.vertex_size_bytes() > t_buffer.vertices.max_size_bytes() - vertices_size_to_add) { +#else if (curr_vertex_buffer.second * t_buffer.vertices.vertex_size_bytes() > t_buffer.vertices.max_size_bytes() - t_buffer.max_vertices_per_segment_size_bytes()) { +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS i_multibuffer.push_back(IndexBuffer()); ++curr_vertex_buffer.first; curr_vertex_buffer.second = 0; vbo_index_list.push_back(t_buffer.vertices.vbos[curr_vertex_buffer.first]); +#if ENABLE_SEAMS_USING_BATCHED_MODELS + if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point && + t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::BatchedModel) { +#else if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point) { +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS Path& last_path = t_buffer.paths.back(); last_path.add_sub_path(prev, static_cast(i_multibuffer.size()) - 1, 0, i - 1); } @@ -1884,6 +2009,13 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) add_indices_as_solid(prev, curr, next, t_buffer, curr_vertex_buffer.second, static_cast(i_multibuffer.size()) - 1, i_buffer, i); break; } +#if ENABLE_SEAMS_USING_BATCHED_MODELS + case TBuffer::ERenderPrimitiveType::BatchedModel: { + add_indices_as_model_batch(t_buffer.model.data, i_buffer, curr_vertex_buffer.second); + curr_vertex_buffer.second += t_buffer.model.data.vertices_count(); + break; + } +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS default: { break; } } } @@ -1898,7 +2030,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) for (size_t i = 0; i < m_buffers.size(); ++i) { TBuffer& t_buffer = m_buffers[i]; #if ENABLE_SEAMS_USING_MODELS +#if ENABLE_SEAMS_USING_BATCHED_MODELS + if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::InstancedModel) { +#else if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Model) { +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #endif // ENABLE_SEAMS_USING_MODELS const MultiIndexBuffer& i_multibuffer = indices[i]; for (const IndexBuffer& i_buffer : i_multibuffer) { @@ -2174,7 +2310,12 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool continue; #if ENABLE_SEAMS_USING_MODELS +#if ENABLE_SEAMS_USING_BATCHED_MODELS + if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::InstancedModel || + buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) { +#else if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS for (size_t id : buffer.model.instances.s_ids) { if (id < m_layers.get_endpoints_at(m_layers_z_range[0]).first || m_layers.get_endpoints_at(m_layers_z_range[1]).last < id) continue; @@ -2239,7 +2380,12 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool bool found = false; for (const TBuffer& buffer : m_buffers) { #if ENABLE_SEAMS_USING_MODELS +#if ENABLE_SEAMS_USING_BATCHED_MODELS + if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::InstancedModel || + buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) { +#else if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS for (size_t i = 0; i < buffer.model.instances.s_ids.size(); ++i) { if (buffer.model.instances.s_ids[i] == m_sequential_view.current.last) { size_t offset = i * buffer.model.instances.instance_size_floats(); @@ -2400,10 +2546,19 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool } #if ENABLE_SEAMS_USING_MODELS +#if ENABLE_SEAMS_USING_BATCHED_MODELS + // second pass: for buffers using instanced and batched models, update the instances render ranges +#else // second pass: for buffers using instanced models, update the instances render ranges +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS for (size_t b = 0; b < m_buffers.size(); ++b) { TBuffer& buffer = const_cast(m_buffers[b]); +#if ENABLE_SEAMS_USING_BATCHED_MODELS + if (buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::InstancedModel && + buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::BatchedModel) +#else if (buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Model) +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS continue; buffer.model.instances.render_ranges.reset(); @@ -2689,6 +2844,66 @@ void GCodeViewer::render_toolpaths() } } }; + +#if ENABLE_SEAMS_USING_BATCHED_MODELS +#if ENABLE_GCODE_VIEWER_STATISTICS + auto render_as_batched_model = [this](TBuffer& buffer, GLShaderProgram& shader) { +#else + auto render_as_batched_model = [](TBuffer& buffer, GLShaderProgram& shader) { +#endif // ENABLE_GCODE_VIEWER_STATISTICS + + struct Range + { + unsigned int first; + unsigned int last; + bool intersects(const Range& other) const { return (other.last < first || other.first > last) ? false : true; } + }; + Range buffer_range = { 0, 0 }; + size_t indices_per_instance = buffer.model.data.indices_count(); + + for (size_t j = 0; j < buffer.indices.size(); ++j) { + const IBuffer& i_buffer = buffer.indices[j]; + buffer_range.last = buffer_range.first + i_buffer.count / indices_per_instance; + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo)); + glsafe(::glVertexPointer(buffer.vertices.position_size_floats(), GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.position_offset_bytes())); + glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); + bool has_normals = buffer.vertices.normal_size_floats() > 0; + if (has_normals) { + glsafe(::glNormalPointer(GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.normal_offset_bytes())); + glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); + } + + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo)); + + for (auto& range : buffer.model.instances.render_ranges.ranges) { + Range range_range = { range.offset, range.offset + range.count }; + if (range_range.intersects(buffer_range)) { + shader.set_uniform("uniform_color", range.color); + unsigned int offset = (range_range.first > buffer_range.first) ? range_range.first - buffer_range.first : 0; + size_t offset_bytes = static_cast(offset) * indices_per_instance * sizeof(IBufferType); + Range render_range = { std::max(range_range.first, buffer_range.first), std::min(range_range.last, buffer_range.last) }; + size_t count = static_cast(render_range.last - render_range.first) * indices_per_instance; + if (count > 0) { + glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)count, GL_UNSIGNED_SHORT, (const void*)offset_bytes)); +#if ENABLE_GCODE_VIEWER_STATISTICS + ++m_statistics.gl_batched_models_calls_count; +#endif // ENABLE_GCODE_VIEWER_STATISTICS + } + } + } + + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); + + if (has_normals) + glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); + + glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + + buffer_range.first = buffer_range.last; + } + }; +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #endif // ENABLE_SEAMS_USING_MODELS auto line_width = [](double zoom) { @@ -2712,11 +2927,22 @@ void GCodeViewer::render_toolpaths() shader->start_using(); #if ENABLE_SEAMS_USING_MODELS +#if ENABLE_SEAMS_USING_BATCHED_MODELS + if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::InstancedModel) { +#else if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS shader->set_uniform("emission_factor", 0.25f); render_as_instanced_model(buffer, *shader); shader->set_uniform("emission_factor", 0.0f); } +#if ENABLE_SEAMS_USING_BATCHED_MODELS + else if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) { + shader->set_uniform("emission_factor", 0.25f); + render_as_batched_model(buffer, *shader); + shader->set_uniform("emission_factor", 0.0f); + } +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS else { #endif // ENABLE_SEAMS_USING_MODELS for (size_t j = 0; j < buffer.indices.size(); ++j) { @@ -2882,6 +3108,7 @@ void GCodeViewer::render_legend(float& legend_height) } case EItemType::Circle: { ImVec2 center(0.5f * (pos.x + pos.x + icon_size), 0.5f * (pos.y + pos.y + icon_size)); +#if !ENABLE_SEAMS_USING_BATCHED_MODELS if (m_buffers[buffer_id(EMoveType::Retract)].shader == "options_120") { draw_list->AddCircleFilled(center, 0.5f * icon_size, ImGui::GetColorU32({ 0.5f * color[0], 0.5f * color[1], 0.5f * color[2], 1.0f }), 16); @@ -2891,6 +3118,7 @@ void GCodeViewer::render_legend(float& legend_height) draw_list->AddCircleFilled(center, radius, ImGui::GetColorU32({ 0.5f * color[0], 0.5f * color[1], 0.5f * color[2], 1.0f }), 16); } else +#endif // !ENABLE_SEAMS_USING_BATCHED_MODELS draw_list->AddCircleFilled(center, 0.5f * icon_size, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16); break; @@ -3756,7 +3984,11 @@ void GCodeViewer::render_statistics() add_counter(std::string("Multi GL_TRIANGLES:"), m_statistics.gl_multi_triangles_calls_count); add_counter(std::string("GL_TRIANGLES:"), m_statistics.gl_triangles_calls_count); #if ENABLE_SEAMS_USING_MODELS + ImGui::Separator(); add_counter(std::string("Instanced models:"), m_statistics.gl_instanced_models_calls_count); +#if ENABLE_SEAMS_USING_BATCHED_MODELS + add_counter(std::string("Batched models:"), m_statistics.gl_batched_models_calls_count); +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #endif // ENABLE_SEAMS_USING_MODELS } @@ -3788,6 +4020,9 @@ void GCodeViewer::render_statistics() add_counter(std::string("Extrude segments count:"), m_statistics.extrude_segments_count); #if ENABLE_SEAMS_USING_MODELS add_counter(std::string("Instances count:"), m_statistics.instances_count); +#if ENABLE_SEAMS_USING_BATCHED_MODELS + add_counter(std::string("Batched count:"), m_statistics.batched_count); +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #endif // ENABLE_SEAMS_USING_MODELS ImGui::Separator(); add_counter(std::string("VBuffers count:"), m_statistics.vbuffers_count); diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 429175fe68..86a7dcf856 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -105,9 +105,16 @@ class GCodeViewer }; #if ENABLE_SEAMS_USING_MODELS +#if ENABLE_SEAMS_USING_BATCHED_MODELS + // buffer containing instances data used to render a toolpaths using instanced or batched models + // instance record format: + // instanced models: 5 floats -> position.x|position.y|position.z|width|height (which are sent to the shader as -> vec3 (offset) + vec2 (scales) in GLModel::render_instanced()) + // batched models: 3 floats -> position.x|position.y|position.z +#else // buffer containing instances data used to render a toolpaths using instanced models // instance record format: 5 floats -> position.x|position.y|position.z|width|height // which is sent to the shader as -> vec3 (offset) + vec2 (scales) in GLModel::render_instanced() +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS struct InstanceVBuffer { // ranges used to render only subparts of the intances @@ -130,6 +137,16 @@ class GCodeViewer void reset(); }; +#if ENABLE_SEAMS_USING_BATCHED_MODELS + enum class EFormat : unsigned char + { + InstancedModel, + BatchedModel + }; + + EFormat format; +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS + // cpu-side buffer containing all instances data InstanceBuffer buffer; // indices of the moves for all instances @@ -138,7 +155,18 @@ class GCodeViewer size_t data_size_bytes() const { return s_ids.size() * instance_size_bytes(); } +#if ENABLE_SEAMS_USING_BATCHED_MODELS + size_t instance_size_floats() const { + switch (format) + { + case EFormat::InstancedModel: { return 5; } + case EFormat::BatchedModel: { return 3; } + default: { return 0; } + } + } +#else size_t instance_size_floats() const { return 5; } +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS size_t instance_size_bytes() const { return instance_size_floats() * sizeof(float); } void reset(); @@ -280,7 +308,12 @@ class GCodeViewer Line, #if ENABLE_SEAMS_USING_MODELS Triangle, +#if ENABLE_SEAMS_USING_BATCHED_MODELS + InstancedModel, + BatchedModel +#else Model +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #else Triangle #endif // ENABLE_SEAMS_USING_MODELS @@ -298,6 +331,9 @@ class GCodeViewer GLModel model; Color color; InstanceVBuffer instances; +#if ENABLE_SEAMS_USING_BATCHED_MODELS + GLModel::InitializationData data; +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS void reset(); }; @@ -362,7 +398,15 @@ class GCodeViewer case ERenderPrimitiveType::Triangle: { return !vertices.vbos.empty() && vertices.vbos.front() != 0 && !indices.empty() && indices.front().ibo != 0; } +#if ENABLE_SEAMS_USING_BATCHED_MODELS + case ERenderPrimitiveType::InstancedModel: { return model.model.is_initialized() && !model.instances.buffer.empty(); } + case ERenderPrimitiveType::BatchedModel: { + return model.data.vertices_count() > 0 && model.data.indices_count() && + !vertices.vbos.empty() && vertices.vbos.front() != 0 && !indices.empty() && indices.front().ibo != 0; + } +#else case ERenderPrimitiveType::Model: { return model.model.is_initialized() && !model.instances.buffer.empty(); } +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS default: { return false; } } } @@ -520,6 +564,9 @@ class GCodeViewer int64_t gl_triangles_calls_count{ 0 }; #if ENABLE_SEAMS_USING_MODELS int64_t gl_instanced_models_calls_count{ 0 }; +#if ENABLE_SEAMS_USING_BATCHED_MODELS + int64_t gl_batched_models_calls_count{ 0 }; +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #endif // ENABLE_SEAMS_USING_MODELS // memory int64_t results_size{ 0 }; @@ -541,6 +588,9 @@ class GCodeViewer int64_t extrude_segments_count{ 0 }; #if ENABLE_SEAMS_USING_MODELS int64_t instances_count{ 0 }; +#if ENABLE_SEAMS_USING_BATCHED_MODELS + int64_t batched_count{ 0 }; +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #endif // ENABLE_SEAMS_USING_MODELS int64_t vbuffers_count{ 0 }; int64_t ibuffers_count{ 0 }; @@ -569,6 +619,9 @@ class GCodeViewer gl_triangles_calls_count = 0; #if ENABLE_SEAMS_USING_MODELS gl_instanced_models_calls_count = 0; +#if ENABLE_SEAMS_USING_BATCHED_MODELS + gl_batched_models_calls_count = 0; +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #endif // ENABLE_SEAMS_USING_MODELS } @@ -594,6 +647,9 @@ class GCodeViewer extrude_segments_count = 0; #if ENABLE_SEAMS_USING_MODELS instances_count = 0; +#if ENABLE_SEAMS_USING_BATCHED_MODELS + batched_count = 0; +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #endif // ENABLE_SEAMS_USING_MODELS vbuffers_count = 0; ibuffers_count = 0; diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp index 5cddd7fa3b..d22925673b 100644 --- a/src/slic3r/GUI/GLModel.cpp +++ b/src/slic3r/GUI/GLModel.cpp @@ -19,6 +19,26 @@ namespace Slic3r { namespace GUI { +#if ENABLE_SEAMS_USING_BATCHED_MODELS +size_t GLModel::InitializationData::vertices_count() const +{ + size_t ret = 0; + for (const Entity& entity : entities) { + ret += entity.positions.size(); + } + return ret; +} + +size_t GLModel::InitializationData::indices_count() const +{ + size_t ret = 0; + for (const Entity& entity : entities) { + ret += entity.indices.size(); + } + return ret; +} +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS + void GLModel::init_from(const InitializationData& data) { if (!m_render_data.empty()) // call reset() if you want to reuse this model diff --git a/src/slic3r/GUI/GLModel.hpp b/src/slic3r/GUI/GLModel.hpp index 8e0039b083..7422466f0d 100644 --- a/src/slic3r/GUI/GLModel.hpp +++ b/src/slic3r/GUI/GLModel.hpp @@ -48,6 +48,15 @@ namespace GUI { }; std::vector entities; + +#if ENABLE_SEAMS_USING_BATCHED_MODELS + size_t vertices_count() const; + size_t vertices_size_floats() const { return vertices_count() * 6; } + size_t vertices_size_bytes() const { return vertices_size_floats() * sizeof(float); } + + size_t indices_count() const; + size_t indices_size_bytes() const { return indices_count() * sizeof(unsigned int); } +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS }; private: diff --git a/src/slic3r/GUI/GLShadersManager.cpp b/src/slic3r/GUI/GLShadersManager.cpp index edbe2bb46d..5dd478b578 100644 --- a/src/slic3r/GUI/GLShadersManager.cpp +++ b/src/slic3r/GUI/GLShadersManager.cpp @@ -33,11 +33,19 @@ std::pair GLShadersManager::init() bool valid = true; +#if ENABLE_SEAMS_USING_BATCHED_MODELS + // used to render bed axes and model, selection hints, gcode sequential view marker model, preview shells, options in gcode preview +#else // used to render bed axes and model, selection hints, gcode sequential view marker model, preview shells +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS valid &= append_shader("gouraud_light", { "gouraud_light.vs", "gouraud_light.fs" }); // used to render printbed valid &= append_shader("printbed", { "printbed.vs", "printbed.fs" }); // used to render options in gcode preview +#if ENABLE_SEAMS_USING_BATCHED_MODELS + if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) + valid &= append_shader("gouraud_light_instanced", { "gouraud_light_instanced.vs", "gouraud_light_instanced.fs" }); +#else #if ENABLE_SEAMS_USING_MODELS if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) valid &= append_shader("gouraud_light_instanced", { "gouraud_light_instanced.vs", "gouraud_light_instanced.fs" }); @@ -49,6 +57,7 @@ std::pair GLShadersManager::init() #if ENABLE_SEAMS_USING_MODELS } #endif // ENABLE_SEAMS_USING_MODELS +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS // used to render extrusion and travel paths as lines in gcode preview valid &= append_shader("toolpaths_lines", { "toolpaths_lines.vs", "toolpaths_lines.fs" }); // used to render objects in 3d editor From 2e250c1463c5d8e8bc94d0769e3e82d648e99e3b Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Fri, 3 Sep 2021 16:16:43 +0200 Subject: [PATCH 49/82] Speed-up in GCodeViewer vertex buffer generator --- src/slic3r/GUI/GCodeViewer.cpp | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 3fc6242648..656a674066 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -70,18 +70,9 @@ static std::vector> decode_colors(const std::vector Date: Fri, 3 Sep 2021 16:17:24 +0200 Subject: [PATCH 50/82] Commenting out untested and unused Polyline::simplify_by_visibility() --- src/libslic3r/Polyline.cpp | 4 ++- src/libslic3r/Polyline.hpp | 2 +- xs/t/09_polyline.t | 70 +++++++++++++++++++------------------- xs/xsp/Polyline.xsp | 2 -- 4 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/libslic3r/Polyline.cpp b/src/libslic3r/Polyline.cpp index a6be642994..68c40fc204 100644 --- a/src/libslic3r/Polyline.cpp +++ b/src/libslic3r/Polyline.cpp @@ -120,7 +120,8 @@ void Polyline::simplify(double tolerance) this->points = MultiPoint::_douglas_peucker(this->points, tolerance); } -/* This method simplifies all *lines* contained in the supplied area */ +#if 0 +// This method simplifies all *lines* contained in the supplied area template void Polyline::simplify_by_visibility(const T &area) { @@ -141,6 +142,7 @@ void Polyline::simplify_by_visibility(const T &area) } template void Polyline::simplify_by_visibility(const ExPolygon &area); template void Polyline::simplify_by_visibility(const ExPolygonCollection &area); +#endif void Polyline::split_at(const Point &point, Polyline* p1, Polyline* p2) const { diff --git a/src/libslic3r/Polyline.hpp b/src/libslic3r/Polyline.hpp index 51dcf9d36d..758fc38cd5 100644 --- a/src/libslic3r/Polyline.hpp +++ b/src/libslic3r/Polyline.hpp @@ -72,7 +72,7 @@ public: void extend_start(double distance); Points equally_spaced_points(double distance) const; void simplify(double tolerance); - template void simplify_by_visibility(const T &area); +// template void simplify_by_visibility(const T &area); void split_at(const Point &point, Polyline* p1, Polyline* p2) const; bool is_straight() const; bool is_closed() const { return this->points.front() == this->points.back(); } diff --git a/xs/t/09_polyline.t b/xs/t/09_polyline.t index 0a7b8dcb05..5203ec5ef4 100644 --- a/xs/t/09_polyline.t +++ b/xs/t/09_polyline.t @@ -89,40 +89,40 @@ is_deeply $polyline->pp, [ @$points, @$points ], 'append_polyline'; } # disabled because we now use a more efficient but incomplete algorithm -if (0) { - my $polyline = Slic3r::Polyline->new( - map [$_,10], (0,10,20,30,40,50,60) - ); - { - my $expolygon = Slic3r::ExPolygon->new(Slic3r::Polygon->new( - [25,0], [55,0], [55,30], [25,30], - )); - my $p = $polyline->clone; - $p->simplify_by_visibility($expolygon); - is_deeply $p->pp, [ - map [$_,10], (0,10,20,30,50,60) - ], 'simplify_by_visibility()'; - } - { - my $expolygon = Slic3r::ExPolygon->new(Slic3r::Polygon->new( - [-15,0], [75,0], [75,30], [-15,30], - )); - my $p = $polyline->clone; - $p->simplify_by_visibility($expolygon); - is_deeply $p->pp, [ - map [$_,10], (0,60) - ], 'simplify_by_visibility()'; - } - { - my $expolygon = Slic3r::ExPolygon->new(Slic3r::Polygon->new( - [-15,0], [25,0], [25,30], [-15,30], - )); - my $p = $polyline->clone; - $p->simplify_by_visibility($expolygon); - is_deeply $p->pp, [ - map [$_,10], (0,20,30,40,50,60) - ], 'simplify_by_visibility()'; - } -} +#if (0) { +# my $polyline = Slic3r::Polyline->new( +# map [$_,10], (0,10,20,30,40,50,60) +# ); +# { +# my $expolygon = Slic3r::ExPolygon->new(Slic3r::Polygon->new( +# [25,0], [55,0], [55,30], [25,30], +# )); +# my $p = $polyline->clone; +# $p->simplify_by_visibility($expolygon); +# is_deeply $p->pp, [ +# map [$_,10], (0,10,20,30,50,60) +# ], 'simplify_by_visibility()'; +# } +# { +# my $expolygon = Slic3r::ExPolygon->new(Slic3r::Polygon->new( +# [-15,0], [75,0], [75,30], [-15,30], +# )); +# my $p = $polyline->clone; +# $p->simplify_by_visibility($expolygon); +# is_deeply $p->pp, [ +# map [$_,10], (0,60) +# ], 'simplify_by_visibility()'; +# } +# { +# my $expolygon = Slic3r::ExPolygon->new(Slic3r::Polygon->new( +# [-15,0], [25,0], [25,30], [-15,30], +# )); +# my $p = $polyline->clone; +# $p->simplify_by_visibility($expolygon); +# is_deeply $p->pp, [ +# map [$_,10], (0,20,30,40,50,60) +# ], 'simplify_by_visibility()'; +# } +#} __END__ diff --git a/xs/xsp/Polyline.xsp b/xs/xsp/Polyline.xsp index 10bbb263f8..7846ea5f4c 100644 --- a/xs/xsp/Polyline.xsp +++ b/xs/xsp/Polyline.xsp @@ -31,8 +31,6 @@ void extend_end(double distance); void extend_start(double distance); void simplify(double tolerance); - void simplify_by_visibility(ExPolygon* expolygon) - %code{% THIS->simplify_by_visibility(*expolygon); %}; void split_at(Point* point, Polyline* p1, Polyline* p2) %code{% THIS->split_at(*point, p1, p2); %}; bool is_straight(); From dc7272391191a76b4315d1b7849ff2e570fd69fe Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Fri, 3 Sep 2021 16:19:16 +0200 Subject: [PATCH 51/82] Optimization of GCodeReader: 1) Use std::from_chars() instead of strtod() 2) Own implementation of buffered readline() --- src/libslic3r/GCodeReader.cpp | 40 +++++++++++++++++++++++++++++------ src/libslic3r/GCodeReader.hpp | 13 ++++++------ 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/src/libslic3r/GCodeReader.cpp b/src/libslic3r/GCodeReader.cpp index 7dc3c9a8ac..54e6802e62 100644 --- a/src/libslic3r/GCodeReader.cpp +++ b/src/libslic3r/GCodeReader.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -32,7 +33,7 @@ void GCodeReader::apply_config(const DynamicPrintConfig &config) m_extrusion_axis = get_extrusion_axis_char(m_config); } -const char* GCodeReader::parse_line_internal(const char *ptr, GCodeLine &gline, std::pair &command) +const char* GCodeReader::parse_line_internal(const char *ptr, const char *end, GCodeLine &gline, std::pair &command) { PROFILE_FUNC(); @@ -70,9 +71,9 @@ const char* GCodeReader::parse_line_internal(const char *ptr, GCodeLine &gline, } if (axis != NUM_AXES_WITH_UNKNOWN) { // Try to parse the numeric value. - char *pend = nullptr; - double v = strtod(++ c, &pend); - if (pend != nullptr && is_end_of_word(*pend)) { + double v; + auto [pend, ec] = std::from_chars(++ c, end, v); + if (pend != c && is_end_of_word(*pend)) { // The axis value has been parsed correctly. if (axis != UNKNOWN_AXIS) gline.m_axis[int(axis)] = float(v); @@ -128,10 +129,37 @@ void GCodeReader::update_coordinates(GCodeLine &gline, std::pair buffer(65536 * 10, 0); std::string line; m_parsing = true; - while (m_parsing && std::getline(f, line)) - this->parse_line(line, callback); + GCodeLine gline; + bool eof = false; + while (m_parsing && ! eof) { + f.read(buffer.data(), buffer.size()); + auto it = buffer.begin(); + auto it_bufend = buffer.begin() + f.gcount(); + eof = ! f.good(); + while (it != it_bufend) { + bool eol = false; + auto it_end = it; + for (; it_end != it_bufend && ! (eol = *it_end == '\r' || *it_end == '\n'); ++ it_end) ; + eol |= eof && it_end == it_bufend; + if (eol) { + gline.reset(); + if (line.empty()) + this->parse_line(&(*it), &(*it_end), gline, callback); + else { + line.insert(line.end(), it, it_end); + this->parse_line(line.c_str(), line.c_str() + line.size(), gline, callback); + line.clear(); + } + } else + line.insert(line.end(), it, it_end); + // Skip all the empty lines. + for (it = it_end; it != it_bufend && (*it == '\r' || *it == '\n'); ++ it) ; + } + } } bool GCodeReader::GCodeLine::has(char axis) const diff --git a/src/libslic3r/GCodeReader.hpp b/src/libslic3r/GCodeReader.hpp index 6b58608e61..88c9df2841 100644 --- a/src/libslic3r/GCodeReader.hpp +++ b/src/libslic3r/GCodeReader.hpp @@ -83,11 +83,12 @@ public: void parse_buffer(const std::string &buffer, Callback callback) { const char *ptr = buffer.c_str(); + const char *end = ptr + buffer.size(); GCodeLine gline; m_parsing = true; while (m_parsing && *ptr != 0) { gline.reset(); - ptr = this->parse_line(ptr, gline, callback); + ptr = this->parse_line(ptr, end, gline, callback); } } @@ -95,18 +96,18 @@ public: { this->parse_buffer(buffer, [](GCodeReader&, const GCodeReader::GCodeLine&){}); } template - const char* parse_line(const char *ptr, GCodeLine &gline, Callback &callback) + const char* parse_line(const char *ptr, const char *end, GCodeLine &gline, Callback &callback) { std::pair cmd; - const char *end = parse_line_internal(ptr, gline, cmd); + const char *line_end = parse_line_internal(ptr, end, gline, cmd); callback(*this, gline); update_coordinates(gline, cmd); - return end; + return line_end; } template void parse_line(const std::string &line, Callback callback) - { GCodeLine gline; this->parse_line(line.c_str(), gline, callback); } + { GCodeLine gline; this->parse_line(line.c_str(), line.c_str() + line.size(), gline, callback); } void parse_file(const std::string &file, callback_t callback); void quit_parsing() { m_parsing = false; } @@ -127,7 +128,7 @@ public: // void set_extrusion_axis(char axis) { m_extrusion_axis = axis; } private: - const char* parse_line_internal(const char *ptr, GCodeLine &gline, std::pair &command); + const char* parse_line_internal(const char *ptr, const char *end, GCodeLine &gline, std::pair &command); void update_coordinates(GCodeLine &gline, std::pair &command); static bool is_whitespace(char c) { return c == ' ' || c == '\t'; } From 97d1fe35ad784d41f15dda896448d163e4d8e56a Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Fri, 3 Sep 2021 17:22:28 +0200 Subject: [PATCH 52/82] G-code writer optimization: Don't use std::strstream, it is slow! --- src/libslic3r/GCodeWriter.cpp | 151 +++++++++++++++++++++++----------- 1 file changed, 102 insertions(+), 49 deletions(-) diff --git a/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp index 24549fd895..3aecdfd1f3 100644 --- a/src/libslic3r/GCodeWriter.cpp +++ b/src/libslic3r/GCodeWriter.cpp @@ -1,17 +1,21 @@ #include "GCodeWriter.hpp" #include "CustomGCode.hpp" #include +#include #include #include #include #include +#define XYZF_EXPORT_DIGITS 3 +#define E_EXPORT_DIGITS 5 + #define FLAVOR_IS(val) this->config.gcode_flavor == val #define FLAVOR_IS_NOT(val) this->config.gcode_flavor != val #define COMMENT(comment) if (this->config.gcode_comments && !comment.empty()) gcode << " ; " << comment; #define PRECISION(val, precision) std::fixed << std::setprecision(precision) << (val) -#define XYZF_NUM(val) PRECISION(val, 3) -#define E_NUM(val) PRECISION(val, 5) +#define XYZF_NUM(val) PRECISION(val, XYZF_EXPORT_DIGITS) +#define E_NUM(val) PRECISION(val, E_EXPORT_DIGITS) namespace Slic3r { @@ -288,16 +292,80 @@ std::string GCodeWriter::toolchange(unsigned int extruder_id) return gcode.str(); } +class G1Writer { +private: + static constexpr const size_t buflen = 256; + char buf[buflen]; + char *buf_end; + std::to_chars_result ptr_err; + +public: + G1Writer() { + this->buf[0] = 'G'; + this->buf[1] = '1'; + this->buf_end = this->buf + buflen; + this->ptr_err.ptr = this->buf + 2; + } + + void emit_axis(const char axis, const double v, size_t digits) { + *ptr_err.ptr ++ = ' '; *ptr_err.ptr ++ = axis; + this->ptr_err = std::to_chars(this->ptr_err.ptr, this->buf_end, v, std::chars_format::fixed, digits); + } + + void emit_xy(const Vec2d &point) { + this->emit_axis('X', point.x(), XYZF_EXPORT_DIGITS); + this->emit_axis('Y', point.y(), XYZF_EXPORT_DIGITS); + } + + void emit_xyz(const Vec3d &point) { + this->emit_axis('X', point.x(), XYZF_EXPORT_DIGITS); + this->emit_axis('Y', point.y(), XYZF_EXPORT_DIGITS); + this->emit_z(point.z()); + } + + void emit_z(const double z) { + this->emit_axis('Z', z, XYZF_EXPORT_DIGITS); + } + + void emit_e(const std::string &axis, double v) { + if (! axis.empty()) { + // not gcfNoExtrusion + this->emit_axis(axis[0], v, E_EXPORT_DIGITS); + } + } + + void emit_f(double speed) { + this->emit_axis('F', speed, XYZF_EXPORT_DIGITS); + } + + void emit_string(const std::string &s) { + strncpy(ptr_err.ptr, s.c_str(), s.size()); + ptr_err.ptr += s.size(); + } + + void emit_comment(bool allow_comments, const std::string &comment) { + if (allow_comments && ! comment.empty()) { + *ptr_err.ptr ++ = ' '; *ptr_err.ptr ++ = ';'; *ptr_err.ptr ++ = ' '; + this->emit_string(comment); + } + } + + std::string string() { + *ptr_err.ptr ++ = '\n'; + return std::string(this->buf, ptr_err.ptr - buf); + } +}; + std::string GCodeWriter::set_speed(double F, const std::string &comment, const std::string &cooling_marker) const { assert(F > 0.); assert(F < 100000.); - std::ostringstream gcode; - gcode << "G1 F" << XYZF_NUM(F); - COMMENT(comment); - gcode << cooling_marker; - gcode << "\n"; - return gcode.str(); + + G1Writer w; + w.emit_f(F); + w.emit_comment(this->config.gcode_comments, comment); + w.emit_string(cooling_marker); + return w.string(); } std::string GCodeWriter::travel_to_xy(const Vec2d &point, const std::string &comment) @@ -305,13 +373,11 @@ std::string GCodeWriter::travel_to_xy(const Vec2d &point, const std::string &com m_pos(0) = point(0); m_pos(1) = point(1); - std::ostringstream gcode; - gcode << "G1 X" << XYZF_NUM(point(0)) - << " Y" << XYZF_NUM(point(1)) - << " F" << XYZF_NUM(this->config.travel_speed.value * 60.0); - COMMENT(comment); - gcode << "\n"; - return gcode.str(); + G1Writer w; + w.emit_xy(point); + w.emit_f(this->config.travel_speed.value * 60.0); + w.emit_comment(this->config.gcode_comments, comment); + return w.string(); } std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &comment) @@ -340,14 +406,11 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co m_lifted = 0; m_pos = point; - std::ostringstream gcode; - gcode << "G1 X" << XYZF_NUM(point(0)) - << " Y" << XYZF_NUM(point(1)) - << " Z" << XYZF_NUM(point(2)) - << " F" << XYZF_NUM(this->config.travel_speed.value * 60.0); - COMMENT(comment); - gcode << "\n"; - return gcode.str(); + G1Writer w; + w.emit_xyz(point); + w.emit_f(this->config.travel_speed.value * 60.0); + w.emit_comment(this->config.gcode_comments, comment); + return w.string(); } std::string GCodeWriter::travel_to_z(double z, const std::string &comment) @@ -377,12 +440,11 @@ std::string GCodeWriter::_travel_to_z(double z, const std::string &comment) if (speed == 0.) speed = this->config.travel_speed.value; - std::ostringstream gcode; - gcode << "G1 Z" << XYZF_NUM(z) - << " F" << XYZF_NUM(speed * 60.0); - COMMENT(comment); - gcode << "\n"; - return gcode.str(); + G1Writer w; + w.emit_z(z); + w.emit_f(speed * 60.0); + w.emit_comment(this->config.gcode_comments, comment); + return w.string(); } bool GCodeWriter::will_move_z(double z) const @@ -402,16 +464,12 @@ std::string GCodeWriter::extrude_to_xy(const Vec2d &point, double dE, const std: m_pos(0) = point(0); m_pos(1) = point(1); m_extruder->extrude(dE); - - std::ostringstream gcode; - gcode << "G1 X" << XYZF_NUM(point(0)) - << " Y" << XYZF_NUM(point(1)); - if (! m_extrusion_axis.empty()) - // not gcfNoExtrusion - gcode << " " << m_extrusion_axis << E_NUM(m_extruder->E()); - COMMENT(comment); - gcode << "\n"; - return gcode.str(); + + G1Writer w; + w.emit_xy(point); + w.emit_e(m_extrusion_axis, m_extruder->E()); + w.emit_comment(this->config.gcode_comments, comment); + return w.string(); } std::string GCodeWriter::extrude_to_xyz(const Vec3d &point, double dE, const std::string &comment) @@ -420,16 +478,11 @@ std::string GCodeWriter::extrude_to_xyz(const Vec3d &point, double dE, const std m_lifted = 0; m_extruder->extrude(dE); - std::ostringstream gcode; - gcode << "G1 X" << XYZF_NUM(point(0)) - << " Y" << XYZF_NUM(point(1)) - << " Z" << XYZF_NUM(point(2)); - if (! m_extrusion_axis.empty()) - // not gcfNoExtrusion - gcode << " " << m_extrusion_axis << E_NUM(m_extruder->E()); - COMMENT(comment); - gcode << "\n"; - return gcode.str(); + G1Writer w; + w.emit_xyz(point); + w.emit_e(m_extrusion_axis, m_extruder->E()); + w.emit_comment(this->config.gcode_comments, comment); + return w.string(); } std::string GCodeWriter::retract(bool before_wipe) From 86d06b0be98d0dc53f0afbbcf714475aa21f6e45 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Fri, 3 Sep 2021 17:22:53 +0200 Subject: [PATCH 53/82] G-code processor tiny change: In place initialization --- src/libslic3r/GCode/GCodeProcessor.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 0d71a19f53..73ee0d164e 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -2916,7 +2916,7 @@ void GCodeProcessor::store_move_vertex(EMoveType type) m_line_id + 1 : ((type == EMoveType::Seam) ? m_last_line_id : m_line_id); - MoveVertex vertex = { + m_result.moves.push_back({ m_last_line_id, type, m_extrusion_role, @@ -2931,8 +2931,7 @@ void GCodeProcessor::store_move_vertex(EMoveType type) m_fan_speed, m_extruder_temps[m_extruder_id], static_cast(m_result.moves.size()) - }; - m_result.moves.emplace_back(vertex); + }); // stores stop time placeholders for later use if (type == EMoveType::Color_change || type == EMoveType::Pause_Print) { From d04ece92c379adc9eeb0bc4e42ee0d0610c30907 Mon Sep 17 00:00:00 2001 From: Jason Scurtu Date: Fri, 3 Sep 2021 22:20:12 +0200 Subject: [PATCH 54/82] folder not needed anymore. --- ...om.prusa3d.PrusaSlicer.GCodeViewer.desktop | 10 -- .../flatpak/com.prusa3d.PrusaSlicer.desktop | 20 ---- .../com.prusa3d.PrusaSlicer.metainfo.xml | 106 ------------------ 3 files changed, 136 deletions(-) delete mode 100644 src/platform/unix/flatpak/com.prusa3d.PrusaSlicer.GCodeViewer.desktop delete mode 100755 src/platform/unix/flatpak/com.prusa3d.PrusaSlicer.desktop delete mode 100755 src/platform/unix/flatpak/com.prusa3d.PrusaSlicer.metainfo.xml diff --git a/src/platform/unix/flatpak/com.prusa3d.PrusaSlicer.GCodeViewer.desktop b/src/platform/unix/flatpak/com.prusa3d.PrusaSlicer.GCodeViewer.desktop deleted file mode 100644 index 3177854734..0000000000 --- a/src/platform/unix/flatpak/com.prusa3d.PrusaSlicer.GCodeViewer.desktop +++ /dev/null @@ -1,10 +0,0 @@ -[Desktop Entry] -Name=Prusa GCode viewer -Name[de]=Prusa GCode Vorschau -Exec=prusa-slicer --gcodeviewer %F -Icon=com.prusa3d.PrusaSlicer.GCodeViewer -Terminal=false -Type=Application -MimeType=text/x.gcode; -Categories=Graphics;3DGraphics; -Keywords=3D;Printing;Slicer; diff --git a/src/platform/unix/flatpak/com.prusa3d.PrusaSlicer.desktop b/src/platform/unix/flatpak/com.prusa3d.PrusaSlicer.desktop deleted file mode 100755 index 1ea3e157e7..0000000000 --- a/src/platform/unix/flatpak/com.prusa3d.PrusaSlicer.desktop +++ /dev/null @@ -1,20 +0,0 @@ -[Desktop Entry] -Name=PrusaSlicer -Name[de]=PrusaSlicer -GenericName=3D Printing Software -Icon=com.prusa3d.PrusaSlicer -Exec=prusa-slicer %F -Terminal=false -Type=Application -MimeType=model/stl;model/x-wavefront-obj;model/3mf;model/x-geomview-off;application/x-amf; -Categories=Graphics;3DGraphics;Engineering; -Keywords=3D;Printing;Slicer;slice;3D;printer;convert;gcode;stl;obj;amf;SLA -StartupNotify=false -StartupWMClass=prusa-slicer -Actions=GCodeViewer; - -[Desktop Action GCodeViewer] -Exec=prusa-slicer --gcodeviewer %F -Name=G-Code Viewer -Name[de]=G-Code Vorschau -Icon=com.prusa3d.PrusaSlicer.GCodeViewer diff --git a/src/platform/unix/flatpak/com.prusa3d.PrusaSlicer.metainfo.xml b/src/platform/unix/flatpak/com.prusa3d.PrusaSlicer.metainfo.xml deleted file mode 100755 index c37f43d69f..0000000000 --- a/src/platform/unix/flatpak/com.prusa3d.PrusaSlicer.metainfo.xml +++ /dev/null @@ -1,106 +0,0 @@ - - - com.prusa3d.PrusaSlicer - com.prusa3d.PrusaSlicer.desktop - - prusa-slicer.desktop - - PrusaSlicer -

Powerful 3D printing slicer optimized for Prusa printers - 0BSD - AGPL-3.0-only - -

- PrusaSlicer takes 3D models (STL, OBJ, AMF) and converts them into G-code - instructions for FFF printers or PNG layers for mSLA 3D printers. It's - compatible with any modern printer based on the RepRap toolchain, including all - those based on the Marlin, Prusa, Sprinter and Repetier firmware. It also works - with Mach3, LinuxCNC and Machinekit controllers. -

-

- PrusaSlicer is based on Slic3r by Alessandro Ranelucci and the RepRap community. -

-

- What are some of PrusaSlicer's main features? -

-
    -
  • multi-platform (Linux/Mac/Win) and packaged as standalone-app with no dependencies required
  • -
  • complete command-line interface to use it with no GUI
  • -
  • multi-material (multiple extruders) object printing
  • -
  • multiple G-code flavors supported (RepRap, Makerbot, Mach3, Machinekit etc.)
  • -
  • ability to plate multiple objects having distinct print settings
  • -
  • multithread processing
  • -
  • STL auto-repair (tolerance for broken models)
  • -
  • wide automated unit testing
  • -
-
- https://www.prusa3d.com/prusaslicer/ - https://help.prusa3d.com - https://github.com/prusa3d/PrusaSlicer/issues - - - https://user-images.githubusercontent.com/590307/78981854-24d07580-7b21-11ea-9441-77923534a659.png - - - https://user-images.githubusercontent.com/590307/78981860-2863fc80-7b21-11ea-8c2d-8ff79ced2578.png - - - https://user-images.githubusercontent.com/590307/78981862-28fc9300-7b21-11ea-9b0d-d03e16b709d3.png - - - - - - -

This is the first alpha release of PrusaSlicer 2.4.0, introducing Multi-material painting tool, improved FDM supports and raft, - Windows dark mode, Fuzzy Skin, per object Brim configuration, Negative volumes, automatic Color Print for signs, Shape Gallery, - "Tip of the day" notifications, Model simplification, support for Marlin 2 acceleration control, support of 3DLabPrint airplane models, - new 3rd party printer profiles and many more new features, improvements and bugfixes.

-
-
- - -

PrusaSlicer 2.3.3 is a patch release following PrusaSlicer 2.3.2 release, fixing an unfortunate bug in handling FDM multi-material - project and configuration files #6711.

-
-
- - -

This is a final release of PrusaSlicer 2.3.2, following 2.3.2-beta and 2.3.2-rc. - For the new features in the 2.3.2 series, please read the change logs of the beta and release candidate. - The final release is functionally equal to the release candidate, with a single additional improvement: - Before installing profile updates, a configuration snapshot is taken. In rare circumstances when the current configuration is not consistent, - taking a configuration snapshot fails. PrusaSlicer 2.3.2 newly informs about the issue and offers either to install the configuration updates - even if taking the configuration snapshot failed or to abort update of the profiles.

-
-
- - -

This a final release of PrusaSlicer 2.3.1, introducing native builds for the new Apple Silicon MacBooks, Chrome OS support, performance improvements - in G-code rendering, security fixes and new 3rd party printer profiles. For full changelog on PrusaSlicer 2.3.1 series, please check the PrusaSlicer - 2.3.1-rc change log.

-
-
- - -

This a final release of PrusaSlicer 2.3.0, introducing paint-on supports, ironing, monotonic infill, seam painting, adaptive and support cubic infill, - print time per feature analysis, standalone G-code viewer application, better auto-arrange with a customizable gap and rotation, - search function for the settings, reworked "Avoid crossing perimeters" function, physical printers (network settings), - many new 3rd party printer profiles and much, much more.

-
-
- - -

Development/Unstable Snapshot

-
-
- - -

This is final release of PrusaSlicer 2.2.0 introducing SLA hollowing and hole drilling, support for 3rd party printer vendors, 3Dconnexion support, - automatic variable layer height, macOS dark mode support, greatly improved ColorPrint feature and much, much more. - Several bugs found in the previous release candidate are fixed in this final release. See the respective change logs of the previous releases for all the - new features, improvements and bugfixes in the 2.2.0 series.

-
-
-
- From 9c8c44e4ddc111548e338e6d9ca78d38f97383a6 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 6 Sep 2021 11:37:59 +0200 Subject: [PATCH 55/82] ENABLE_SEAMS_USING_BATCHED_MODELS - Fixed preview legend update --- src/slic3r/GUI/GCodeViewer.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 1e0b9b1242..8bf5ba5d85 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -3764,7 +3764,11 @@ void GCodeViewer::render_legend(float& legend_height) auto add_option = [this, append_item](EMoveType move_type, EOptionsColors color, const std::string& text) { const TBuffer& buffer = m_buffers[buffer_id(move_type)]; if (buffer.visible && buffer.has_data()) +#if ENABLE_SEAMS_USING_BATCHED_MODELS + append_item(EItemType::Circle, Options_Colors[static_cast(color)], text); +#else append_item((buffer.shader == "options_110") ? EItemType::Rect : EItemType::Circle, Options_Colors[static_cast(color)], text); +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS }; // options section From ad41c3f01c94f888e500462e4127574f1fc60766 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 6 Sep 2021 13:15:36 +0200 Subject: [PATCH 56/82] Tech ENABLE_SEAMS_USING_MODELS - Fixed crash when enabling visualization of tool change markers in preview --- src/slic3r/GUI/GCodeViewer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 656a674066..8c2ef573fc 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -2399,7 +2399,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool buffer.model.instances.render_ranges.reset(); - if (!buffer.visible) + if (!buffer.visible || buffer.model.instances.s_ids.empty()) continue; buffer.model.instances.render_ranges.ranges.push_back({ 0, 0, 0, buffer.model.color }); From 7b4c98d72704a86acc99eb57837fd3bcb941f981 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 6 Sep 2021 14:31:10 +0200 Subject: [PATCH 57/82] #6828 - Clamping of toolpaths width performed only for gcodes files produced by 3rd part softwares (Tech ENABLE_CLAMP_TOOLPATHS_WIDTH) --- src/libslic3r/GCode/GCodeProcessor.cpp | 6 ++++++ src/libslic3r/Technologies.hpp | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 73ee0d164e..c4f262675a 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -2252,8 +2252,14 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) // cross section: rectangle + 2 semicircles m_width = delta_pos[E] * static_cast(M_PI * sqr(filament_radius)) / (delta_xyz * m_height) + static_cast(1.0 - 0.25 * M_PI) * m_height; +#if ENABLE_CLAMP_TOOLPATHS_WIDTH + if (m_producers_enabled && m_producer != EProducer::PrusaSlicer) + // clamp width to avoid artifacts which may arise from wrong values of m_height + m_width = std::min(m_width, std::max(1.0f, 4.0f * m_height)); +#else // clamp width to avoid artifacts which may arise from wrong values of m_height m_width = std::min(m_width, std::max(1.0f, 4.0f * m_height)); +#endif // ENABLE_CLAMP_TOOLPATHS_WIDTH #if ENABLE_GCODE_VIEWER_DATA_CHECKING m_width_compare.update(m_width, m_extrusion_role); diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 6132430f1a..405119fc0d 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -57,4 +57,13 @@ #define ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED (1 && ENABLE_2_4_0_ALPHA0) +//==================== +// 2.4.0.alpha2 techs +//==================== +#define ENABLE_2_4_0_ALPHA2 1 + +// Enable clamping toolpaths width only for gcodes files produced by 3rd part softwares +#define ENABLE_CLAMP_TOOLPATHS_WIDTH (1 && ENABLE_2_4_0_ALPHA2) + + #endif // _prusaslicer_technologies_h_ From ce0beabb434b80d8db9117a8db3f056e63bd8bd7 Mon Sep 17 00:00:00 2001 From: Jason Scurtu Date: Fri, 3 Sep 2021 11:56:04 +0200 Subject: [PATCH 58/82] add new mac icon and update MainFrame.cpp --- resources/icons/PrusaSlicer-mac_128px.png | Bin 0 -> 6890 bytes src/slic3r/GUI/MainFrame.cpp | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 resources/icons/PrusaSlicer-mac_128px.png diff --git a/resources/icons/PrusaSlicer-mac_128px.png b/resources/icons/PrusaSlicer-mac_128px.png new file mode 100644 index 0000000000000000000000000000000000000000..ff0b093beb1d3c6b8cf7e215397a654e03549cde GIT binary patch literal 6890 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 - m_taskbar_icon->SetIcon(wxIcon(Slic3r::var("PrusaSlicer_128px.png"), wxBITMAP_TYPE_PNG), "PrusaSlicer"); + m_taskbar_icon->SetIcon(wxIcon(Slic3r::var("PrusaSlicer-mac_128px.png"), wxBITMAP_TYPE_PNG), "PrusaSlicer"); break; case GUI_App::EAppMode::GCodeViewer: m_taskbar_icon = std::make_unique(wxTBI_DOCK); From 07bdb5fbe3df35f18e7c800b136d7da52c2a1fcc Mon Sep 17 00:00:00 2001 From: Jason Scurtu Date: Fri, 3 Sep 2021 12:08:24 +0200 Subject: [PATCH 59/82] add gcodeviewer --- .../icons/PrusaSlicer-gcodeviewer-mac-128px.png | Bin 0 -> 12218 bytes src/slic3r/GUI/MainFrame.cpp | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 resources/icons/PrusaSlicer-gcodeviewer-mac-128px.png diff --git a/resources/icons/PrusaSlicer-gcodeviewer-mac-128px.png b/resources/icons/PrusaSlicer-gcodeviewer-mac-128px.png new file mode 100644 index 0000000000000000000000000000000000000000..b62f3fddc84e662f1b011cc19aad7128781cb3ca GIT binary patch literal 12218 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 KAYLVE82BGiN2+}Q literal 0 HcmV?d00001 diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 687333f190..31acc1c576 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -146,7 +146,7 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S break; case GUI_App::EAppMode::GCodeViewer: m_taskbar_icon = std::make_unique(wxTBI_DOCK); - m_taskbar_icon->SetIcon(wxIcon(Slic3r::var("PrusaSlicer-gcodeviewer_128px.png"), wxBITMAP_TYPE_PNG), "G-code Viewer"); + m_taskbar_icon->SetIcon(wxIcon(Slic3r::var("PrusaSlicer-gcodeviewer-mac-128px.png"), wxBITMAP_TYPE_PNG), "G-code Viewer"); break; } #endif // __APPLE__ From b41e3214736ad4fdf8789f39db7a8e206a54807b Mon Sep 17 00:00:00 2001 From: Jason Scurtu Date: Fri, 3 Sep 2021 12:09:32 +0200 Subject: [PATCH 60/82] rename --- ...px.png => PrusaSlicer-gcodeviewer-mac_128px.png} | Bin src/slic3r/GUI/MainFrame.cpp | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename resources/icons/{PrusaSlicer-gcodeviewer-mac-128px.png => PrusaSlicer-gcodeviewer-mac_128px.png} (100%) diff --git a/resources/icons/PrusaSlicer-gcodeviewer-mac-128px.png b/resources/icons/PrusaSlicer-gcodeviewer-mac_128px.png similarity index 100% rename from resources/icons/PrusaSlicer-gcodeviewer-mac-128px.png rename to resources/icons/PrusaSlicer-gcodeviewer-mac_128px.png diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 31acc1c576..51dbc201d3 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -146,7 +146,7 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S break; case GUI_App::EAppMode::GCodeViewer: m_taskbar_icon = std::make_unique(wxTBI_DOCK); - m_taskbar_icon->SetIcon(wxIcon(Slic3r::var("PrusaSlicer-gcodeviewer-mac-128px.png"), wxBITMAP_TYPE_PNG), "G-code Viewer"); + m_taskbar_icon->SetIcon(wxIcon(Slic3r::var("PrusaSlicer-gcodeviewer-mac_128px.png"), wxBITMAP_TYPE_PNG), "G-code Viewer"); break; } #endif // __APPLE__ From 428509ac00885348cf5455ae1b6eadfd0e96f6ca Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Mon, 6 Sep 2021 18:08:13 +0200 Subject: [PATCH 61/82] Pimped up GCodeProcessor::TimeProcessor::post_process(): replaced implicit lambda capture with explicit listing of captured context for readability and code correctness. Captured this as const. --- src/libslic3r/GCode/GCodeProcessor.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index c4f262675a..e375179e23 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -476,11 +476,19 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st g1_times_cache_it.emplace_back(machine.g1_times_cache.begin()); // add lines M73 to exported gcode - auto process_line_G1 = [&]() { + auto process_line_G1 = [ + // Lambdas, mostly for string formatting, all with an empty capture block. + time_in_minutes, format_time_float, format_line_M73_main, format_line_M73_stop_int, format_line_M73_stop_float, time_in_last_minute, + &self = std::as_const(*this), + // Caches, to be modified + &g1_times_cache_it, &last_exported_main, &last_exported_stop, + // String output + &export_line] + (const size_t g1_lines_counter) { unsigned int exported_lines_count = 0; - if (export_remaining_time_enabled) { + if (self.export_remaining_time_enabled) { for (size_t i = 0; i < static_cast(PrintEstimatedStatistics::ETimeMode::Count); ++i) { - const TimeMachine& machine = machines[i]; + const TimeMachine& machine = self.machines[i]; if (machine.enabled) { // export pair // Skip all machine.g1_times_cache below g1_lines_counter. @@ -581,8 +589,7 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st parser.parse_line(gcode_line, [&](GCodeReader& reader, const GCodeReader::GCodeLine& line) { if (line.cmd_is("G1")) { - unsigned int extra_lines_count = process_line_G1(); - ++g1_lines_counter; + unsigned int extra_lines_count = process_line_G1(g1_lines_counter ++); if (extra_lines_count > 0) offsets.push_back({ line_id, extra_lines_count }); } From 0bc77cef3ec30075b14a01702e3a3877964516a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Tue, 7 Sep 2021 07:33:57 +0200 Subject: [PATCH 62/82] Fixed build on Linux and macOS that was failing because of using std::to_chars and std::from_chars with floating-point values. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old version of GCC and Clang support only integers to be passed to std::to_chars and std::from_chars. macOS older version of Clang doesn't support std::from_chars at all. So for Linux and macOS, it was replaced std::from_chars with strtod and temporarily was replace std::to_chars with snprintf. --- src/libslic3r/GCodeReader.cpp | 7 +++++++ src/libslic3r/GCodeWriter.cpp | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/src/libslic3r/GCodeReader.cpp b/src/libslic3r/GCodeReader.cpp index 54e6802e62..aa52685397 100644 --- a/src/libslic3r/GCodeReader.cpp +++ b/src/libslic3r/GCodeReader.cpp @@ -71,9 +71,16 @@ const char* GCodeReader::parse_line_internal(const char *ptr, const char *end, G } if (axis != NUM_AXES_WITH_UNKNOWN) { // Try to parse the numeric value. +#ifdef WIN32 double v; auto [pend, ec] = std::from_chars(++ c, end, v); if (pend != c && is_end_of_word(*pend)) { +#else + // The older version of GCC and Clang support std::from_chars just for integers, so strtod we used it instead. + char *pend = nullptr; + double v = strtod(++ c, &pend); + if (pend != nullptr && is_end_of_word(*pend)) { +#endif // The axis value has been parsed correctly. if (axis != UNKNOWN_AXIS) gline.m_axis[int(axis)] = float(v); diff --git a/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp index 3aecdfd1f3..c97180982d 100644 --- a/src/libslic3r/GCodeWriter.cpp +++ b/src/libslic3r/GCodeWriter.cpp @@ -309,7 +309,16 @@ public: void emit_axis(const char axis, const double v, size_t digits) { *ptr_err.ptr ++ = ' '; *ptr_err.ptr ++ = axis; +#ifdef WIN32 this->ptr_err = std::to_chars(this->ptr_err.ptr, this->buf_end, v, std::chars_format::fixed, digits); +#else + int buf_capacity = int(this->buf_end - this->ptr_err.ptr); + int ret = snprintf(this->ptr_err.ptr, buf_capacity, "%.*lf", int(digits), v); + if (ret <= 0 || ret > buf_capacity) + ptr_err.ec = std::errc::value_too_large; + else + this->ptr_err.ptr = this->ptr_err.ptr + ret; +#endif } void emit_xy(const Vec2d &point) { From d35183921b0696effd194a0cb47cce83020f5efc Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 7 Sep 2021 09:41:14 +0200 Subject: [PATCH 63/82] Revert of 7b4c98d72704a86acc99eb57837fd3bcb941f981, clamp toolpaths widths increased to 2mm and added default values for toolpaths width and height --- src/libslic3r/GCode/GCodeProcessor.cpp | 26 +++++++++++++------------- src/libslic3r/Technologies.hpp | 9 --------- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index e375179e23..2c58c2a25e 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -21,6 +21,9 @@ #include +static const float DEFAULT_TOOLPATH_WIDTH = 0.4f; +static const float DEFAULT_TOOLPATH_HEIGHT = 0.2f; + static const float INCHES_TO_MM = 25.4f; static const float MMMIN_TO_MMSEC = 1.0f / 60.0f; static const float DEFAULT_ACCELERATION = 1500.0f; // Prusa Firmware 1_75mm_MK2 @@ -2217,9 +2220,6 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) return; EMoveType type = move_type(delta_pos); - if (type == EMoveType::Extrude && m_end_position[Z] == 0.0f) - type = EMoveType::Travel; - if (type == EMoveType::Extrude) { float delta_xyz = std::sqrt(sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z])); float volume_extruded_filament = area_filament_cross_section * delta_pos[E]; @@ -2243,6 +2243,12 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) } } + if (m_height == 0.0f) + m_height = DEFAULT_TOOLPATH_HEIGHT; + + if (m_end_position[Z] == 0.0f) + m_end_position[Z] = m_height; + #if ENABLE_GCODE_VIEWER_DATA_CHECKING m_height_compare.update(m_height, m_extrusion_role); #endif // ENABLE_GCODE_VIEWER_DATA_CHECKING @@ -2259,23 +2265,17 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) // cross section: rectangle + 2 semicircles m_width = delta_pos[E] * static_cast(M_PI * sqr(filament_radius)) / (delta_xyz * m_height) + static_cast(1.0 - 0.25 * M_PI) * m_height; -#if ENABLE_CLAMP_TOOLPATHS_WIDTH - if (m_producers_enabled && m_producer != EProducer::PrusaSlicer) - // clamp width to avoid artifacts which may arise from wrong values of m_height - m_width = std::min(m_width, std::max(1.0f, 4.0f * m_height)); -#else + if (m_width == 0.0f) + m_width = DEFAULT_TOOLPATH_WIDTH; + // clamp width to avoid artifacts which may arise from wrong values of m_height - m_width = std::min(m_width, std::max(1.0f, 4.0f * m_height)); -#endif // ENABLE_CLAMP_TOOLPATHS_WIDTH + m_width = std::min(m_width, std::max(2.0f, 4.0f * m_height)); #if ENABLE_GCODE_VIEWER_DATA_CHECKING m_width_compare.update(m_width, m_extrusion_role); #endif // ENABLE_GCODE_VIEWER_DATA_CHECKING } - if (type == EMoveType::Extrude && (m_width == 0.0f || m_height == 0.0f)) - type = EMoveType::Travel; - // time estimate section auto move_length = [](const AxisCoords& delta_pos) { float sq_xyz_length = sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z]); diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 405119fc0d..6132430f1a 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -57,13 +57,4 @@ #define ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED (1 && ENABLE_2_4_0_ALPHA0) -//==================== -// 2.4.0.alpha2 techs -//==================== -#define ENABLE_2_4_0_ALPHA2 1 - -// Enable clamping toolpaths width only for gcodes files produced by 3rd part softwares -#define ENABLE_CLAMP_TOOLPATHS_WIDTH (1 && ENABLE_2_4_0_ALPHA2) - - #endif // _prusaslicer_technologies_h_ From 5c9bc26ed5efee227dad831e89702f331a5891b5 Mon Sep 17 00:00:00 2001 From: Justin Schuh Date: Tue, 7 Sep 2021 00:45:10 -0700 Subject: [PATCH 64/82] Replace OpenProcess with GetCurrentProcess where appropriate (#6914) GetCurrentProcess is more correct and resolves spurious AV warnings. --- src/libslic3r/BlacklistedLibraryCheck.cpp | 11 ++++------- src/libslic3r/utils.cpp | 15 +++++---------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/libslic3r/BlacklistedLibraryCheck.cpp b/src/libslic3r/BlacklistedLibraryCheck.cpp index d9dea188f5..76f675c707 100644 --- a/src/libslic3r/BlacklistedLibraryCheck.cpp +++ b/src/libslic3r/BlacklistedLibraryCheck.cpp @@ -33,22 +33,20 @@ std::wstring BlacklistedLibraryCheck::get_blacklisted_string() bool BlacklistedLibraryCheck::perform_check() { - // Get a handle to the process. - HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, GetCurrentProcessId()); - if (NULL == hProcess) - return false; + // Get the pseudo-handle for the current process. + HANDLE hCurrentProcess = GetCurrentProcess(); // Get a list of all the modules in this process. HMODULE hMods[1024]; DWORD cbNeeded; - if (EnumProcessModulesEx(hProcess, hMods, sizeof(hMods), &cbNeeded, LIST_MODULES_ALL)) + if (EnumProcessModulesEx(hCurrentProcess, hMods, sizeof(hMods), &cbNeeded, LIST_MODULES_ALL)) { //printf("Total Dlls: %d\n", cbNeeded / sizeof(HMODULE)); for (unsigned int i = 0; i < cbNeeded / sizeof(HMODULE); ++ i) { wchar_t szModName[MAX_PATH]; // Get the full path to the module's file. - if (GetModuleFileNameExW(hProcess, hMods[i], szModName, MAX_PATH)) + if (GetModuleFileNameExW(hCurrentProcess, hMods[i], szModName, MAX_PATH)) { // Add to list if blacklisted if (BlacklistedLibraryCheck::is_blacklisted(szModName)) { @@ -61,7 +59,6 @@ bool BlacklistedLibraryCheck::perform_check() } } - CloseHandle(hProcess); //printf("\n"); return !m_found.empty(); } diff --git a/src/libslic3r/utils.cpp b/src/libslic3r/utils.cpp index c330f34b2b..c5dbdac9cd 100644 --- a/src/libslic3r/utils.cpp +++ b/src/libslic3r/utils.cpp @@ -984,16 +984,11 @@ std::string log_memory_info(bool ignore_loglevel) } PROCESS_MEMORY_COUNTERS_EX, *PPROCESS_MEMORY_COUNTERS_EX; #endif /* PROCESS_MEMORY_COUNTERS_EX */ - - HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ::GetCurrentProcessId()); - if (hProcess != nullptr) { - PROCESS_MEMORY_COUNTERS_EX pmc; - if (GetProcessMemoryInfo(hProcess, (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc))) - out = " WorkingSet: " + format_memsize_MB(pmc.WorkingSetSize) + "; PrivateBytes: " + format_memsize_MB(pmc.PrivateUsage) + "; Pagefile(peak): " + format_memsize_MB(pmc.PagefileUsage) + "(" + format_memsize_MB(pmc.PeakPagefileUsage) + ")"; - else - out += " Used memory: N/A"; - CloseHandle(hProcess); - } + PROCESS_MEMORY_COUNTERS_EX pmc; + if (GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc))) + out = " WorkingSet: " + format_memsize_MB(pmc.WorkingSetSize) + "; PrivateBytes: " + format_memsize_MB(pmc.PrivateUsage) + "; Pagefile(peak): " + format_memsize_MB(pmc.PagefileUsage) + "(" + format_memsize_MB(pmc.PeakPagefileUsage) + ")"; + else + out += " Used memory: N/A"; #elif defined(__linux__) or defined(__APPLE__) // Get current memory usage. #ifdef __APPLE__ From c1c8a60271083e3577a150b19042c052787a5891 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 7 Sep 2021 11:13:12 +0200 Subject: [PATCH 65/82] Changed color for toolpaths whose extrusion role is unknown --- src/slic3r/GUI/GCodeViewer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 8c2ef573fc..49fd17ce84 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -503,7 +503,7 @@ void GCodeViewer::SequentialView::render(float legend_height) const } const std::vector GCodeViewer::Extrusion_Role_Colors {{ - { 0.75f, 0.75f, 0.75f, 1.0f }, // erNone + { 0.90f, 0.70f, 0.70f, 1.0f }, // erNone { 1.00f, 0.90f, 0.30f, 1.0f }, // erPerimeter { 1.00f, 0.49f, 0.22f, 1.0f }, // erExternalPerimeter { 0.12f, 0.12f, 1.00f, 1.0f }, // erOverhangPerimeter From 771a8927763f312401fa73b92cb950c31d2fd89b Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Tue, 7 Sep 2021 11:18:07 +0200 Subject: [PATCH 66/82] Optimization of GCodeProcessor for speed. --- src/libslic3r/GCode/GCodeProcessor.cpp | 306 +++++++++++++++++-------- src/libslic3r/GCodeReader.cpp | 12 +- src/libslic3r/GCodeReader.hpp | 15 +- 3 files changed, 232 insertions(+), 101 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 2c58c2a25e..142dd015df 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -360,7 +360,8 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nCannot open file for writing.\n")); auto time_in_minutes = [](float time_in_seconds) { - return int(::roundf(time_in_seconds / 60.0f)); + assert(time_in_seconds >= 0.f); + return int((time_in_seconds + 0.5f) / 60.0f); }; auto time_in_last_minute = [](float time_in_seconds) { @@ -392,7 +393,6 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st return std::string(line_M73); }; - GCodeReader parser; std::string gcode_line; size_t g1_lines_counter = 0; // keeps track of last exported pair @@ -411,11 +411,12 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st std::string export_line; // replace placeholder lines with the proper final value - auto process_placeholders = [&](const std::string& gcode_line) { + // gcode_line is in/out parameter, to reduce expensive memory allocation + auto process_placeholders = [&](std::string& gcode_line) { unsigned int extra_lines_count = 0; // remove trailing '\n' - std::string line = gcode_line.substr(0, gcode_line.length() - 1); + auto line = std::string_view(gcode_line).substr(0, gcode_line.length() - 1); std::string ret; if (line.length() > 1) { @@ -456,7 +457,10 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st } } - return std::tuple(!ret.empty(), ret.empty() ? gcode_line : ret, (extra_lines_count == 0) ? extra_lines_count : extra_lines_count - 1); + if (! ret.empty()) + // Not moving the move operator on purpose, so that the gcode_line allocation will grow and it will not be reallocated after handful of lines are processed. + gcode_line = ret; + return std::tuple(!ret.empty(), (extra_lines_count == 0) ? extra_lines_count : extra_lines_count - 1); }; // check for temporary lines @@ -569,39 +573,56 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st unsigned int line_id = 0; std::vector> offsets; - while (std::getline(in, gcode_line)) { - if (!in.good()) { - fclose(out); - throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nError while reading from file.\n")); - } + { + // Read the input stream 64kB at a time, extract lines and process them. + in.sync_with_stdio(false); + std::vector buffer(65536 * 10, 0); + // Line buffer. + assert(gcode_line.empty()); + while (! in.eof()) { + in.read(buffer.data(), buffer.size()); + if (! in.eof() && ! in.good()) { + fclose(out); + throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nError while reading from file.\n")); + } + auto it = buffer.begin(); + auto it_bufend = buffer.begin() + in.gcount(); + while (it != it_bufend) { + // Find end of line. + bool eol = false; + auto it_end = it; + for (; it_end != it_bufend && ! (eol = *it_end == '\r' || *it_end == '\n'); ++ it_end) ; + // End of line is indicated also if end of file was reached. + eol |= in.eof() && it_end == it_bufend; + gcode_line.insert(gcode_line.end(), it, it_end); + if (eol) { + ++line_id; - ++line_id; - - gcode_line += "\n"; - // replace placeholder lines - auto [processed, result, lines_added_count] = process_placeholders(gcode_line); - if (processed && lines_added_count > 0) - offsets.push_back({ line_id, lines_added_count }); - gcode_line = result; - if (!processed) { - // remove temporary lines - if (is_temporary_decoration(gcode_line)) - continue; - - // add lines M73 where needed - parser.parse_line(gcode_line, - [&](GCodeReader& reader, const GCodeReader::GCodeLine& line) { - if (line.cmd_is("G1")) { + gcode_line += "\n"; + // replace placeholder lines + auto [processed, lines_added_count] = process_placeholders(gcode_line); + if (processed && lines_added_count > 0) + offsets.push_back({ line_id, lines_added_count }); + if (! processed && ! is_temporary_decoration(gcode_line) && GCodeReader::GCodeLine::cmd_is(gcode_line, "G1")) { + // remove temporary lines, add lines M73 where needed unsigned int extra_lines_count = process_line_G1(g1_lines_counter ++); if (extra_lines_count > 0) offsets.push_back({ line_id, extra_lines_count }); } - }); - } - export_line += gcode_line; - if (export_line.length() > 65535) - write_string(export_line); + export_line += gcode_line; + if (export_line.length() > 65535) + write_string(export_line); + gcode_line.clear(); + } + // Skip EOL. + it = it_end; + if (it != it_bufend && *it == '\r') + ++ it; + if (it != it_bufend && *it == '\n') + ++ it; + } + } } if (!export_line.empty()) @@ -1171,8 +1192,6 @@ void GCodeProcessor::reset() void GCodeProcessor::process_file(const std::string& filename, bool apply_postprocess, std::function cancel_callback) { - auto last_cancel_callback_time = std::chrono::high_resolution_clock::now(); - CNumericLocalesSetter locales_setter; #if ENABLE_GCODE_VIEWER_STATISTICS @@ -1184,7 +1203,7 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr if (m_producers_enabled) { m_parser.parse_file(filename, [this](GCodeReader& reader, const GCodeReader::GCodeLine& line) { const std::string_view cmd = line.cmd(); - if (cmd.length() == 0) { + if (cmd.empty()) { const std::string_view comment = line.comment(); if (comment.length() > 1 && detect_producer(comment)) m_parser.quit_parsing(); @@ -1211,17 +1230,15 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr m_result.id = ++s_result_id; // 1st move must be a dummy move m_result.moves.emplace_back(MoveVertex()); - m_parser.parse_file(filename, [this, cancel_callback, &last_cancel_callback_time](GCodeReader& reader, const GCodeReader::GCodeLine& line) { - if (cancel_callback != nullptr) { - // call the cancel callback every 100 ms - auto curr_time = std::chrono::high_resolution_clock::now(); - if (std::chrono::duration_cast(curr_time - last_cancel_callback_time).count() > 100) { - cancel_callback(); - last_cancel_callback_time = curr_time; - } + size_t parse_line_callback_cntr = 10000; + m_parser.parse_file(filename, [this, cancel_callback, &parse_line_callback_cntr](GCodeReader& reader, const GCodeReader::GCodeLine& line) { + if (-- parse_line_callback_cntr == 0) { + // Don't call the cancel_callback() too often, do it every at every 10000'th line. + parse_line_callback_cntr = 10000; + cancel_callback(); } - process_gcode_line(line); - }); + this->process_gcode_line(line); + }); // update width/height of wipe moves for (MoveVertex& move : m_result.moves) { @@ -1401,61 +1418,170 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line) const std::string_view cmd = line.cmd(); if (cmd.length() > 1) { // process command lines - switch (::toupper(cmd[0])) + switch (cmd[0]) { + case 'g': case 'G': - { - switch (::atoi(&cmd[1])) - { - case 0: { process_G0(line); break; } // Move - case 1: { process_G1(line); break; } // Move - case 10: { process_G10(line); break; } // Retract - case 11: { process_G11(line); break; } // Unretract - case 20: { process_G20(line); break; } // Set Units to Inches - case 21: { process_G21(line); break; } // Set Units to Millimeters - case 22: { process_G22(line); break; } // Firmware controlled retract - case 23: { process_G23(line); break; } // Firmware controlled unretract - case 28: { process_G28(line); break; } // Move to origin - case 90: { process_G90(line); break; } // Set to Absolute Positioning - case 91: { process_G91(line); break; } // Set to Relative Positioning - case 92: { process_G92(line); break; } // Set Position - default: { break; } + switch (cmd.size()) { + case 2: + switch (cmd[1]) { + case '0': { process_G0(line); break; } // Move + case '1': { process_G1(line); break; } // Move + default: break; } break; + case 3: + switch (cmd[1]) { + case '1': + switch (cmd[2]) { + case '0': { process_G10(line); break; } // Retract + case '1': { process_G11(line); break; } // Unretract + default: break; + } + break; + case '2': + switch (cmd[2]) { + case '0': { process_G20(line); break; } // Set Units to Inches + case '1': { process_G21(line); break; } // Set Units to Millimeters + case '2': { process_G22(line); break; } // Firmware controlled retract + case '3': { process_G23(line); break; } // Firmware controlled unretract + case '8': { process_G28(line); break; } // Move to origin + default: break; + } + break; + case '9': + switch (cmd[2]) { + case '0': { process_G90(line); break; } // Set to Absolute Positioning + case '1': { process_G91(line); break; } // Set to Relative Positioning + case '2': { process_G92(line); break; } // Set Position + default: break; + } + break; + } + break; + default: + break; } + break; + case 'm': case 'M': - { - switch (::atoi(&cmd[1])) - { - case 1: { process_M1(line); break; } // Sleep or Conditional stop - case 82: { process_M82(line); break; } // Set extruder to absolute mode - case 83: { process_M83(line); break; } // Set extruder to relative mode - case 104: { process_M104(line); break; } // Set extruder temperature - case 106: { process_M106(line); break; } // Set fan speed - case 107: { process_M107(line); break; } // Disable fan - case 108: { process_M108(line); break; } // Set tool (Sailfish) - case 109: { process_M109(line); break; } // Set extruder temperature and wait - case 132: { process_M132(line); break; } // Recall stored home offsets - case 135: { process_M135(line); break; } // Set tool (MakerWare) - case 201: { process_M201(line); break; } // Set max printing acceleration - case 203: { process_M203(line); break; } // Set maximum feedrate - case 204: { process_M204(line); break; } // Set default acceleration - case 205: { process_M205(line); break; } // Advanced settings - case 221: { process_M221(line); break; } // Set extrude factor override percentage - case 401: { process_M401(line); break; } // Repetier: Store x, y and z position - case 402: { process_M402(line); break; } // Repetier: Go to stored position - case 566: { process_M566(line); break; } // Set allowable instantaneous speed change - case 702: { process_M702(line); break; } // Unload the current filament into the MK3 MMU2 unit at the end of print. - default: { break; } + switch (cmd.size()) { + case 2: + switch (cmd[1]) { + case '1': { process_M1(line); break; } // Sleep or Conditional stop + default: break; } break; - } - case 'T': - { - process_T(line); // Select Tool + case 3: + switch (cmd[1]) { + case '8': + switch (cmd[2]) { + case '2': { process_M82(line); break; } // Set extruder to absolute mode + case '3': { process_M83(line); break; } // Set extruder to relative mode + default: break; + } + break; + default: + break; + } + break; + case 4: + switch (cmd[1]) { + case '1': + switch (cmd[2]) { + case '0': + switch (cmd[3]) { + case '4': { process_M104(line); break; } // Set extruder temperature + case '6': { process_M106(line); break; } // Set fan speed + case '7': { process_M107(line); break; } // Disable fan + case '8': { process_M108(line); break; } // Set tool (Sailfish) + case '9': { process_M109(line); break; } // Set extruder temperature and wait + default: break; + } + break; + case '3': + switch (cmd[3]) { + case '2': { process_M132(line); break; } // Recall stored home offsets + case '5': { process_M135(line); break; } // Set tool (MakerWare) + default: break; + } + break; + default: + break; + } + break; + case '2': + switch (cmd[2]) { + case '0': + switch (cmd[3]) { + case '1': { process_M201(line); break; } // Set max printing acceleration + case '3': { process_M203(line); break; } // Set maximum feedrate + case '4': { process_M204(line); break; } // Set default acceleration + case '5': { process_M205(line); break; } // Advanced settings + default: break; + } + break; + case '2': + switch (cmd[3]) { + case '1': { process_M221(line); break; } // Set extrude factor override percentage + default: break; + } + break; + default: + break; + } + break; + case '4': + switch (cmd[2]) { + case '0': + switch (cmd[3]) { + case '1': { process_M401(line); break; } // Repetier: Store x, y and z position + case '2': { process_M402(line); break; } // Repetier: Go to stored position + default: break; + } + break; + default: + break; + } + break; + case '5': + switch (cmd[2]) { + case '6': + switch (cmd[3]) { + case '6': { process_M566(line); break; } // Set allowable instantaneous speed change + default: break; + } + break; + default: + break; + } + break; + case '7': + switch (cmd[2]) { + case '0': + switch (cmd[3]) { + case '2': { process_M702(line); break; } // Unload the current filament into the MK3 MMU2 unit at the end of print. + default: break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + default: break; } - default: { break; } + break; + case 't': + case 'T': + process_T(line); // Select Tool + break; + default: + break; } } else { diff --git a/src/libslic3r/GCodeReader.cpp b/src/libslic3r/GCodeReader.cpp index aa52685397..4c4bebee44 100644 --- a/src/libslic3r/GCodeReader.cpp +++ b/src/libslic3r/GCodeReader.cpp @@ -133,7 +133,7 @@ void GCodeReader::update_coordinates(GCodeLine &gline, std::pairhas(Y) ? (this->y() - reader.y()) : 0; return sqrt(x*x + y*y); } - bool cmd_is(const char *cmd_test) const { - const char *cmd = GCodeReader::skip_whitespaces(m_raw.c_str()); - size_t len = strlen(cmd_test); - return strncmp(cmd, cmd_test, len) == 0 && GCodeReader::is_end_of_word(cmd[len]); - } + bool cmd_is(const char *cmd_test) const { return cmd_is(m_raw, cmd_test); } bool extruding(const GCodeReader &reader) const { return this->cmd_is("G1") && this->dist_E(reader) > 0; } bool retracting(const GCodeReader &reader) const { return this->cmd_is("G1") && this->dist_E(reader) < 0; } bool travel() const { return this->cmd_is("G1") && ! this->has(E); } @@ -66,6 +62,12 @@ public: float e() const { return m_axis[E]; } float f() const { return m_axis[F]; } + static bool cmd_is(const std::string &gcode_line, const char *cmd_test) { + const char *cmd = GCodeReader::skip_whitespaces(gcode_line.c_str()); + size_t len = strlen(cmd_test); + return strncmp(cmd, cmd_test, len) == 0 && GCodeReader::is_end_of_word(cmd[len]); + } + private: std::string m_raw; float m_axis[NUM_AXES]; @@ -109,7 +111,8 @@ public: void parse_line(const std::string &line, Callback callback) { GCodeLine gline; this->parse_line(line.c_str(), line.c_str() + line.size(), gline, callback); } - void parse_file(const std::string &file, callback_t callback); + // Returns false if reading the file failed. + bool parse_file(const std::string &file, callback_t callback); void quit_parsing() { m_parsing = false; } float& x() { return m_position[X]; } From af20419ed4997bc08f419b13dead78eb905a10b3 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 7 Sep 2021 11:18:58 +0200 Subject: [PATCH 67/82] Fix for #6903 - Compare presets window titles inaccurate... --- src/slic3r/GUI/UnsavedChangesDialog.cpp | 16 +++++++++++----- src/slic3r/GUI/UnsavedChangesDialog.hpp | 3 ++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/slic3r/GUI/UnsavedChangesDialog.cpp b/src/slic3r/GUI/UnsavedChangesDialog.cpp index 2b63bc79b6..ef480f60f8 100644 --- a/src/slic3r/GUI/UnsavedChangesDialog.cpp +++ b/src/slic3r/GUI/UnsavedChangesDialog.cpp @@ -696,7 +696,12 @@ void DiffViewCtrl::context_menu(wxDataViewEvent& event) auto it = m_items_map.find(item); if (it == m_items_map.end() || !it->second.is_long) return; - FullCompareDialog(it->second.opt_name, it->second.old_val, it->second.new_val).ShowModal(); + + size_t column_cnt = this->GetColumnCount(); + const wxString old_value_header = this->GetColumn(column_cnt - 2)->GetTitle(); + const wxString new_value_header = this->GetColumn(column_cnt - 1)->GetTitle(); + FullCompareDialog(it->second.opt_name, it->second.old_val, it->second.new_val, + old_value_header, new_value_header).ShowModal(); #ifdef __WXOSX__ wxWindow* parent = this->GetParent(); @@ -1281,7 +1286,8 @@ void UnsavedChangesDialog::on_sys_color_changed() // FullCompareDialog //------------------------------------------ -FullCompareDialog::FullCompareDialog(const wxString& option_name, const wxString& old_value, const wxString& new_value) +FullCompareDialog::FullCompareDialog(const wxString& option_name, const wxString& old_value, const wxString& new_value, + const wxString& old_value_header, const wxString& new_value_header) : wxDialog(nullptr, wxID_ANY, option_name, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { wxGetApp().UpdateDarkUI(this); @@ -1302,8 +1308,8 @@ FullCompareDialog::FullCompareDialog(const wxString& option_name, const wxString grid_sizer->Add(text, 0, wxALL, border); }; - add_header(_L("Old value")); - add_header(_L("New value")); + add_header(old_value_header); + add_header(new_value_header); auto get_set_from_val = [](wxString str) { if (str.Find("\n") == wxNOT_FOUND) @@ -1327,7 +1333,7 @@ FullCompareDialog::FullCompareDialog(const wxString& option_name, const wxString std::set_difference(new_set.begin(), new_set.end(), old_set.begin(), old_set.end(), std::inserter(new_old_diff_set, new_old_diff_set.begin())); auto add_value = [grid_sizer, border, this](wxString label, const std::set& diff_set, bool is_colored = false) { - wxTextCtrl* text = new wxTextCtrl(this, wxID_ANY, label, wxDefaultPosition, wxSize(400, 400), wxTE_MULTILINE | wxTE_READONLY | wxBORDER_SIMPLE | wxTE_RICH); + wxTextCtrl* text = new wxTextCtrl(this, wxID_ANY, label, wxDefaultPosition, wxSize(400, 400), wxTE_MULTILINE | wxTE_READONLY | wxBORDER_DEFAULT | wxTE_RICH); wxGetApp().UpdateDarkUI(text); text->SetStyle(0, label.Len(), wxTextAttr(is_colored ? wxColour(orange) : wxNullColour, wxNullColour, this->GetFont())); diff --git a/src/slic3r/GUI/UnsavedChangesDialog.hpp b/src/slic3r/GUI/UnsavedChangesDialog.hpp index 9667430334..9dbaf6e99c 100644 --- a/src/slic3r/GUI/UnsavedChangesDialog.hpp +++ b/src/slic3r/GUI/UnsavedChangesDialog.hpp @@ -299,7 +299,8 @@ protected: class FullCompareDialog : public wxDialog { public: - FullCompareDialog(const wxString& option_name, const wxString& old_value, const wxString& new_value); + FullCompareDialog(const wxString& option_name, const wxString& old_value, const wxString& new_value, + const wxString& old_value_header, const wxString& new_value_header); ~FullCompareDialog() {} }; From 761c06ed9282c76475ab9986cd0cd0a5c340022d Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 7 Sep 2021 12:25:30 +0200 Subject: [PATCH 68/82] GCodeViewer - Fixed crash when importing gcode generated with Simplify3D and switching to tool view --- src/libslic3r/GCode/GCodeProcessor.cpp | 13 +++++++++---- src/slic3r/GUI/GCodeViewer.cpp | 4 ++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 2c58c2a25e..4b38020c11 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -961,10 +961,9 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config) } // replace missing values with default - std::string default_color = "#FF8000"; for (size_t i = 0; i < m_result.extruder_colors.size(); ++i) { if (m_result.extruder_colors[i].empty()) - m_result.extruder_colors[i] = default_color; + m_result.extruder_colors[i] = "#FF8000"; } m_extruder_colors.resize(m_result.extruder_colors.size()); @@ -1350,7 +1349,7 @@ void GCodeProcessor::apply_config_simplify3d(const std::string& filename) if (pos != cmt.npos) { std::string data_str = cmt.substr(pos + 1); std::vector values_str; - boost::split(values_str, data_str, boost::is_any_of("|"), boost::token_compress_on); + boost::split(values_str, data_str, boost::is_any_of("|,"), boost::token_compress_on); for (const std::string& s : values_str) { out.emplace_back(static_cast(string_to_double_decimal_point(s))); } @@ -1374,10 +1373,16 @@ void GCodeProcessor::apply_config_simplify3d(const std::string& filename) m_result.filament_densities.clear(); extract_floats(comment, "filamentDensities", m_result.filament_densities); } + else if (comment.find("extruderDiameter") != comment.npos) { + std::vector extruder_diameters; + extract_floats(comment, "extruderDiameter", extruder_diameters); + m_result.extruders_count = extruder_diameters.size(); + } } }); - m_result.extruders_count = std::max(1, std::min(m_result.filament_diameters.size(), m_result.filament_densities.size())); + if (m_result.extruders_count == 0) + m_result.extruders_count = std::max(1, std::min(m_result.filament_diameters.size(), m_result.filament_densities.size())); if (bed_size.is_defined()) { m_result.bed_shape = { diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 49fd17ce84..979214fb5a 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -695,8 +695,8 @@ void GCodeViewer::refresh(const GCodeProcessor::Result& gcode_result, const std: // update tool colors m_tool_colors = decode_colors(str_tool_colors); - // ensure at least one (default) color is defined - if (m_tool_colors.empty()) + // ensure there are enough colors defined + while (m_tool_colors.size() < std::max(size_t(1), gcode_result.extruders_count)) m_tool_colors.push_back(decode_color("#FF8000")); // update ranges for coloring / legend From e30ff22b8a2d586abb3b023519b40f715c44e1ad Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Tue, 7 Sep 2021 14:20:16 +0200 Subject: [PATCH 69/82] GCodePostProcessor - use C files instead of C++ streams, C files are faster. Also fixed a regression - crashes on undefined cancellation callback. --- src/libslic3r/GCode/GCodeProcessor.cpp | 48 +++++++++++++++----------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index f7709e9d68..aa6912fc48 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -347,17 +347,25 @@ void GCodeProcessor::TimeProcessor::reset() machines[static_cast(PrintEstimatedStatistics::ETimeMode::Normal)].enabled = true; } +struct FilePtr { + FilePtr(FILE *f) : f(f) {} + ~FilePtr() { this->close(); } + void close() { if (f) ::fclose(f); } + FILE* f = nullptr; +}; + void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, std::vector& moves) { - boost::nowide::ifstream in(filename); - if (!in.good()) + FilePtr in{ boost::nowide::fopen(filename.c_str(), "rb") }; + if (in.f == nullptr) throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nCannot open file for reading.\n")); // temporary file to contain modified gcode std::string out_path = filename + ".postprocess"; - FILE* out = boost::nowide::fopen(out_path.c_str(), "wb"); - if (out == nullptr) + FilePtr out{ boost::nowide::fopen(out_path.c_str(), "wb") }; + if (out.f == nullptr) { throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nCannot open file for writing.\n")); + } auto time_in_minutes = [](float time_in_seconds) { assert(time_in_seconds >= 0.f); @@ -559,11 +567,10 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st }; // helper function to write to disk - auto write_string = [&](const std::string& str) { - fwrite((const void*)export_line.c_str(), 1, export_line.length(), out); - if (ferror(out)) { - in.close(); - fclose(out); + auto write_string = [&export_line, &out, &out_path](const std::string& str) { + fwrite((const void*)export_line.c_str(), 1, export_line.length(), out.f); + if (ferror(out.f)) { + out.close(); boost::nowide::remove(out_path.c_str()); throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nIs the disk full?\n")); } @@ -575,25 +582,23 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st { // Read the input stream 64kB at a time, extract lines and process them. - in.sync_with_stdio(false); std::vector buffer(65536 * 10, 0); // Line buffer. assert(gcode_line.empty()); - while (! in.eof()) { - in.read(buffer.data(), buffer.size()); - if (! in.eof() && ! in.good()) { - fclose(out); + for (;;) { + size_t cnt_read = ::fread(buffer.data(), 1, buffer.size(), in.f); + if (::ferror(in.f)) throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nError while reading from file.\n")); - } + bool eof = cnt_read == 0; auto it = buffer.begin(); - auto it_bufend = buffer.begin() + in.gcount(); - while (it != it_bufend) { + auto it_bufend = buffer.begin() + cnt_read; + while (it != it_bufend || (eof && ! gcode_line.empty())) { // Find end of line. bool eol = false; auto it_end = it; for (; it_end != it_bufend && ! (eol = *it_end == '\r' || *it_end == '\n'); ++ it_end) ; // End of line is indicated also if end of file was reached. - eol |= in.eof() && it_end == it_bufend; + eol |= eof && it_end == it_bufend; gcode_line.insert(gcode_line.end(), it, it_end); if (eol) { ++line_id; @@ -622,13 +627,15 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st if (it != it_bufend && *it == '\n') ++ it; } + if (eof) + break; } } if (!export_line.empty()) write_string(export_line); - fclose(out); + out.close(); in.close(); // updates moves' gcode ids which have been modified by the insertion of the M73 lines @@ -1234,7 +1241,8 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr if (-- parse_line_callback_cntr == 0) { // Don't call the cancel_callback() too often, do it every at every 10000'th line. parse_line_callback_cntr = 10000; - cancel_callback(); + if (cancel_callback) + cancel_callback(); } this->process_gcode_line(line); }); From 719c91514bd71cf04d4abec70a958fd3710f5f01 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 7 Sep 2021 15:19:59 +0200 Subject: [PATCH 70/82] ObjectList:: Allow use BACKSPACE to delete selected items --- src/slic3r/GUI/GUI_ObjectList.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index c99d9090cb..bf174cbf12 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1044,13 +1044,8 @@ void ObjectList::key_event(wxKeyEvent& event) { if (event.GetKeyCode() == WXK_TAB) Navigate(event.ShiftDown() ? wxNavigationKeyEvent::IsBackward : wxNavigationKeyEvent::IsForward); - else if (event.GetKeyCode() == WXK_DELETE -#ifdef __WXOSX__ - || event.GetKeyCode() == WXK_BACK -#endif //__WXOSX__ - ) { + else if (event.GetKeyCode() == WXK_DELETE || event.GetKeyCode() == WXK_BACK ) remove(); - } else if (event.GetKeyCode() == WXK_F5) wxGetApp().plater()->reload_all_from_disk(); else if (wxGetKeyState(wxKeyCode('A')) && wxGetKeyState(WXK_CONTROL/*WXK_SHIFT*/)) From 32733b7db943ccf823a27f9fca83a17c8aaae350 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Tue, 7 Sep 2021 15:42:50 +0200 Subject: [PATCH 71/82] GCodeProcessor collects positions of line ends for GCodeViewer, GCodeViewer no more parses G-code just to extract line end positions. Removed start_mapping_gcode_window(), void stop_mapping_gcode_window(), they are no more needed. --- src/libslic3r/GCode/GCodeProcessor.cpp | 16 ++++-- src/libslic3r/GCode/GCodeProcessor.hpp | 4 +- src/slic3r/GUI/BackgroundSlicingProcess.cpp | 5 +- src/slic3r/GUI/GCodeViewer.cpp | 62 ++++----------------- src/slic3r/GUI/GCodeViewer.hpp | 9 +-- src/slic3r/GUI/GLCanvas3D.cpp | 10 ---- src/slic3r/GUI/GLCanvas3D.hpp | 3 - src/slic3r/GUI/Plater.cpp | 10 ---- src/slic3r/GUI/Plater.hpp | 3 - 9 files changed, 30 insertions(+), 92 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index aa6912fc48..ec586dbef7 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -354,7 +354,7 @@ struct FilePtr { FILE* f = nullptr; }; -void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, std::vector& moves) +void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, std::vector& moves, std::vector& lines_ends) { FilePtr in{ boost::nowide::fopen(filename.c_str(), "rb") }; if (in.f == nullptr) @@ -567,13 +567,19 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st }; // helper function to write to disk - auto write_string = [&export_line, &out, &out_path](const std::string& str) { + size_t out_file_pos = 0; + lines_ends.clear(); + auto write_string = [&export_line, &out, &out_path, &out_file_pos, &lines_ends](const std::string& str) { fwrite((const void*)export_line.c_str(), 1, export_line.length(), out.f); if (ferror(out.f)) { out.close(); boost::nowide::remove(out_path.c_str()); throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nIs the disk full?\n")); } + for (size_t i = 0; i < export_line.size(); ++ i) + if (export_line[i] == '\n') + lines_ends.emplace_back(out_file_pos + i + 1); + out_file_pos += export_line.size(); export_line.clear(); }; @@ -736,7 +742,9 @@ void GCodeProcessor::Result::reset() { } #else void GCodeProcessor::Result::reset() { - moves = std::vector(); + + moves.clear(); + lines_ends.clear(); bed_shape = Pointfs(); settings_ids.reset(); extruders_count = 0; @@ -1270,7 +1278,7 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr // post-process to add M73 lines into the gcode if (apply_postprocess) - m_time_processor.post_process(filename, m_result.moves); + m_time_processor.post_process(filename, m_result.moves, m_result.lines_ends); #if ENABLE_GCODE_VIEWER_DATA_CHECKING std::cout << "\n"; diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 4fcdd8df39..bb93108881 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -306,7 +306,7 @@ namespace Slic3r { // post process the file with the given filename to add remaining time lines M73 // and updates moves' gcode ids accordingly - void post_process(const std::string& filename, std::vector& moves); + void post_process(const std::string& filename, std::vector& moves, std::vector& lines_ends); }; struct UsedFilaments // filaments per ColorChange @@ -350,6 +350,8 @@ namespace Slic3r { std::string filename; unsigned int id; std::vector moves; + // Positions of ends of lines of the final G-code this->filename after TimeProcessor::post_process() finalizes the G-code. + std::vector lines_ends; Pointfs bed_shape; SettingsIds settings_ids; size_t extruders_count; diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.cpp b/src/slic3r/GUI/BackgroundSlicingProcess.cpp index 8a58e5ec93..b4de4a509f 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.cpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.cpp @@ -574,11 +574,8 @@ Print::ApplyStatus BackgroundSlicingProcess::apply(const Model &model, const Dyn // Some FFF status was invalidated, and the G-code was not exported yet. // Let the G-code preview UI know that the final G-code preview is not valid. // In addition, this early memory deallocation reduces memory footprint. - if (m_gcode_result != nullptr) { - //FIXME calling platter from here is not a staple of a good architecture. - GUI::wxGetApp().plater()->stop_mapping_gcode_window(); + if (m_gcode_result != nullptr) m_gcode_result->reset(); - } } return invalidated; } diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 979214fb5a..946cbb2759 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -284,45 +284,14 @@ void GCodeViewer::SequentialView::Marker::render() const ImGui::PopStyleVar(); } -void GCodeViewer::SequentialView::GCodeWindow::load_gcode() +void GCodeViewer::SequentialView::GCodeWindow::load_gcode(const std::string& filename, const std::vector &lines_ends) { - if (m_filename.empty()) - return; - + assert(! m_file.is_open()); if (m_file.is_open()) return; - try - { - // generate mapping for accessing data in file by line number - boost::nowide::ifstream f(m_filename); - - f.seekg(0, f.end); - uint64_t file_length = static_cast(f.tellg()); - f.seekg(0, f.beg); - - std::string line; - uint64_t offset = 0; - while (std::getline(f, line)) { - uint64_t line_length = static_cast(line.length()); - m_lines_map.push_back({ offset, line_length }); - offset += static_cast(line_length) + 1; - } - - if (offset != file_length) { - // if the final offset does not match with file length, lines are terminated with CR+LF - // so update all offsets accordingly - for (size_t i = 0; i < m_lines_map.size(); ++i) { - m_lines_map[i].first += static_cast(i); - } - } - } - catch (...) - { - BOOST_LOG_TRIVIAL(error) << "Unable to load data from " << m_filename << ". Cannot show G-code window."; - reset(); - return; - } + m_filename = filename; + m_lines_ends = std::move(lines_ends); m_selected_line_id = 0; m_last_lines_size = 0; @@ -345,7 +314,9 @@ void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, u ret.reserve(end_id - start_id + 1); for (uint64_t id = start_id; id <= end_id; ++id) { // read line from file - std::string gline(m_file.data() + m_lines_map[id - 1].first, m_lines_map[id - 1].second); + const size_t start = id == 1 ? 0 : m_lines_ends[id - 2]; + const size_t len = m_lines_ends[id - 1] - start; + std::string gline(m_file.data() + start, len); std::string command; std::string parameters; @@ -379,7 +350,7 @@ void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, u static const ImVec4 PARAMETERS_COLOR = { 1.0f, 1.0f, 1.0f, 1.0f }; static const ImVec4 COMMENT_COLOR = { 0.7f, 0.7f, 0.7f, 1.0f }; - if (!m_visible || m_filename.empty() || m_lines_map.empty() || curr_line_id == 0) + if (!m_visible || m_filename.empty() || m_lines_ends.empty() || curr_line_id == 0) return; // window height @@ -397,8 +368,8 @@ void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, u const uint64_t half_lines_count = lines_count / 2; uint64_t start_id = (curr_line_id >= half_lines_count) ? curr_line_id - half_lines_count : 0; uint64_t end_id = start_id + lines_count - 1; - if (end_id >= static_cast(m_lines_map.size())) { - end_id = static_cast(m_lines_map.size()) - 1; + if (end_id >= static_cast(m_lines_ends.size())) { + end_id = static_cast(m_lines_ends.size()) - 1; start_id = end_id - lines_count + 1; } @@ -606,8 +577,7 @@ void GCodeViewer::load(const GCodeProcessor::Result& gcode_result, const Print& // release gpu memory, if used reset(); - m_sequential_view.gcode_window.set_filename(gcode_result.filename); - m_sequential_view.gcode_window.load_gcode(); + m_sequential_view.gcode_window.load_gcode(gcode_result.filename, gcode_result.lines_ends); #if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER if (wxGetApp().is_gcode_viewer()) @@ -1146,16 +1116,6 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const fclose(fp); } -void GCodeViewer::start_mapping_gcode_window() -{ - m_sequential_view.gcode_window.load_gcode(); -} - -void GCodeViewer::stop_mapping_gcode_window() -{ - m_sequential_view.gcode_window.stop_mapping_file(); -} - void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) { // max index buffer size, in bytes diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 429175fe68..b918dee238 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -639,18 +639,17 @@ public: std::string m_filename; boost::iostreams::mapped_file_source m_file; // map for accessing data in file by line number - std::vector> m_lines_map; + std::vector m_lines_ends; // current visible lines std::vector m_lines; public: GCodeWindow() = default; ~GCodeWindow() { stop_mapping_file(); } - void set_filename(const std::string& filename) { m_filename = filename; } - void load_gcode(); + void load_gcode(const std::string& filename, const std::vector &lines_ends); void reset() { stop_mapping_file(); - m_lines_map.clear(); + m_lines_ends.clear(); m_lines.clear(); m_filename.clear(); } @@ -777,8 +776,6 @@ public: void export_toolpaths_to_obj(const char* filename) const; - void start_mapping_gcode_window(); - void stop_mapping_gcode_window(); void toggle_gcode_window_visibility() { m_sequential_view.gcode_window.toggle_visibility(); } #if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index e281892204..f50c7fe25b 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1114,16 +1114,6 @@ int GLCanvas3D::check_volumes_outside_state() const return (int)state; } -void GLCanvas3D::start_mapping_gcode_window() -{ - m_gcode_viewer.start_mapping_gcode_window(); -} - -void GLCanvas3D::stop_mapping_gcode_window() -{ - m_gcode_viewer.stop_mapping_gcode_window(); -} - void GLCanvas3D::toggle_sla_auxiliaries_visibility(bool visible, const ModelObject* mo, int instance_idx) { m_render_sla_auxiliaries = visible; diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 3750e3a3e2..799fa11c79 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -621,9 +621,6 @@ public: const GCodeViewer::SequentialView& get_gcode_sequential_view() const { return m_gcode_viewer.get_sequential_view(); } void update_gcode_sequential_view_current(unsigned int first, unsigned int last) { m_gcode_viewer.update_sequential_view_current(first, last); } - void start_mapping_gcode_window(); - void stop_mapping_gcode_window(); - void toggle_sla_auxiliaries_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1); void toggle_model_objects_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1); void update_instance_printable_state_for_object(size_t obj_idx); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index af8734184f..2c77dcb7ac 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -6143,16 +6143,6 @@ BoundingBoxf Plater::bed_shape_bb() const return p->bed_shape_bb(); } -void Plater::start_mapping_gcode_window() -{ - p->preview->get_canvas3d()->start_mapping_gcode_window(); -} - -void Plater::stop_mapping_gcode_window() -{ - p->preview->get_canvas3d()->stop_mapping_gcode_window(); -} - void Plater::arrange() { p->m_ui_jobs.arrange(); diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 99f7e3cdaa..f1a493b0f0 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -282,9 +282,6 @@ public: GLCanvas3D* get_current_canvas3D(); BoundingBoxf bed_shape_bb() const; - void start_mapping_gcode_window(); - void stop_mapping_gcode_window(); - void arrange(); void find_new_position(const ModelInstancePtrs &instances); From b5a007a683124ec3b01b61e892ed8eb39c034248 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Tue, 7 Sep 2021 16:23:43 +0200 Subject: [PATCH 72/82] WIP to G-code export parallelization through pipelining: New class GCodeOutputStream as a G-code consumer. In the following steps the GCodeOutputStream will be pipelined with GCodeProcessor. --- src/libslic3r/GCode.cpp | 152 ++++++++++++++++++++-------------------- src/libslic3r/GCode.hpp | 48 ++++++++----- 2 files changed, 107 insertions(+), 93 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 19909b2bcf..54815188eb 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -744,27 +744,27 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessor::Result* re std::string path_tmp(path); path_tmp += ".tmp"; - FILE *file = boost::nowide::fopen(path_tmp.c_str(), "wb"); - if (file == nullptr) + GCodeOutputStream file(boost::nowide::fopen(path_tmp.c_str(), "wb")); + if (! file.is_open()) throw Slic3r::RuntimeError(std::string("G-code export to ") + path + " failed.\nCannot open the file for writing.\n"); try { m_placeholder_parser_failed_templates.clear(); this->_do_export(*print, file, thumbnail_cb); - fflush(file); - if (ferror(file)) { - fclose(file); + file.flush(); + if (file.is_error()) { + file.close(); boost::nowide::remove(path_tmp.c_str()); throw Slic3r::RuntimeError(std::string("G-code export to ") + path + " failed\nIs the disk full?\n"); } } catch (std::exception & /* ex */) { // Rethrow on any exception. std::runtime_exception and CanceledException are expected to be thrown. // Close and remove the file. - fclose(file); + file.close(); boost::nowide::remove(path_tmp.c_str()); throw; } - fclose(file); + file.close(); if (! m_placeholder_parser_failed_templates.empty()) { // G-code export proceeded, but some of the PlaceholderParser substitutions failed. @@ -1046,7 +1046,7 @@ std::vector sort_object_instances_by_model_order(const Pri return instances; } -void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thumbnail_cb) +void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGeneratorCallback thumbnail_cb) { PROFILE_FUNC(); @@ -1111,10 +1111,10 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu #endif /* HAS_PRESSURE_EQUALIZER */ // Write information on the generator. - _write_format(file, "; %s\n\n", Slic3r::header_slic3r_generated().c_str()); + file.write_format("; %s\n\n", Slic3r::header_slic3r_generated().c_str()); DoExport::export_thumbnails_to_file(thumbnail_cb, print.full_print_config().option("thumbnails")->values, - [this, file](const char* sz) { this->_write(file, sz); }, + [&file](const char* sz) { file.write(sz); }, [&print]() { print.throw_if_canceled(); }); // Write notes (content of the Print Settings tab -> Notes) @@ -1125,10 +1125,10 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu // Remove the trailing '\r' from the '\r\n' sequence. if (! line.empty() && line.back() == '\r') line.pop_back(); - _write_format(file, "; %s\n", line.c_str()); + file.write_format("; %s\n", line.c_str()); } if (! lines.empty()) - _write(file, "\n"); + file.write("\n"); } print.throw_if_canceled(); @@ -1139,22 +1139,22 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu const double first_layer_height = print.config().first_layer_height.value; for (size_t region_id = 0; region_id < print.num_print_regions(); ++ region_id) { const PrintRegion ®ion = print.get_print_region(region_id); - _write_format(file, "; external perimeters extrusion width = %.2fmm\n", region.flow(*first_object, frExternalPerimeter, layer_height).width()); - _write_format(file, "; perimeters extrusion width = %.2fmm\n", region.flow(*first_object, frPerimeter, layer_height).width()); - _write_format(file, "; infill extrusion width = %.2fmm\n", region.flow(*first_object, frInfill, layer_height).width()); - _write_format(file, "; solid infill extrusion width = %.2fmm\n", region.flow(*first_object, frSolidInfill, layer_height).width()); - _write_format(file, "; top infill extrusion width = %.2fmm\n", region.flow(*first_object, frTopSolidInfill, layer_height).width()); + file.write_format("; external perimeters extrusion width = %.2fmm\n", region.flow(*first_object, frExternalPerimeter, layer_height).width()); + file.write_format("; perimeters extrusion width = %.2fmm\n", region.flow(*first_object, frPerimeter, layer_height).width()); + file.write_format("; infill extrusion width = %.2fmm\n", region.flow(*first_object, frInfill, layer_height).width()); + file.write_format("; solid infill extrusion width = %.2fmm\n", region.flow(*first_object, frSolidInfill, layer_height).width()); + file.write_format("; top infill extrusion width = %.2fmm\n", region.flow(*first_object, frTopSolidInfill, layer_height).width()); if (print.has_support_material()) - _write_format(file, "; support material extrusion width = %.2fmm\n", support_material_flow(first_object).width()); + file.write_format("; support material extrusion width = %.2fmm\n", support_material_flow(first_object).width()); if (print.config().first_layer_extrusion_width.value > 0) - _write_format(file, "; first layer extrusion width = %.2fmm\n", region.flow(*first_object, frPerimeter, first_layer_height, true).width()); - _write_format(file, "\n"); + file.write_format("; first layer extrusion width = %.2fmm\n", region.flow(*first_object, frPerimeter, first_layer_height, true).width()); + file.write_format("\n"); } print.throw_if_canceled(); // adds tags for time estimators if (print.config().remaining_times.value) - _write_format(file, ";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::First_Line_M73_Placeholder).c_str()); + file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::First_Line_M73_Placeholder).c_str()); // Prepare the helper object for replacing placeholders in custom G-code and output filename. m_placeholder_parser = print.placeholder_parser(); @@ -1218,7 +1218,7 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu // Disable fan. if (! print.config().cooling.get_at(initial_extruder_id) || print.config().disable_fan_first_layers.get_at(initial_extruder_id)) - _write(file, m_writer.set_fan(0, true)); + file.write(m_writer.set_fan(0, true)); // Let the start-up script prime the 1st printing tool. m_placeholder_parser.set("initial_tool", initial_extruder_id); @@ -1261,10 +1261,10 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu this->_print_first_layer_extruder_temperatures(file, print, start_gcode, initial_extruder_id, false); // adds tag for processor - _write_format(file, ";%s%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role).c_str(), ExtrusionEntity::role_to_string(erCustom).c_str()); + file.write_format(";%s%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role).c_str(), ExtrusionEntity::role_to_string(erCustom).c_str()); // Write the custom start G-code - _writeln(file, start_gcode); + file.writeln(start_gcode); // Process filament-specific gcode. /* if (has_wipe_tower) { @@ -1272,14 +1272,14 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu } else { DynamicConfig config; config.set_key_value("filament_extruder_id", new ConfigOptionInt(int(initial_extruder_id))); - _writeln(file, this->placeholder_parser_process("start_filament_gcode", print.config().start_filament_gcode.values[initial_extruder_id], initial_extruder_id, &config)); + file.writeln(this->placeholder_parser_process("start_filament_gcode", print.config().start_filament_gcode.values[initial_extruder_id], initial_extruder_id, &config)); } */ this->_print_first_layer_extruder_temperatures(file, print, start_gcode, initial_extruder_id, true); print.throw_if_canceled(); // Set other general things. - _write(file, this->preamble()); + file.write(this->preamble()); // Calculate wiping points if needed DoExport::init_ooze_prevention(print, m_ooze_prevention); @@ -1291,7 +1291,7 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu if (! (has_wipe_tower && print.config().single_extruder_multi_material_priming)) { // Set initial extruder only after custom start G-code. // Ugly hack: Do not set the initial extruder if the extruder is primed using the MMU priming towers at the edge of the print bed. - _write(file, this->set_extruder(initial_extruder_id, 0.)); + file.write(this->set_extruder(initial_extruder_id, 0.)); } // Do all objects for each layer. @@ -1317,8 +1317,8 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu // This happens before Z goes down to layer 0 again, so that no collision happens hopefully. m_enable_cooling_markers = false; // we're not filtering these moves through CoolingBuffer m_avoid_crossing_perimeters.use_external_mp_once(); - _write(file, this->retract()); - _write(file, this->travel_to(Point(0, 0), erNone, "move to origin position for next object")); + file.write(this->retract()); + file.write(this->travel_to(Point(0, 0), erNone, "move to origin position for next object")); m_enable_cooling_markers = true; // Disable motion planner when traveling to first object point. m_avoid_crossing_perimeters.disable_once(); @@ -1330,7 +1330,7 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu // Set first layer bed and extruder temperatures, don't wait for it to reach the temperature. this->_print_first_layer_bed_temperature(file, print, between_objects_gcode, initial_extruder_id, false); this->_print_first_layer_extruder_temperatures(file, print, between_objects_gcode, initial_extruder_id, false); - _writeln(file, between_objects_gcode); + file.writeln(between_objects_gcode); } // Reset the cooling buffer internal state (the current position, feed rate, accelerations). m_cooling_buffer->reset(); @@ -1346,7 +1346,7 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu } #ifdef HAS_PRESSURE_EQUALIZER if (m_pressure_equalizer) - _write(file, m_pressure_equalizer->process("", true)); + file.write(m_pressure_equalizer->process("", true)); #endif /* HAS_PRESSURE_EQUALIZER */ ++ finished_objects; // Flag indicating whether the nozzle temperature changes from 1st to 2nd layer were performed. @@ -1361,9 +1361,9 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu // Prusa Multi-Material wipe tower. if (has_wipe_tower && ! layers_to_print.empty()) { m_wipe_tower.reset(new WipeTowerIntegration(print.config(), *print.wipe_tower_data().priming.get(), print.wipe_tower_data().tool_changes, *print.wipe_tower_data().final_purge.get())); - _write(file, m_writer.travel_to_z(first_layer_height + m_config.z_offset.value, "Move to the first layer height")); + file.write(m_writer.travel_to_z(first_layer_height + m_config.z_offset.value, "Move to the first layer height")); if (print.config().single_extruder_multi_material_priming) { - _write(file, m_wipe_tower->prime(*this)); + file.write(m_wipe_tower->prime(*this)); // Verify, whether the print overaps the priming extrusions. BoundingBoxf bbox_print(get_print_extrusions_extents(print)); coordf_t twolayers_printz = ((layers_to_print.size() == 1) ? layers_to_print.front() : layers_to_print[1]).first + EPSILON; @@ -1375,15 +1375,15 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu bool overlap = bbox_prime.overlap(bbox_print); if (print.config().gcode_flavor == gcfMarlinLegacy || print.config().gcode_flavor == gcfMarlinFirmware) { - _write(file, this->retract()); - _write(file, "M300 S800 P500\n"); // Beep for 500ms, tone 800Hz. + file.write(this->retract()); + file.write("M300 S800 P500\n"); // Beep for 500ms, tone 800Hz. if (overlap) { // Wait for the user to remove the priming extrusions. - _write(file, "M1 Remove priming towers and click button.\n"); + file.write("M1 Remove priming towers and click button.\n"); } else { // Just wait for a bit to let the user check, that the priming succeeded. //TODO Add a message explaining what the printer is waiting for. This needs a firmware fix. - _write(file, "M1 S10\n"); + file.write("M1 S10\n"); } } else { // This is not Marlin, M1 command is probably not supported. @@ -1410,19 +1410,19 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu } #ifdef HAS_PRESSURE_EQUALIZER if (m_pressure_equalizer) - _write(file, m_pressure_equalizer->process("", true)); + file.write(m_pressure_equalizer->process("", true)); #endif /* HAS_PRESSURE_EQUALIZER */ if (m_wipe_tower) // Purge the extruder, pull out the active filament. - _write(file, m_wipe_tower->finalize(*this)); + file.write(m_wipe_tower->finalize(*this)); } // Write end commands to file. - _write(file, this->retract()); - _write(file, m_writer.set_fan(false)); + file.write(this->retract()); + file.write(m_writer.set_fan(false)); // adds tag for processor - _write_format(file, ";%s%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role).c_str(), ExtrusionEntity::role_to_string(erCustom).c_str()); + file.write_format(";%s%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role).c_str(), ExtrusionEntity::role_to_string(erCustom).c_str()); // Process filament-specific gcode in extruder order. { @@ -1434,48 +1434,48 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu // Process the end_filament_gcode for the active filament only. int extruder_id = m_writer.extruder()->id(); config.set_key_value("filament_extruder_id", new ConfigOptionInt(extruder_id)); - _writeln(file, this->placeholder_parser_process("end_filament_gcode", print.config().end_filament_gcode.get_at(extruder_id), extruder_id, &config)); + file.writeln(this->placeholder_parser_process("end_filament_gcode", print.config().end_filament_gcode.get_at(extruder_id), extruder_id, &config)); } else { for (const std::string &end_gcode : print.config().end_filament_gcode.values) { int extruder_id = (unsigned int)(&end_gcode - &print.config().end_filament_gcode.values.front()); config.set_key_value("filament_extruder_id", new ConfigOptionInt(extruder_id)); - _writeln(file, this->placeholder_parser_process("end_filament_gcode", end_gcode, extruder_id, &config)); + file.writeln(this->placeholder_parser_process("end_filament_gcode", end_gcode, extruder_id, &config)); } } - _writeln(file, this->placeholder_parser_process("end_gcode", print.config().end_gcode, m_writer.extruder()->id(), &config)); + file.writeln(this->placeholder_parser_process("end_gcode", print.config().end_gcode, m_writer.extruder()->id(), &config)); } - _write(file, m_writer.update_progress(m_layer_count, m_layer_count, true)); // 100% - _write(file, m_writer.postamble()); + file.write(m_writer.update_progress(m_layer_count, m_layer_count, true)); // 100% + file.write(m_writer.postamble()); // adds tags for time estimators if (print.config().remaining_times.value) - _write_format(file, ";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Last_Line_M73_Placeholder).c_str()); + file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Last_Line_M73_Placeholder).c_str()); print.throw_if_canceled(); // Get filament stats. - _write(file, DoExport::update_print_stats_and_format_filament_stats( + file.write(DoExport::update_print_stats_and_format_filament_stats( // Const inputs has_wipe_tower, print.wipe_tower_data(), m_writer.extruders(), // Modifies print.m_print_statistics)); - _write(file, "\n"); - _write_format(file, "; total filament used [g] = %.2lf\n", print.m_print_statistics.total_weight); - _write_format(file, "; total filament cost = %.2lf\n", print.m_print_statistics.total_cost); + file.write("\n"); + file.write_format("; total filament used [g] = %.2lf\n", print.m_print_statistics.total_weight); + file.write_format("; total filament cost = %.2lf\n", print.m_print_statistics.total_cost); if (print.m_print_statistics.total_toolchanges > 0) - _write_format(file, "; total toolchanges = %i\n", print.m_print_statistics.total_toolchanges); - _write_format(file, ";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Estimated_Printing_Time_Placeholder).c_str()); + file.write_format("; total toolchanges = %i\n", print.m_print_statistics.total_toolchanges); + file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Estimated_Printing_Time_Placeholder).c_str()); // Append full config, delimited by two 'phony' configuration keys prusaslicer_config = begin and prusaslicer_config = end. // The delimiters are structured as configuration key / value pairs to be parsable by older versions of PrusaSlicer G-code viewer. { - _write(file, "\n; prusaslicer_config = begin\n"); + file.write("\n; prusaslicer_config = begin\n"); std::string full_config; append_full_config(print, full_config); if (!full_config.empty()) - _write(file, full_config); - _write(file, "; prusaslicer_config = end\n"); + file.write(full_config); + file.write("; prusaslicer_config = end\n"); } print.throw_if_canceled(); } @@ -1565,16 +1565,16 @@ static bool custom_gcode_sets_temperature(const std::string &gcode, const int mc // Print the machine envelope G-code for the Marlin firmware based on the "machine_max_xxx" parameters. // Do not process this piece of G-code by the time estimator, it already knows the values through another sources. -void GCode::print_machine_envelope(FILE *file, Print &print) +void GCode::print_machine_envelope(GCodeOutputStream &file, Print &print) { if ((print.config().gcode_flavor.value == gcfMarlinLegacy || print.config().gcode_flavor.value == gcfMarlinFirmware) && print.config().machine_limits_usage.value == MachineLimitsUsage::EmitToGCode) { - fprintf(file, "M201 X%d Y%d Z%d E%d ; sets maximum accelerations, mm/sec^2\n", + file.write_format("M201 X%d Y%d Z%d E%d ; sets maximum accelerations, mm/sec^2\n", int(print.config().machine_max_acceleration_x.values.front() + 0.5), int(print.config().machine_max_acceleration_y.values.front() + 0.5), int(print.config().machine_max_acceleration_z.values.front() + 0.5), int(print.config().machine_max_acceleration_e.values.front() + 0.5)); - fprintf(file, "M203 X%d Y%d Z%d E%d ; sets maximum feedrates, mm/sec\n", + file.write_format("M203 X%d Y%d Z%d E%d ; sets maximum feedrates, mm/sec\n", int(print.config().machine_max_feedrate_x.values.front() + 0.5), int(print.config().machine_max_feedrate_y.values.front() + 0.5), int(print.config().machine_max_feedrate_z.values.front() + 0.5), @@ -1587,18 +1587,18 @@ void GCode::print_machine_envelope(FILE *file, Print &print) int travel_acc = print.config().gcode_flavor == gcfMarlinLegacy ? int(print.config().machine_max_acceleration_extruding.values.front() + 0.5) : int(print.config().machine_max_acceleration_travel.values.front() + 0.5); - fprintf(file, "M204 P%d R%d T%d ; sets acceleration (P, T) and retract acceleration (R), mm/sec^2\n", + file.write_format("M204 P%d R%d T%d ; sets acceleration (P, T) and retract acceleration (R), mm/sec^2\n", int(print.config().machine_max_acceleration_extruding.values.front() + 0.5), int(print.config().machine_max_acceleration_retracting.values.front() + 0.5), travel_acc); assert(is_decimal_separator_point()); - fprintf(file, "M205 X%.2lf Y%.2lf Z%.2lf E%.2lf ; sets the jerk limits, mm/sec\n", + file.write_format("M205 X%.2lf Y%.2lf Z%.2lf E%.2lf ; sets the jerk limits, mm/sec\n", print.config().machine_max_jerk_x.values.front(), print.config().machine_max_jerk_y.values.front(), print.config().machine_max_jerk_z.values.front(), print.config().machine_max_jerk_e.values.front()); - fprintf(file, "M205 S%d T%d ; sets the minimum extruding and travel feed rate, mm/sec\n", + file.write_format("M205 S%d T%d ; sets the minimum extruding and travel feed rate, mm/sec\n", int(print.config().machine_min_extruding_rate.values.front() + 0.5), int(print.config().machine_min_travel_rate.values.front() + 0.5)); } @@ -1608,7 +1608,7 @@ void GCode::print_machine_envelope(FILE *file, Print &print) // Only do that if the start G-code does not already contain any M-code controlling an extruder temperature. // M140 - Set Extruder Temperature // M190 - Set Extruder Temperature and Wait -void GCode::_print_first_layer_bed_temperature(FILE *file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait) +void GCode::_print_first_layer_bed_temperature(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait) { // Initial bed temperature based on the first extruder. int temp = print.config().first_layer_bed_temperature.get_at(first_printing_extruder_id); @@ -1621,7 +1621,7 @@ void GCode::_print_first_layer_bed_temperature(FILE *file, Print &print, const s // the custom start G-code emited these. std::string set_temp_gcode = m_writer.set_bed_temperature(temp, wait); if (! temp_set_by_gcode) - _write(file, set_temp_gcode); + file.write(set_temp_gcode); } // Write 1st layer extruder temperatures into the G-code. @@ -1629,7 +1629,7 @@ void GCode::_print_first_layer_bed_temperature(FILE *file, Print &print, const s // M104 - Set Extruder Temperature // M109 - Set Extruder Temperature and Wait // RepRapFirmware: G10 Sxx -void GCode::_print_first_layer_extruder_temperatures(FILE *file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait) +void GCode::_print_first_layer_extruder_temperatures(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait) { // Is the bed temperature set by the provided custom G-code? int temp_by_gcode = -1; @@ -1646,7 +1646,7 @@ void GCode::_print_first_layer_extruder_temperatures(FILE *file, Print &print, c // Set temperature of the first printing extruder only. int temp = print.config().first_layer_temperature.get_at(first_printing_extruder_id); if (temp > 0) - _write(file, m_writer.set_temperature(temp, wait, first_printing_extruder_id)); + file.write(m_writer.set_temperature(temp, wait, first_printing_extruder_id)); } else { // Set temperatures of all the printing extruders. for (unsigned int tool_id : print.extruders()) { @@ -1654,7 +1654,7 @@ void GCode::_print_first_layer_extruder_temperatures(FILE *file, Print &print, c if (print.config().ooze_prevention.value) temp += print.config().standby_temperature_delta.value; if (temp > 0) - _write(file, m_writer.set_temperature(temp, wait, tool_id)); + file.write(m_writer.set_temperature(temp, wait, tool_id)); } } } @@ -1891,7 +1891,7 @@ namespace Skirt { // and performing the extruder specific extrusions together. void GCode::process_layer( // Write into the output file. - FILE *file, + GCodeOutputStream &file, const Print &print, // Set of object & print layers of the same PrintObject and with the same print_z. const std::vector &layers, @@ -2306,7 +2306,7 @@ void GCode::process_layer( // printf("G-code after filter:\n%s\n", out.c_str()); #endif /* HAS_PRESSURE_EQUALIZER */ - _write(file, gcode); + file.write(gcode); BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z << log_memory_info(); } @@ -2642,22 +2642,22 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill return gcode; } -void GCode::_write(FILE* file, const char *what) +void GCode::GCodeOutputStream::write(const char *what) { if (what != nullptr) { const char* gcode = what; // writes string to file - fwrite(gcode, 1, ::strlen(gcode), file); + fwrite(gcode, 1, ::strlen(gcode), this->f); } } -void GCode::_writeln(FILE* file, const std::string &what) +void GCode::GCodeOutputStream::writeln(const std::string &what) { if (! what.empty()) - _write(file, (what.back() == '\n') ? what : (what + '\n')); + this->write(what.back() == '\n' ? what : what + '\n'); } -void GCode::_write_format(FILE* file, const char* format, ...) +void GCode::GCodeOutputStream::write_format(const char* format, ...) { va_list args; va_start(args, format); @@ -2681,7 +2681,7 @@ void GCode::_write_format(FILE* file, const char* format, ...) char *bufptr = buffer_dynamic ? (char*)malloc(buflen) : buffer; int res = ::vsnprintf(bufptr, buflen, format, args); if (res > 0) - _write(file, bufptr); + this->write(bufptr); if (buffer_dynamic) free(bufptr); diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index d2d241054f..06900410ae 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -184,13 +184,39 @@ public: }; private: - void _do_export(Print &print, FILE *file, ThumbnailsGeneratorCallback thumbnail_cb); + class GCodeOutputStream { + public: + GCodeOutputStream(FILE *f) : f(f) {} + ~GCodeOutputStream() { this->close(); } + + bool is_open() const { return f; } + bool is_error() const { return ::ferror(f); } + + void flush() { ::fflush(f); } + void close() { if (f) ::fclose(f); } + + // Write a string into a file. + void write(const std::string& what) { this->write(what.c_str()); } + void write(const char* what); + + // Write a string into a file. + // Add a newline, if the string does not end with a newline already. + // Used to export a custom G-code section processed by the PlaceholderParser. + void writeln(const std::string& what); + + // Formats and write into a file the given data. + void write_format(const char* format, ...); + + private: + FILE *f = nullptr; + }; + void _do_export(Print &print, GCodeOutputStream &file, ThumbnailsGeneratorCallback thumbnail_cb); static std::vector collect_layers_to_print(const PrintObject &object); static std::vector>> collect_layers_to_print(const Print &print); void process_layer( // Write into the output file. - FILE *file, + GCodeOutputStream &file, const Print &print, // Set of object & print layers of the same PrintObject and with the same print_z. const std::vector &layers, @@ -358,22 +384,10 @@ private: // Processor GCodeProcessor m_processor; - // Write a string into a file. - void _write(FILE* file, const std::string& what) { this->_write(file, what.c_str()); } - void _write(FILE* file, const char *what); - - // Write a string into a file. - // Add a newline, if the string does not end with a newline already. - // Used to export a custom G-code section processed by the PlaceholderParser. - void _writeln(FILE* file, const std::string& what); - - // Formats and write into a file the given data. - void _write_format(FILE* file, const char* format, ...); - std::string _extrude(const ExtrusionPath &path, std::string description = "", double speed = -1); - void print_machine_envelope(FILE *file, Print &print); - void _print_first_layer_bed_temperature(FILE *file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait); - void _print_first_layer_extruder_temperatures(FILE *file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait); + void print_machine_envelope(GCodeOutputStream &file, Print &print); + void _print_first_layer_bed_temperature(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait); + void _print_first_layer_extruder_temperatures(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait); // On the first printing layer. This flag triggers first layer speeds. bool on_first_layer() const { return m_layer != nullptr && m_layer->id() == 0; } // To control print speed of 1st object layer over raft interface. From eb2debc2c6f212dfe3bed71f0a072bd674a20e5b Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 7 Sep 2021 16:48:13 +0200 Subject: [PATCH 73/82] ObjectList: Fixed DnD of Volumes inside the Object --- src/slic3r/GUI/ObjectDataViewModel.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/ObjectDataViewModel.cpp b/src/slic3r/GUI/ObjectDataViewModel.cpp index 9417364ef1..88527e9fd3 100644 --- a/src/slic3r/GUI/ObjectDataViewModel.cpp +++ b/src/slic3r/GUI/ObjectDataViewModel.cpp @@ -1361,7 +1361,8 @@ wxDataViewItem ObjectDataViewModel::ReorganizeChildren( const int current_volume if (!node_parent) // happens if item.IsOk()==false return ret_item; - const size_t shift = node_parent->GetChildren().Item(0)->m_type == itSettings ? 1 : 0; + size_t shift; + for (shift = 0; shift < node_parent->GetChildCount() && node_parent->GetNthChild(shift)->GetType() != itVolume; shift ++); ObjectDataViewModelNode *deleted_node = node_parent->GetNthChild(current_volume_id+shift); node_parent->GetChildren().Remove(deleted_node); From 152e236ddad9170ac22afb7a82db455c357f66b8 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Tue, 7 Sep 2021 17:25:53 +0200 Subject: [PATCH 74/82] Trying to fix the windows build --- src/libslic3r/GCode.cpp | 4 ++++ src/libslic3r/GCode.hpp | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 54815188eb..ff00768807 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2642,6 +2642,10 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill return gcode; } +bool GCode::GCodeOutputStream::is_error() const { return ::ferror(f); } +void GCode::GCodeOutputStream::flush() { ::fflush(f); } +void GCode::GCodeOutputStream::close() { if (f) ::fclose(f); } + void GCode::GCodeOutputStream::write(const char *what) { if (what != nullptr) { diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 06900410ae..89e4570a95 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -190,10 +190,10 @@ private: ~GCodeOutputStream() { this->close(); } bool is_open() const { return f; } - bool is_error() const { return ::ferror(f); } + bool is_error() const; - void flush() { ::fflush(f); } - void close() { if (f) ::fclose(f); } + void flush(); + void close(); // Write a string into a file. void write(const std::string& what) { this->write(what.c_str()); } From 0da0a7b2a0e2a45f55ce51434761f37d34937df6 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Tue, 7 Sep 2021 17:58:06 +0200 Subject: [PATCH 75/82] Fix of recent GCode / GCodeProcessor refactoring: Don't close a FILE twice. --- src/libslic3r/GCode.cpp | 20 +++++++++++++++++--- src/libslic3r/GCode/GCodeProcessor.cpp | 7 ++++++- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index ff00768807..f2deba0467 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2642,9 +2642,23 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill return gcode; } -bool GCode::GCodeOutputStream::is_error() const { return ::ferror(f); } -void GCode::GCodeOutputStream::flush() { ::fflush(f); } -void GCode::GCodeOutputStream::close() { if (f) ::fclose(f); } +bool GCode::GCodeOutputStream::is_error() const +{ + return ::ferror(this->f); +} + +void GCode::GCodeOutputStream::flush() +{ + ::fflush(this->f); +} + +void GCode::GCodeOutputStream::close() +{ + if (this->f) { + ::fclose(this->f); + this->f = nullptr; + } +} void GCode::GCodeOutputStream::write(const char *what) { diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index ec586dbef7..60af399c06 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -350,7 +350,12 @@ void GCodeProcessor::TimeProcessor::reset() struct FilePtr { FilePtr(FILE *f) : f(f) {} ~FilePtr() { this->close(); } - void close() { if (f) ::fclose(f); } + void close() { + if (this->f) { + ::fclose(this->f); + this->f = nullptr; + } + } FILE* f = nullptr; }; From 9abebe5fbe6950d809b51926af8772317fe2657f Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 8 Sep 2021 13:04:43 +0200 Subject: [PATCH 76/82] Techs ENABLE_SEAMS_USING_MODELS and ENABLE_SEAMS_USING_BATCHED_MODELS - Fixed seams (and other options) zs to match toolpaths zs in preview --- resources/shaders/gouraud_light_instanced.vs | 4 +++- src/slic3r/GUI/GCodeViewer.cpp | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/resources/shaders/gouraud_light_instanced.vs b/resources/shaders/gouraud_light_instanced.vs index a8931361d0..997b6a2bf9 100644 --- a/resources/shaders/gouraud_light_instanced.vs +++ b/resources/shaders/gouraud_light_instanced.vs @@ -34,7 +34,9 @@ void main() float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0); intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; - vec4 world_position = vec4(v_position * vec3(vec2(i_scales.x), i_scales.y) + i_offset, 1.0); + float width = 1.5 * i_scales.x; + float height = 1.5 * i_scales.y; + vec4 world_position = vec4(v_position * vec3(vec2(width), height) + i_offset - vec3(0.0, 0.0, 0.5 * i_scales.y), 1.0); vec3 eye_position = (gl_ModelViewMatrix * world_position).xyz; intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(eye_position), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS); diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 7e8e587a6e..ac97b8dbc5 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -1414,9 +1414,9 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) instances.push_back(curr.position.y()); instances.push_back(curr.position.z()); // append width - instances.push_back(1.5f * curr.width); + instances.push_back(curr.width); // append height - instances.push_back(1.5f * curr.height); + instances.push_back(curr.height); // append id instances_ids.push_back(move_id); @@ -1428,7 +1428,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) const double width = static_cast(1.5f * curr.width); const double height = static_cast(1.5f * curr.height); - const Transform3d trafo = Geometry::assemble_transform(curr.position.cast(), Vec3d::Zero(), { width, width, height }); + const Transform3d trafo = Geometry::assemble_transform((curr.position - 0.5f * curr.height * Vec3f::UnitZ()).cast(), Vec3d::Zero(), { width, width, height }); const Eigen::Matrix normal_matrix = trafo.matrix().template block<3, 3>(0, 0).inverse().transpose(); for (const auto& entity : data.entities) { From 6f678c09d1358fdbfbe50452604797d8f03c3056 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 8 Sep 2021 14:30:40 +0200 Subject: [PATCH 77/82] Tech ENABLE_FIX_PREVIEW_OPTIONS_Z - Enable fixing the z position of seams (and other options) in preview --- src/libslic3r/GCode/GCodeProcessor.cpp | 23 ++++++++++++++ src/libslic3r/GCode/GCodeProcessor.hpp | 42 ++++++++++++++++++++++++++ src/libslic3r/Technologies.hpp | 9 ++++++ src/slic3r/GUI/GCodeViewer.cpp | 4 +++ 4 files changed, 78 insertions(+) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 60af399c06..a217fa1020 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -828,6 +828,9 @@ bool GCodeProcessor::contains_reserved_tags(const std::string& gcode, unsigned i } GCodeProcessor::GCodeProcessor() +#if ENABLE_FIX_PREVIEW_OPTIONS_Z +: m_options_z_corrector(m_result) +#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z { reset(); m_time_processor.machines[static_cast(PrintEstimatedStatistics::ETimeMode::Normal)].line_m73_main_mask = "M73 P%s R%s\n"; @@ -1202,6 +1205,10 @@ void GCodeProcessor::reset() m_last_default_color_id = 0; #endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER +#if ENABLE_FIX_PREVIEW_OPTIONS_Z + m_options_z_corrector.reset(); +#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z + #if ENABLE_GCODE_VIEWER_DATA_CHECKING m_mm3_per_mm_compare.reset(); m_height_compare.reset(); @@ -1781,6 +1788,9 @@ void GCodeProcessor::process_tags(const std::string_view comment) #if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER CustomGCode::Item item = { static_cast(m_end_position[2]), CustomGCode::ColorChange, extruder_id + 1, color, "" }; m_result.custom_gcode_per_print_z.emplace_back(item); +#if ENABLE_FIX_PREVIEW_OPTIONS_Z + m_options_z_corrector.set(); +#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z process_custom_gcode_time(CustomGCode::ColorChange); process_filaments(CustomGCode::ColorChange); #endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER @@ -1800,6 +1810,9 @@ void GCodeProcessor::process_tags(const std::string_view comment) #if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER CustomGCode::Item item = { static_cast(m_end_position[2]), CustomGCode::PausePrint, m_extruder_id + 1, "", "" }; m_result.custom_gcode_per_print_z.emplace_back(item); +#if ENABLE_FIX_PREVIEW_OPTIONS_Z + m_options_z_corrector.set(); +#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z #endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER process_custom_gcode_time(CustomGCode::PausePrint); return; @@ -1811,6 +1824,9 @@ void GCodeProcessor::process_tags(const std::string_view comment) #if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER CustomGCode::Item item = { static_cast(m_end_position[2]), CustomGCode::Custom, m_extruder_id + 1, "", "" }; m_result.custom_gcode_per_print_z.emplace_back(item); +#if ENABLE_FIX_PREVIEW_OPTIONS_Z + m_options_z_corrector.set(); +#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z #endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER return; } @@ -2391,7 +2407,9 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) else { if (m_end_position[Z] > m_extruded_last_z + EPSILON) { m_height = m_end_position[Z] - m_extruded_last_z; +#if !ENABLE_FIX_PREVIEW_OPTIONS_Z m_extruded_last_z = m_end_position[Z]; +#endif // !ENABLE_FIX_PREVIEW_OPTIONS_Z } } @@ -2401,6 +2419,11 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) if (m_end_position[Z] == 0.0f) m_end_position[Z] = m_height; +#if ENABLE_FIX_PREVIEW_OPTIONS_Z + m_extruded_last_z = m_end_position[Z]; + m_options_z_corrector.update(m_height); +#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z + #if ENABLE_GCODE_VIEWER_DATA_CHECKING m_height_compare.update(m_height, m_extrusion_role); #endif // ENABLE_GCODE_VIEWER_DATA_CHECKING diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index bb93108881..a1730daf24 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -390,6 +390,45 @@ namespace Slic3r { bool has_first_vertex() const { return m_first_vertex.has_value(); } }; +#if ENABLE_FIX_PREVIEW_OPTIONS_Z + // Helper class used to fix the z for color change, pause print and + // custom gcode markes + class OptionsZCorrector + { + Result& m_result; + std::optional m_move_id; + std::optional m_custom_gcode_per_print_z_id; + + public: + explicit OptionsZCorrector(Result& result) : m_result(result) { + } + + void set() { + m_move_id = m_result.moves.size() - 1; + m_custom_gcode_per_print_z_id = m_result.custom_gcode_per_print_z.size() - 1; + } + + void update(float height) { + if (!m_move_id.has_value() || !m_custom_gcode_per_print_z_id.has_value()) + return; + + const Vec3f position = m_result.moves.back().position; + + MoveVertex& move = m_result.moves.emplace_back(m_result.moves[m_move_id.value()]); + move.position = position; + move.height = height; + m_result.moves.erase(m_result.moves.begin() + m_move_id.value()); + m_result.custom_gcode_per_print_z[m_custom_gcode_per_print_z_id.value()].print_z = position.z(); + reset(); + } + + void reset() { + m_move_id.reset(); + m_custom_gcode_per_print_z_id.reset(); + } + }; +#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z + #if ENABLE_GCODE_VIEWER_DATA_CHECKING struct DataChecker { @@ -494,6 +533,9 @@ namespace Slic3r { CpColor m_cp_color; bool m_use_volumetric_e; SeamsDetector m_seams_detector; +#if ENABLE_FIX_PREVIEW_OPTIONS_Z + OptionsZCorrector m_options_z_corrector; +#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z #if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER size_t m_last_default_color_id; #endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 6132430f1a..adcde55723 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -57,4 +57,13 @@ #define ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED (1 && ENABLE_2_4_0_ALPHA0) +//==================== +// 2.4.0.alpha2 techs +//==================== +#define ENABLE_2_4_0_ALPHA2 1 + +// Enable fixing the z position of color change, pause print and custom gcode markers in preview +#define ENABLE_FIX_PREVIEW_OPTIONS_Z (1 && ENABLE_SEAMS_USING_MODELS && ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER && ENABLE_2_4_0_ALPHA2) + + #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 946cbb2759..9b4e2ef8db 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -2370,7 +2370,11 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool if (m_sequential_view.current.first <= buffer.model.instances.s_ids.back() && buffer.model.instances.s_ids.front() <= m_sequential_view.current.last) { for (size_t id : buffer.model.instances.s_ids) { if (has_second_range) { +#if ENABLE_FIX_PREVIEW_OPTIONS_Z + if (id < m_sequential_view.endpoints.first) { +#else if (id <= m_sequential_view.endpoints.first) { +#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z ++buffer.model.instances.render_ranges.ranges.front().offset; if (id <= m_sequential_view.current.first) ++buffer.model.instances.render_ranges.ranges.back().offset; From 88d608351d0b5f3d4c678ffe673cb818a1ad6dd5 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 8 Sep 2021 14:34:31 +0200 Subject: [PATCH 78/82] Fix after merge with master --- src/libslic3r/Technologies.hpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 1183b51df4..ac92ecd108 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -64,13 +64,6 @@ // Enable rendering seams (and other options) in preview using batched models on systems not supporting OpenGL 3.3 #define ENABLE_SEAMS_USING_BATCHED_MODELS (1 && ENABLE_SEAMS_USING_MODELS && ENABLE_2_4_0_ALPHA2) - - -//==================== -// 2.4.0.alpha2 techs -//==================== -#define ENABLE_2_4_0_ALPHA2 1 - // Enable fixing the z position of color change, pause print and custom gcode markers in preview #define ENABLE_FIX_PREVIEW_OPTIONS_Z (1 && ENABLE_SEAMS_USING_MODELS && ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER && ENABLE_2_4_0_ALPHA2) From beee18f22991e369b1722a43bbcb692fa0d68af0 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 8 Sep 2021 15:06:05 +0200 Subject: [PATCH 79/82] Follow-up to b5a007a683124ec3b01b61e892ed8eb39c034248 WIP to G-code export parallelization through pipelining: GCodeProcessor is called during the G-code export, the G-code is no more reopened and re-read, but it is pipelined from the G-code generator. --- src/libslic3r/GCode.cpp | 7 +++- src/libslic3r/GCode.hpp | 3 +- src/libslic3r/GCode/GCodeProcessor.cpp | 54 ++++++++++++++++++-------- src/libslic3r/GCode/GCodeProcessor.hpp | 13 ++++--- src/libslic3r/GCodeReader.hpp | 3 +- src/slic3r/GUI/GCodeViewer.cpp | 2 +- src/slic3r/GUI/Plater.cpp | 3 +- 7 files changed, 57 insertions(+), 28 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index f2deba0467..efea240e55 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -744,7 +744,8 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessor::Result* re std::string path_tmp(path); path_tmp += ".tmp"; - GCodeOutputStream file(boost::nowide::fopen(path_tmp.c_str(), "wb")); + m_processor.initialize(path_tmp); + GCodeOutputStream file(boost::nowide::fopen(path_tmp.c_str(), "wb"), m_processor); if (! file.is_open()) throw Slic3r::RuntimeError(std::string("G-code export to ") + path + " failed.\nCannot open the file for writing.\n"); @@ -782,7 +783,7 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessor::Result* re } BOOST_LOG_TRIVIAL(debug) << "Start processing gcode, " << log_memory_info(); - m_processor.process_file(path_tmp, true, [print]() { print->throw_if_canceled(); }); + m_processor.finalize(); // DoExport::update_print_estimated_times_stats(m_processor, print->m_print_statistics); DoExport::update_print_estimated_stats(m_processor, m_writer.extruders(), print->m_print_statistics); if (result != nullptr) { @@ -2666,6 +2667,8 @@ void GCode::GCodeOutputStream::write(const char *what) const char* gcode = what; // writes string to file fwrite(gcode, 1, ::strlen(gcode), this->f); + //FIXME don't allocate a string, maybe process a batch of lines? + m_processor.process_buffer(std::string(gcode)); } } diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 89e4570a95..1dbc5b70a0 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -186,7 +186,7 @@ public: private: class GCodeOutputStream { public: - GCodeOutputStream(FILE *f) : f(f) {} + GCodeOutputStream(FILE *f, GCodeProcessor &processor) : f(f), m_processor(processor) {} ~GCodeOutputStream() { this->close(); } bool is_open() const { return f; } @@ -209,6 +209,7 @@ private: private: FILE *f = nullptr; + GCodeProcessor &m_processor; }; void _do_export(Print &print, GCodeOutputStream &file, ThumbnailsGeneratorCallback thumbnail_cb); diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 60af399c06..1891c90b4a 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -1189,7 +1189,6 @@ void GCodeProcessor::reset() m_cp_color.reset(); m_producer = EProducer::Unknown; - m_producers_enabled = false; m_time_processor.reset(); m_used_filaments.reset(); @@ -1209,7 +1208,7 @@ void GCodeProcessor::reset() #endif // ENABLE_GCODE_VIEWER_DATA_CHECKING } -void GCodeProcessor::process_file(const std::string& filename, bool apply_postprocess, std::function cancel_callback) +void GCodeProcessor::process_file(const std::string& filename, std::function cancel_callback) { CNumericLocalesSetter locales_setter; @@ -1219,7 +1218,7 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr // pre-processing // parse the gcode file to detect its producer - if (m_producers_enabled) { + { m_parser.parse_file(filename, [this](GCodeReader& reader, const GCodeReader::GCodeLine& line) { const std::string_view cmd = line.cmd(); if (cmd.empty()) { @@ -1228,6 +1227,7 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr m_parser.quit_parsing(); } }); + m_parser.reset(); // if the gcode was produced by PrusaSlicer, // extract the config from it @@ -1257,9 +1257,37 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr if (cancel_callback) cancel_callback(); } - this->process_gcode_line(line); + this->process_gcode_line(line, true); }); + this->finalize(); + + // post-process to add M73 lines into the gcode +#if ENABLE_GCODE_VIEWER_STATISTICS + m_result.time = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time).count(); +#endif // ENABLE_GCODE_VIEWER_STATISTICS +} + +void GCodeProcessor::initialize(const std::string& filename) +{ + assert(is_decimal_separator_point()); + // process gcode + m_result.filename = filename; + m_result.id = ++s_result_id; + // 1st move must be a dummy move + m_result.moves.emplace_back(MoveVertex()); +} + +void GCodeProcessor::process_buffer(const std::string &buffer) +{ + //FIXME maybe cache GCodeLine gline to be over multiple parse_buffer() invocations. + m_parser.parse_buffer(buffer, [this](GCodeReader&, const GCodeReader::GCodeLine& line) { + this->process_gcode_line(line, false); + }); +} + +void GCodeProcessor::finalize() +{ // update width/height of wipe moves for (MoveVertex& move : m_result.moves) { if (move.type == EMoveType::Wipe) { @@ -1281,10 +1309,6 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr update_estimated_times_stats(); - // post-process to add M73 lines into the gcode - if (apply_postprocess) - m_time_processor.post_process(filename, m_result.moves, m_result.lines_ends); - #if ENABLE_GCODE_VIEWER_DATA_CHECKING std::cout << "\n"; m_mm3_per_mm_compare.output(); @@ -1292,9 +1316,7 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr m_width_compare.output(); #endif // ENABLE_GCODE_VIEWER_DATA_CHECKING -#if ENABLE_GCODE_VIEWER_STATISTICS - m_result.time = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time).count(); -#endif // ENABLE_GCODE_VIEWER_STATISTICS + m_time_processor.post_process(m_result.filename, m_result.moves, m_result.lines_ends); } float GCodeProcessor::get_time(PrintEstimatedStatistics::ETimeMode mode) const @@ -1432,7 +1454,7 @@ void GCodeProcessor::apply_config_simplify3d(const std::string& filename) } } -void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line) +void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line, bool producers_enabled) { /* std::cout << line.raw() << std::endl; */ @@ -1615,7 +1637,7 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line) if (comment.length() > 2 && comment.front() == ';') // Process tags embedded into comments. Tag comments always start at the start of a line // with a comment and continue with a tag without any whitespace separator. - process_tags(comment.substr(1)); + process_tags(comment.substr(1), producers_enabled); } } @@ -1664,10 +1686,10 @@ template } } -void GCodeProcessor::process_tags(const std::string_view comment) +void GCodeProcessor::process_tags(const std::string_view comment, bool producers_enabled) { // producers tags - if (m_producers_enabled && process_producers_tags(comment)) + if (producers_enabled && process_producers_tags(comment)) return; // extrusion role tag @@ -1691,7 +1713,7 @@ void GCodeProcessor::process_tags(const std::string_view comment) return; } - if (!m_producers_enabled || m_producer == EProducer::PrusaSlicer) { + if (!producers_enabled || m_producer == EProducer::PrusaSlicer) { // height tag if (boost::starts_with(comment, reserved_tag(ETags::Height))) { if (!parse_number(comment.substr(reserved_tag(ETags::Height).size()), m_forced_height)) diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index bb93108881..1665fb9f2d 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -513,7 +513,6 @@ namespace Slic3r { static const std::vector> Producers; EProducer m_producer; - bool m_producers_enabled; TimeProcessor m_time_processor; UsedFilaments m_used_filaments; @@ -536,7 +535,6 @@ namespace Slic3r { return m_time_processor.machines[static_cast(PrintEstimatedStatistics::ETimeMode::Stealth)].enabled; } void enable_machine_envelope_processing(bool enabled) { m_time_processor.machine_envelope_processing_enabled = enabled; } - void enable_producers(bool enabled) { m_producers_enabled = enabled; } void reset(); const Result& get_result() const { return m_result; } @@ -544,7 +542,12 @@ namespace Slic3r { // Process the gcode contained in the file with the given filename // throws CanceledException through print->throw_if_canceled() (sent by the caller as callback). - void process_file(const std::string& filename, bool apply_postprocess, std::function cancel_callback = nullptr); + void process_file(const std::string& filename, std::function cancel_callback = nullptr); + + // Streaming interface, for processing G-codes just generated by PrusaSlicer in a pipelined fashion. + void initialize(const std::string& filename); + void process_buffer(const std::string& buffer); + void finalize(); float get_time(PrintEstimatedStatistics::ETimeMode mode) const; std::string get_time_dhm(PrintEstimatedStatistics::ETimeMode mode) const; @@ -557,10 +560,10 @@ namespace Slic3r { private: void apply_config(const DynamicPrintConfig& config); void apply_config_simplify3d(const std::string& filename); - void process_gcode_line(const GCodeReader::GCodeLine& line); + void process_gcode_line(const GCodeReader::GCodeLine& line, bool producers_enabled); // Process tags embedded into comments - void process_tags(const std::string_view comment); + void process_tags(const std::string_view comment, bool producers_enabled); bool process_producers_tags(const std::string_view comment); bool process_prusaslicer_tags(const std::string_view comment); bool process_cura_tags(const std::string_view comment); diff --git a/src/libslic3r/GCodeReader.hpp b/src/libslic3r/GCodeReader.hpp index 8c820b95df..15376c0fc6 100644 --- a/src/libslic3r/GCodeReader.hpp +++ b/src/libslic3r/GCodeReader.hpp @@ -77,7 +77,8 @@ public: typedef std::function callback_t; - GCodeReader() : m_verbose(false), m_extrusion_axis('E') { memset(m_position, 0, sizeof(m_position)); } + GCodeReader() : m_verbose(false), m_extrusion_axis('E') { this->reset(); } + void reset() { memset(m_position, 0, sizeof(m_position)); } void apply_config(const GCodeConfig &config); void apply_config(const DynamicPrintConfig &config); diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index ac97b8dbc5..e61d1356a1 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -1190,7 +1190,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) }; auto add_indices_as_line = [](const GCodeProcessor::MoveVertex& prev, const GCodeProcessor::MoveVertex& curr, TBuffer& buffer, unsigned int ibuffer_id, IndexBuffer& indices, size_t move_id) { - if (prev.type != curr.type || !buffer.paths.back().matches(curr)) { + if (buffer.paths.empty() || prev.type != curr.type || !buffer.paths.back().matches(curr)) { // add starting index indices.push_back(static_cast(indices.size())); buffer.add_path(curr, ibuffer_id, indices.size() - 1, move_id - 1); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 2c77dcb7ac..76612a718c 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -4871,10 +4871,9 @@ void Plater::load_gcode(const wxString& filename) // process gcode GCodeProcessor processor; - processor.enable_producers(true); try { - processor.process_file(filename.ToUTF8().data(), false); + processor.process_file(filename.ToUTF8().data()); } catch (const std::exception& ex) { From a115da63347d52704fdea659e7b3f1f2438dca38 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 8 Sep 2021 15:30:51 +0200 Subject: [PATCH 80/82] Fix for #6921 - Error while disabling filament overrides in Dutch language --- src/slic3r/GUI/Field.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 1aaac54690..06cfd0a1c1 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -230,18 +230,21 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true } double val; + bool is_na_value = m_opt.nullable && str == na_value(); + const char dec_sep = is_decimal_separator_point() ? '.' : ','; const char dec_sep_alt = dec_sep == '.' ? ',' : '.'; - // Replace the first incorrect separator in decimal number. - if (str.Replace(dec_sep_alt, dec_sep, false) != 0) + // Replace the first incorrect separator in decimal number, + // if this value doesn't "N/A" value in some language + // see https://github.com/prusa3d/PrusaSlicer/issues/6921 + if (!is_na_value && str.Replace(dec_sep_alt, dec_sep, false) != 0) set_value(str, false); - if (str == dec_sep) val = 0.0; else { - if (m_opt.nullable && str == na_value()) + if (is_na_value) val = ConfigOptionFloatsNullable::nil_value(); else if (!str.ToDouble(&val)) { From d3382b666fed0fee2067a8c30314e664fce8a8e7 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 8 Sep 2021 15:47:27 +0200 Subject: [PATCH 81/82] Fixed build on MAC --- src/libslic3r/GCode/GCodeProcessor.hpp | 6 +++--- src/slic3r/GUI/GCodeViewer.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index a1730daf24..ac0fb0d870 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -414,11 +414,11 @@ namespace Slic3r { const Vec3f position = m_result.moves.back().position; - MoveVertex& move = m_result.moves.emplace_back(m_result.moves[m_move_id.value()]); + MoveVertex& move = m_result.moves.emplace_back(m_result.moves[*m_move_id]); move.position = position; move.height = height; - m_result.moves.erase(m_result.moves.begin() + m_move_id.value()); - m_result.custom_gcode_per_print_z[m_custom_gcode_per_print_z_id.value()].print_z = position.z(); + m_result.moves.erase(m_result.moves.begin() + *m_move_id); + m_result.custom_gcode_per_print_z[*m_custom_gcode_per_print_z_id].print_z = position.z(); reset(); } diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 7e83831205..0f019b2bf8 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -3045,7 +3045,7 @@ void GCodeViewer::render_legend(float& legend_height) bool imperial_units = wxGetApp().app_config->get("use_inches") == "1"; - auto append_item = [this, icon_size, percent_bar_size, &imgui, imperial_units](EItemType type, const Color& color, const std::string& label, + auto append_item = [icon_size, percent_bar_size, &imgui, imperial_units](EItemType type, const Color& color, const std::string& label, bool visible = true, const std::string& time = "", float percent = 0.0f, float max_percent = 0.0f, const std::array& offsets = { 0.0f, 0.0f, 0.0f, 0.0f }, double used_filament_m = 0.0, double used_filament_g = 0.0, std::function callback = nullptr) { From fe8e2ae0d1889127e5df1b504cafc1c259fbf042 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 9 Sep 2021 09:35:58 +0200 Subject: [PATCH 82/82] ENABLE_GCODE_VIEWER_STATISTICS - Fixed calculation of time required by GCodeProcessor --- src/libslic3r/GCode/GCodeProcessor.cpp | 15 +++++++++------ src/libslic3r/GCode/GCodeProcessor.hpp | 3 +++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 1891c90b4a..8ebd82d663 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -1213,7 +1213,7 @@ void GCodeProcessor::process_file(const std::string& filename, std::functionfinalize(); - - // post-process to add M73 lines into the gcode -#if ENABLE_GCODE_VIEWER_STATISTICS - m_result.time = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time).count(); -#endif // ENABLE_GCODE_VIEWER_STATISTICS } void GCodeProcessor::initialize(const std::string& filename) { assert(is_decimal_separator_point()); + +#if ENABLE_GCODE_VIEWER_STATISTICS + m_start_time = std::chrono::high_resolution_clock::now(); +#endif // ENABLE_GCODE_VIEWER_STATISTICS + // process gcode m_result.filename = filename; m_result.id = ++s_result_id; @@ -1317,6 +1317,9 @@ void GCodeProcessor::finalize() #endif // ENABLE_GCODE_VIEWER_DATA_CHECKING m_time_processor.post_process(m_result.filename, m_result.moves, m_result.lines_ends); +#if ENABLE_GCODE_VIEWER_STATISTICS + m_result.time = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - m_start_time).count(); +#endif // ENABLE_GCODE_VIEWER_STATISTICS } float GCodeProcessor::get_time(PrintEstimatedStatistics::ETimeMode mode) const diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 1665fb9f2d..ea594b3fce 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -497,6 +497,9 @@ namespace Slic3r { #if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER size_t m_last_default_color_id; #endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER +#if ENABLE_GCODE_VIEWER_STATISTICS + std::chrono::time_point m_start_time; +#endif // ENABLE_GCODE_VIEWER_STATISTICS enum class EProducer {