From cd4155a890d6a69e749e0079fb0d86c4d5a7a397 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Fri, 3 Sep 2021 10:19:06 +0200 Subject: [PATCH 01/32] 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 33ccdc4ae..fe5eeb67c 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 02/32] 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 526b7b874..808bdd8a1 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 03/32] 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 808bdd8a1..d9a4f2670 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 eaf75ba5b..5b7218c87 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 04/32] 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 8b033ce73..1c6e00c07 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 8c90d20d3..c7faab3bf 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 cb60c0e25..8e30aa6b8 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 6d9a03977..080991859 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 05/32] 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 cc089e26e..64479a39e 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 1c6e00c07..05f6adb5e 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 641258ca4..3dcb9e2b1 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 99c010bf1..1ebba4d11 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 3e5c12eec..b8c7d9f92 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 05e0be141..f405f457d 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 a30ac377e..608e7bd1f 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 9a056adcb..e7b6a0ad6 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 36759d2ec..54fcfc2c7 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 894d844d8..b97507166 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 5b84bbaba..a2ee56d9a 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 f70e3f93e..9f49f9734 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 c7faab3bf..11446d6d7 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 080991859..dfe6de746 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 06/32] 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 096836f23..c99d9090c 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 dfe6de746..93eba3042 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 188c9e914..ed02574df 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 4236ee450..af8734184 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 2e250c1463c5d8e8bc94d0769e3e82d648e99e3b Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Fri, 3 Sep 2021 16:16:43 +0200 Subject: [PATCH 07/32] 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 3fc624264..656a67406 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 08/32] 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 a6be64299..68c40fc20 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 51dcf9d36..758fc38cd 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 0a7b8dcb0..5203ec5ef 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 10bbb263f..7846ea5f4 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 09/32] 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 7dc3c9a8a..54e6802e6 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 6b58608e6..88c9df284 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 10/32] 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 24549fd89..3aecdfd1f 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 11/32] 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 0d71a19f5..73ee0d164 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 12/32] 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 317785473..000000000 --- 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 1ea3e157e..000000000 --- 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 c37f43d69..000000000 --- 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 ad41c3f01c94f888e500462e4127574f1fc60766 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 6 Sep 2021 13:15:36 +0200 Subject: [PATCH 13/32] 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 656a67406..8c2ef573f 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 14/32] #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 73ee0d164..c4f262675 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 6132430f1..405119fc0 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 15/32] 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 zcma)AWl-Erlm9O)t`ET_xVyVM1h)VoKyW9xEEWQU;I3f_ZUGY9-3e~Nb%6(m;IMnV z_u=m2U3K+L*GyOSuY0^D907T;A49x5)4G5)jTI$#tCc@`RN|JHmf~ob+ zy3?PR58yU+E~^|V&h@g1Bgbps9GLibo{Ah;r3hv5d&)LbHW8*h%(RY`Co!A__1XpC zaF)BN2j%ZGBp636{B><9%}yO-tM{w`~K!i3Wa| zg@R=thcOmE++p;KJLl4D6ZACzMx=Ro=f5VilK8%uD{`<@#KQYmzM$>X- z9H%imm;V@+O7$C+=Viz}n{zf14l+tczR$(>8s_nSx_GV^%G^rjmY$T_CF@#v3RABNQ379 zF|{Zx#Uwwl|9((x|NU-$^LV3|^&Sp1={v%Qj}E4J8bG)kDs>$JZlyoV(JY=+mG|9{(de*Vl(_(74fDe%5*Rnc3~F^V?N`2%)U=i=<}`4&tSc-q7BqZ7q8LwkABG9?*{)p~GgITps2g<{zm&p~{YP{$~PC zr!|E?F<}lFI;&7QlO;|G7V8Mf-o9RIb*%%U$j=y-+yOqqm9OGR%-T?gYTc|WgQ`MF z$~})=tLhfEr1h23QJEnnJ7@gJnyx#a=~bo4=ptO&0zRKym-qy$OD@-h4SHTUOQ3v! zm_r1l2&H@7!^t*cI(3dO<~$C6jp1&`I((~d$o}_h-^lLH2h18iHe&3(?tGS`)`K?6 z=@Q(A4EsHxHjq!G*G(1vOtRu%Y~u+<6?tM7zcpzT#oMexo_e$&6AHE4={N(bq)Pm5 zbp4q7KWre0%!l{&7-^ADR#G2boBFvjt^-Suj`xVi=YXIqNe5C(53C&0TU->_mPD)G~06?s#svxWH z2RbpsNYpn-@5nO9GB&1Y_(`lz|BGFOJOUeih69t+M}R+`BaA9sLmYK^Mr;dvt6!yA zp?+=JGGTglRxG?McDe5J(rm$}DSCmgW1+v6`u?pY9yZjMb!l11y&5sMHLxMR=R+7? zn)i<(uDH+Ed{2XJ*L*iF6<0Uu{{M8Yq13&T+S_q8As!|b^gx)JmWG0fiTNZ2ourOa z3KE%&QK0h=?%L=B0y;Fmi{emS2!U63c-NPg$>l}q{QdncbEA%qj^tMwU7UgrzDLP9 ztT+ArwTE;Le>@}6%H**GlR_l#M9DA6YZh1VEDSc=NsIC59{#!d=L)~0`LrkK^@R~f zX;u~+IB}UNzrhUu+!dSmE2)yRtaI$pj<-l~gdGA8=@&O4=806m-vju?&XDj{t4$9Z zk7NdySvCPS>OOL2mc^YQ3oY4kWX(TcJTtEn|^6AMO{_jrNqot<+* zg77BoFn(=<(n>eI9zzw0*D(X@@+lWr+uPe4?Ctxx$_Z5BLO_KJ5kq$JNhAk8jn9_* z-N4RJf>F+Zv7P{c{mr2+yr7-HF`Gl`=$m$=>`af!f+UQhT9kbi@~ z1j8x&$73@ z9p~BMbXe88ytIkW$uc8#$kWf`)fT;YN>Mrzu6Ouzbh6TIk{V@3vKf`n(psAXgmVJr zWo3z$eUT#?!fOn#m^D*>S`A^=n@8Dk!c*{GS7i#hET{j@5%zR1r{5yOPia71sdZQdkYz)mlOPICTRFAxBrwf(sl4G|fL#yvPgC1=Y$oQGqnRSGa@;f{)wg*CbLI?1$xsyN`$*L5> zuBnUf12tX&3mz3-eCuU0VWC~`U$Jb`q%dhD2cEVlGil{H>l2fe&Q49$lE3dQjwVU1 zml68nciM%3uluh1@6Q7D5>{-S0r(vR{>MLub_YnzQ(wHae={^yX91qk#w?S}WST9Z zp%ihKSr2}6`O^{DB*UrR75t3-yQZzbJLyg3af+tbKc;z=-4oW3w!0~h_a08{K@c#31bW~XR?;my+RuE=wu3s zd?a=Y*F}MDu^|z_bgFo3U&NQj)E@d>*B_Q;x4RWZojzNt<&-X#W#LPMb1YbE{I=Dr zy#4QtdPxeHzOgQCyONV%%dnNx;i+U7ET+iw08W`As z3C(6`w1z2Gd5n;|x!(iPjjM=}>a|x|65sv*2B`gJ&hUas-|wc(+wU2y0JDFs`0;)9lHgr>R;7|K` zffLTaiY)K8Ld`ufFI4J_L~~IZd&w_A=J_Ep>oV}qr%_rHpF(?y>BN6A!q#OP@2#Z_ zAKo%H`}0iv!O_PY{nC4@ftP<7sHV>-`83L2W8c^0^W2gwq$(&^BPGJDZG87d7fpWQ!lrw7% zOESIWZCUbQ(mlT49-2uu3mIaSL0C?mn*1m-`|5-8y=+MNHVUeJ(RoREEnCV}scB8? z0qXf5v9(qXz%KfaR9}-facXSFsck^DYRI)?zVIjiA&Ow1if7!_D6{lUjnc6-gaJ`# zEMw)Pb6eNgec)N=W3|wqf=A|)j-1u`!UnB|4Pw`ZI2Mty)P}kW;H|ER=4#Q#YBW7W z3@Fc}UPnlKxDGgDoCt>ChH5HTD;t1@mzswoYBh3%yfe#l)J<&LbF%MOicjs-89eMu z=cEIn3h`&c^iF-V`b5BN4p0#i0C%n};77_Br{?{j5EUGJ2V@~K2)f)&Bv1wj#7)_+ zCplA=2Cm489roobkSxT0FSrcNC0nJlur z-cU82$wr>-8KXlU!ssS3hkS1d;=UECV@Xo2IT&ADYn#)yhDYFzBg8zl^0iHb5v2ky z0oO+{xDuYZ!0}p}@Xi3a;a2%5yQ{da`)CDCss(P*(*qXJW~Ow8v#9EGsWlw_ zSFj5?s>7e4Mw~MPenNIFXi7!Eca~5H4y6yty+nzM^k+0w5oNq8zwr*&a=L2Mn%dz` zoNC-qJv#ldCT%}!W&q-8pcuwTiPf}6=?uCoYbFiFU2_yv&#Y!??>u`q=0@W>+DwbyR@{l^uOSx`5o}Y1hV)chLgd*% zq>*PxkiJ&kjlnkwV|3so^x$X5HX(br4w8(7=z^=Q$^gVg#i*wv=T#6TwTS1t?H{8n z_q(Ystr-R{fV60$`+e+6PC7Ea-sg^6wk~TaL4CT5u?Sq8RXQD4S}K4{O%|WmX&_`& zQdhL14^nLbRLq{4?qU0C;nYd|*GtEgb@f9Imzb z4(9dLqe87R6J{*)D>>hOIx+lqv4vp(s(pj3jekJc`gq#L|1Uv_z@10lNMTH2m@*e3 z>k;RAuP*Yd-%_mqtyin^j&f8ZzorZR;F|MEe|&N1s^#6-6z$sa&(0?%rpSN?+_a}p z7S*g|mz@;=X>z$5-CsY5aI)?su+%%nxEIzPYD9WUj*5e*)dw3oQur$QC@JMVJK9&b^Rn?<_YuKK_VyY!z({2xcV!M~Z*One z7j)KB4y}Or^ERxd5qf17jlf$oH}!NA%^nPI|tLT0bZow7`uV5M9Yz50=O&8 zp82qqv#mD1Cl~+w3pS}GbesTtYvjdVBjfhp|E2Y;VPak_o`06znl79rv z6Nv}3rc>%XT0KXpPA^Fl*;PT>-#Na3*FZjavt7>{+?^zA3O!?BPSCWju;QR|5%ess zomp^m@%mn+yabq)4WcyOw>F#|WNU3t-zKEpk|1{d3EWAyM|UlxfPMaDu~MC!z9@{` zKOA!m(j0hiNl3qmXsJcU^2|OAxeEOII9(D%xnkSJ(ygIj^ zPqSm;e{>5ssTf@NGU=pxCK_4urOt!Rri2bK>Am~FTw2GbZXy(#a(}%PY_JkGoBk35 z?YID>$}WdNf=00b}=*)-t5Brx8ksgYYq@Qsww#Yv+Yv!VV|Is4Bkb%{*)=tskuJkWr zE7(CiM9p8m#5Gy)Ih}ciElzliwo@^LJBT+8XJdg^QcDu~@^kw%!Y<&Yj^cGLlgSy? zvd&`v^5-JpNE>90VT}Lji5JT{gjRoFf5$x!(YowH6k(TDr$b`UAX8w0B;ks;xVfwA_J@G+x}K{o{SP zkbePfG@*gYj&CqSF+Z`|#;C^}ByjMdJEbn)=#P*d5kO9&<9y&3`$}LOI~S~LY{JkP z&A(f@9?npIN?mL{BzEDU&pAmxCT4bDZ;N4eT4E_k@Nk+?e0!&=YpiR%f@@dwih4mR z9y!pCj3N}mO#%91CA}d(Z@*uKUfhF(5lhKg$_`D&Dr8dMDls7VEY$7uVFqTvD6RZ; z3x1v-LvlKAMDAwH0(Zc&alfWv#a-?iMUxB-XQ48spGD~omwdk6wi@Q0(^da#2E-_! z-kfma@FV0VVylwU@fOvlnVlHjPf62_E&EVX1bg?$sgqddpFbNDKwGuhlw;+8a1YLT ztJ549dK@C(nS&+zU89nLvKzfSNKd`PY{i8^jmFY~i%L^!mODRX^k~E&Q@Qv}alda> zM(^aJ`etSLw&HI>bU6yJ+%#Ewwpwgez_z_>s6%ssN%oLtir;VFVy`=qayIrf3z>WI z-{n`ln{1Ra%KPJ4{GL~^->V_%1vNM%PV6l!AG&r9s<8p<2i7@l5_?_Hh)>~DS*qV~C@M6o}lNqm@B87_vuCr;$ZE=4Y$bLd0mNE0XHvjS|dS)zBa;z;1 z?W-1Zyi6)QFeCXfdnlupR^&XXxs%jd54c0a^4fN zl?u`E$+o5+wf3Wh?WIwRc^ybkQDlBWG@=1vBW%15VYc>>>g~lXs&X0R3_j(W+e^7R zo9c<~SYQwlc(QR%Ho_{c+9EEmv`Fq!ZFIoggbPJ+K=(71diWCK>X|3gY)Vh$MU%@* zPmblTKwFHWxw1xqTS?#5LU6BA8|hl9d|m(jo#JHG6^+X#M;M;NOF<=OGo!%+=)7`w*`ZBH^Ftq8D%Ei8Y=X z4662_yqs31eon26tZ~H6dh7Q=JvQ1K$@7C7#Z^)h@e(ICoi0@n)_NK9Dy-X&6)55C zPbX!rWr8){StPn;bPJW?C&}^b&KsFO(<+t5li~HvXVLw9S7-YhFWLpk>Vu1ETSB`Y zDuF_I|2uoKdiSl~!zeszI44s=vyW`Lhx&2oR?bTk{UF4vVWA#NH3XR|LaAVAUi>`f zi$)j!t|Q<&s8kEO4qHaeQV0DM3%ofV>W?R7s%0qYU(jxFiv-Cc9a=K{)He{&SA&MY z?=hC(-aZKUGqZ(DNW-i4sQfWr(Dpxl3OUPqrJ6ylA9n_E#?m<-3Ht?UJlspkl8_~j zkJwuRE+9=k*dU9@HyMs!%?L4(=7}etmq7KHkI(NscjAQOLrI+Mjg9{R*z87@Yay(S z5ma%_}cOei`+X$`8cLRC;RK@TY$?>*YBW zt*R@N41T&xnv{Ax2AoU#9&b)&OMN~*qfkj$OH3Z_%@Pbw*IJ|l2VlM+M`R^OBqdCw zi16|G2!_xEMHHTP%Fsx385YQ0sJ;}83f9+`iMDnA!53fS`hxOIRLH_L&rrT+S7fp! z6<6sUwz*P*#hxaqd{Zo~pSE!wnK$fGk}nH!9aweIZfpNTIpCzn88pQ|DAE zGzoF-`J6SOEUEFHndjlzI&sEKJ(x+9D$iGwT{P(Vy|1#QXs+;N3cZsMf|>fl zsBN(DP?mY=Z*1#GK0nSkgzuGOhUr7wNWQOsSq>INdcN(j+E(wxTBI_DOCK); - 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 16/32] 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 687333f19..31acc1c57 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 17/32] 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 31acc1c57..51dbc201d 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 18/32] 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 c4f262675..e375179e2 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 19/32] 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 54e6802e6..aa5268539 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 3aecdfd1f..c97180982 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 20/32] 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 e375179e2..2c58c2a25 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 405119fc0..6132430f1 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 21/32] 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 d9dea188f..76f675c70 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 c330f34b2..c5dbdac9c 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 22/32] 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 8c2ef573f..49fd17ce8 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 23/32] 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 2c58c2a25..142dd015d 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 aa5268539..4c4bebee4 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 24/32] 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 2b63bc79b..ef480f60f 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 966743033..9dbaf6e99 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 25/32] 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 2c58c2a25..4b38020c1 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 49fd17ce8..979214fb5 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 26/32] 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 f7709e9d6..aa6912fc4 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 27/32] 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 c99d9090c..bf174cbf1 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 28/32] 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 aa6912fc4..ec586dbef 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 4fcdd8df3..bb9310888 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 8a58e5ec9..b4de4a509 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 979214fb5..946cbb275 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 429175fe6..b918dee23 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 e28189220..f50c7fe25 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 3750e3a3e..799fa11c7 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 af8734184..2c77dcb7a 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 99f7e3cda..f1a493b0f 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 29/32] 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 19909b2bc..54815188e 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 d2d241054..06900410a 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 30/32] 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 9417364ef..88527e9fd 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 31/32] 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 54815188e..ff0076880 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 06900410a..89e4570a9 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 32/32] 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 ff0076880..f2deba046 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 ec586dbef..60af399c0 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; };