From 46c827c7fc3f344b6be28692b25aa5d04659291d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Fri, 28 Jan 2022 14:51:08 +0100 Subject: [PATCH 01/19] Fixed Clang 12 compiler warnings. --- CMakeLists.txt | 5 +++++ src/libslic3r/Fill/FillRectilinear.cpp | 2 +- src/libslic3r/Model.cpp | 2 +- src/libslic3r/MultiPoint.hpp | 3 ++- src/libslic3r/Polygon.hpp | 2 +- src/libslic3r/Polyline.hpp | 3 ++- src/slic3r/GUI/FirmwareDialog.cpp | 2 +- src/slic3r/GUI/OptionsGroup.hpp | 3 ++- 8 files changed, 15 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8557ab0d7..441d09af9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -239,6 +239,11 @@ if (NOT MSVC AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMP add_compile_options(-Wno-deprecated-declarations) endif() + # Clang reports misleading indentation for some IF blocks because of mixing tabs with spaces. + if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + add_compile_options(-Wno-misleading-indentation) + endif() + #GCC generates loads of -Wunknown-pragmas when compiling igl. The fix is not easy due to a bug in gcc, see # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66943 or # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53431 diff --git a/src/libslic3r/Fill/FillRectilinear.cpp b/src/libslic3r/Fill/FillRectilinear.cpp index 69476175e..7d868860a 100644 --- a/src/libslic3r/Fill/FillRectilinear.cpp +++ b/src/libslic3r/Fill/FillRectilinear.cpp @@ -2391,7 +2391,7 @@ static std::vector chain_monotonic_regions( // Probability (unnormalized) of traversing a link between two monotonic regions. auto path_probability = [ -#ifndef __APPLE__ +#if !defined(__APPLE__) && !defined(__clang__) // clang complains when capturing constexpr constants. pheromone_alpha, pheromone_beta #endif // __APPLE__ diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index efc66f478..67450fb11 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -2264,7 +2264,7 @@ void check_model_ids_validity(const Model &model) for (const ModelInstance *model_instance : model_object->instances) check(model_instance->id()); } - for (const auto mm : model.materials) { + for (const auto &mm : model.materials) { check(mm.second->id()); check(mm.second->config.id()); } diff --git a/src/libslic3r/MultiPoint.hpp b/src/libslic3r/MultiPoint.hpp index 935348279..b5208b1d8 100644 --- a/src/libslic3r/MultiPoint.hpp +++ b/src/libslic3r/MultiPoint.hpp @@ -17,7 +17,8 @@ class MultiPoint public: Points points; - MultiPoint() {} + MultiPoint() = default; + virtual ~MultiPoint() = default; MultiPoint(const MultiPoint &other) : points(other.points) {} MultiPoint(MultiPoint &&other) : points(std::move(other.points)) {} MultiPoint(std::initializer_list list) : points(list) {} diff --git a/src/libslic3r/Polygon.hpp b/src/libslic3r/Polygon.hpp index 7d34e3aae..d24540339 100644 --- a/src/libslic3r/Polygon.hpp +++ b/src/libslic3r/Polygon.hpp @@ -19,7 +19,7 @@ class Polygon : public MultiPoint { public: Polygon() = default; - virtual ~Polygon() = default; + ~Polygon() override = default; explicit Polygon(const Points &points) : MultiPoint(points) {} Polygon(std::initializer_list points) : MultiPoint(points) {} Polygon(const Polygon &other) : MultiPoint(other.points) {} diff --git a/src/libslic3r/Polyline.hpp b/src/libslic3r/Polyline.hpp index 31e0b88d3..5766d9671 100644 --- a/src/libslic3r/Polyline.hpp +++ b/src/libslic3r/Polyline.hpp @@ -16,7 +16,8 @@ typedef std::vector ThickPolylines; class Polyline : public MultiPoint { public: - Polyline() {}; + Polyline() = default; + ~Polyline() override = default; Polyline(const Polyline &other) : MultiPoint(other.points) {} Polyline(Polyline &&other) : MultiPoint(std::move(other.points)) {} Polyline(std::initializer_list list) : MultiPoint(list) {} diff --git a/src/slic3r/GUI/FirmwareDialog.cpp b/src/slic3r/GUI/FirmwareDialog.cpp index 7600ef4fa..47402644f 100644 --- a/src/slic3r/GUI/FirmwareDialog.cpp +++ b/src/slic3r/GUI/FirmwareDialog.cpp @@ -654,7 +654,7 @@ void FirmwareDialog::priv::perform_upload() } }) .on_message([ -#ifndef __APPLE__ +#if !defined(__APPLE__) && !defined(__clang__) // clang complains when capturing constants. extra_verbose, #endif // __APPLE__ diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index 61a59f0e3..f3efd0680 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -185,7 +185,7 @@ public: OptionsGroup( wxWindow* _parent, const wxString& title, bool is_tab_opt = false, column_t extra_clmn = nullptr); - ~OptionsGroup() { clear(true); } + virtual ~OptionsGroup() { clear(true); } wxGridSizer* get_grid_sizer() { return m_grid_sizer; } const std::vector& get_lines() { return m_lines; } @@ -253,6 +253,7 @@ public: OptionsGroup(parent, title, is_tab_opt, extra_clmn), m_config(&config->get()), m_modelconfig(config) {} ConfigOptionsGroup( wxWindow* parent) : OptionsGroup(parent, wxEmptyString, true, nullptr) {} + ~ConfigOptionsGroup() override = default; const wxString& config_category() const throw() { return m_config_category; } int config_type() const throw() { return m_config_type; } From 5f0fea4d58f558bb64681d28c8e10c6392b48629 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Fri, 28 Jan 2022 14:51:34 +0100 Subject: [PATCH 02/19] Added option to enable UndefinedBehaviorSanitizer on Clang and GCC. --- CMakeLists.txt | 27 +++++++++++++++++++++++++++ deps/Boost/Boost.cmake | 6 ++++++ deps/Boost/Boost.patch | 23 +++++++++++++++++++++++ src/PrusaSlicer.cpp | 9 +++++++++ src/libslic3r/Int128.hpp | 5 +++++ 5 files changed, 70 insertions(+) create mode 100644 deps/Boost/Boost.patch diff --git a/CMakeLists.txt b/CMakeLists.txt index 441d09af9..72fd87d22 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,7 @@ option(SLIC3R_MSVC_COMPILE_PARALLEL "Compile on Visual Studio in parallel" 1) option(SLIC3R_MSVC_PDB "Generate PDB files on MSVC in Release mode" 1) option(SLIC3R_PERL_XS "Compile XS Perl module and enable Perl unit and integration tests" 0) option(SLIC3R_ASAN "Enable ASan on Clang and GCC" 0) +option(SLIC3R_UBSAN "Enable UBSan on Clang and GCC" 0) # If SLIC3R_FHS is 1 -> SLIC3R_DESKTOP_INTEGRATION is always 0, othrewise variable. CMAKE_DEPENDENT_OPTION(SLIC3R_DESKTOP_INTEGRATION "Allow perfoming desktop integration during runtime" 1 "NOT SLIC3R_FHS" 0) @@ -271,6 +272,32 @@ if (SLIC3R_ASAN) endif () endif () +if (SLIC3R_UBSAN) + # Stacktrace for every report is enabled by default. It can be disabled by running PrusaSlicer with "UBSAN_OPTIONS=print_stacktrace=0". + + # Define macro SLIC3R_UBSAN to allow detection in the source code if this sanitizer is enabled. + add_compile_definitions(SLIC3R_UBSAN) + + # Clang supports much more useful checks than GCC, so when Clang is detected, another checks will be enabled. + # List of what GCC is checking: https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html + # List of what Clang is checking: https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + set(_ubsan_flags "-fsanitize=undefined,integer") + else () + set(_ubsan_flags "-fsanitize=undefined") + endif () + + add_compile_options(${_ubsan_flags} -fno-omit-frame-pointer) + + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${_ubsan_flags}") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${_ubsan_flags}") + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${_ubsan_flags}") + + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lubsan") + endif () +endif () + if (APPLE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=partial-availability -Werror=unguarded-availability -Werror=unguarded-availability-new") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=partial-availability -Werror=unguarded-availability -Werror=unguarded-availability-new") diff --git a/deps/Boost/Boost.cmake b/deps/Boost/Boost.cmake index ec8bab799..15792d5a7 100644 --- a/deps/Boost/Boost.cmake +++ b/deps/Boost/Boost.cmake @@ -120,6 +120,12 @@ set(_build_cmd ${_build_cmd} set(_install_cmd ${_build_cmd} --prefix=${_prefix} install) +if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + # When Clang is used with enabled UndefinedBehaviorSanitizer, it produces "undefined reference to '__muloti4'" when __int128 is used. + # Because of that, UndefinedBehaviorSanitizer is disabled for those functions that use __int128. + list(APPEND _patch_command COMMAND ${PATCH_CMD} ${CMAKE_CURRENT_LIST_DIR}/Boost.patch) +endif () + ExternalProject_Add( dep_Boost URL "https://boostorg.jfrog.io/artifactory/main/release/1.75.0/source/boost_1_75_0.tar.gz" diff --git a/deps/Boost/Boost.patch b/deps/Boost/Boost.patch new file mode 100644 index 000000000..8c54430b9 --- /dev/null +++ b/deps/Boost/Boost.patch @@ -0,0 +1,23 @@ +diff -u ../boost_1_75_0-orig/boost/rational.hpp ./boost/rational.hpp +--- ../boost_1_75_0-orig/boost/rational.hpp 2020-12-03 06:02:19.000000000 +0100 ++++ ./boost/rational.hpp 2022-01-27 16:02:27.993848905 +0100 +@@ -302,6 +302,9 @@ + return *this; + } + template ++ #if defined(__clang__) ++ __attribute__((no_sanitize("undefined"))) ++ #endif + BOOST_CXX14_CONSTEXPR typename boost::enable_if_c::value, rational&>::type operator*= (const T& i) + { + // Avoid overflow and preserve normalization +@@ -311,6 +314,9 @@ + return *this; + } + template ++ #if defined(__clang__) ++ __attribute__((no_sanitize("undefined"))) ++ #endif + BOOST_CXX14_CONSTEXPR typename boost::enable_if_c::value, rational&>::type operator/= (const T& i) + { + // Avoid repeated construction diff --git a/src/PrusaSlicer.cpp b/src/PrusaSlicer.cpp index 78e3623d9..2648fba9e 100644 --- a/src/PrusaSlicer.cpp +++ b/src/PrusaSlicer.cpp @@ -843,6 +843,15 @@ extern "C" { } #endif +#if defined(SLIC3R_UBSAN) +extern "C" { + // Enable printing stacktrace by default. It can be disabled by running PrusaSlicer with "UBSAN_OPTIONS=print_stacktrace=0". + const char *__ubsan_default_options() { + return "print_stacktrace=1"; + } +} +#endif + #if defined(_MSC_VER) || defined(__MINGW32__) extern "C" { __declspec(dllexport) int __stdcall slic3r_main(int argc, wchar_t **argv) diff --git a/src/libslic3r/Int128.hpp b/src/libslic3r/Int128.hpp index 8dc9e012d..7aeacbfce 100644 --- a/src/libslic3r/Int128.hpp +++ b/src/libslic3r/Int128.hpp @@ -105,6 +105,11 @@ public: static inline Int128 multiply(int64_t lhs, int64_t rhs) { return Int128(__int128(lhs) * __int128(rhs)); } +#if defined(__clang__) + // When Clang is used with enabled UndefinedBehaviorSanitizer, it produces "undefined reference to '__muloti4'" when __int128 is used. + // Because of that, UndefinedBehaviorSanitizer is disabled for this function. + __attribute__((no_sanitize("undefined"))) +#endif // Evaluate signum of a 2x2 determinant. static int sign_determinant_2x2(int64_t a11, int64_t a12, int64_t a21, int64_t a22) { From ea84a46cdc9894be4481d3c7eb111522ce20277a Mon Sep 17 00:00:00 2001 From: YuSanka Date: Sat, 29 Jan 2022 11:16:28 +0100 Subject: [PATCH 03/19] G=code substitutions: Debugger: Fixed wxWidgets assert when new substitution is added + Fixed representation of the gcode_substitution in DiffDialog and UnsavedChangesDialog --- src/slic3r/GUI/Tab.cpp | 4 ++-- src/slic3r/GUI/UnsavedChangesDialog.cpp | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index b08eed47b..bdebb5833 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -4000,7 +4000,7 @@ void SubstitutionManager::add_substitution( int substitution_id, editor->SetFont(wxGetApp().normal_font()); wxGetApp().UpdateDarkUI(editor); - top_sizer->Add(editor, proportion, wxALIGN_CENTER_VERTICAL | wxEXPAND| wxRIGHT, m_em); + top_sizer->Add(editor, proportion, wxALIGN_CENTER_VERTICAL | wxRIGHT, m_em); editor->Bind(wxEVT_TEXT_ENTER, [this, editor, substitution_id, opt_pos](wxEvent& e) { #if !defined(__WXGTK__) @@ -4065,7 +4065,7 @@ void SubstitutionManager::add_substitution( int substitution_id, auto v_sizer = new wxBoxSizer(wxVERTICAL); v_sizer->Add(top_sizer, 1, wxEXPAND); v_sizer->Add(params_sizer, 1, wxEXPAND|wxTOP|wxBOTTOM, int(0.5* m_em)); - m_grid_sizer->Add(v_sizer, 1, wxALIGN_CENTER_VERTICAL | wxEXPAND); + m_grid_sizer->Add(v_sizer, 1, wxEXPAND); if (call_after_layout) { m_parent->GetParent()->Layout(); diff --git a/src/slic3r/GUI/UnsavedChangesDialog.cpp b/src/slic3r/GUI/UnsavedChangesDialog.cpp index 608721203..002287ded 100644 --- a/src/slic3r/GUI/UnsavedChangesDialog.cpp +++ b/src/slic3r/GUI/UnsavedChangesDialog.cpp @@ -1158,10 +1158,11 @@ static wxString get_string_value(std::string opt_key, const DynamicPrintConfig& } if (opt_key == "gcode_substitutions") { if (!strings->empty()) - for (size_t id = 0; id < strings->size(); id += 3) + for (size_t id = 0; id < strings->size(); id += 4) out += from_u8(strings->get_at(id)) + ";\t" + from_u8(strings->get_at(id + 1)) + ";\t" + - from_u8(strings->get_at(id + 2)) + ";\n"; + from_u8(strings->get_at(id + 2)) + ";\t" + + from_u8(strings->get_at(id + 3)) + ";\n"; return out; } if (!strings->empty() && opt_idx < strings->values.size()) From de8ba0e85065c4b0d02019009b3be7f09e9b2fc9 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 31 Jan 2022 09:28:00 +0100 Subject: [PATCH 04/19] MsgDialog: get_wraped_wxString(): Fixed a bug in case, when string is break on slash --- src/slic3r/GUI/MsgDialog.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/slic3r/GUI/MsgDialog.cpp b/src/slic3r/GUI/MsgDialog.cpp index 622b8d930..79ff4214a 100644 --- a/src/slic3r/GUI/MsgDialog.cpp +++ b/src/slic3r/GUI/MsgDialog.cpp @@ -319,6 +319,7 @@ wxString get_wraped_wxString(const wxString& text_in, size_t line_len /*=80*/) if (cur_len >= line_len && idx >= 0) { if (text[idx] == slash) { text.insert(static_cast(idx) + 1, 1, new_line); + idx++; text_len++; } else // space From 58d64bae7762e225a9755a79c80068f56a81b5f5 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Mon, 31 Jan 2022 10:18:34 +0100 Subject: [PATCH 05/19] Fix of #6336 #5073: Throw an error if G92 E0 is missing in layer change G-code with relative extruder addressing. Also thrown an error, if G92 E0 is used with absolute extruder addressing. --- src/libslic3r/Print.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index e8078931b..ebd2e8f66 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -22,6 +22,7 @@ #include #include #include +#include // Mark string for localization and translate. #define L(s) Slic3r::I18N::translate(s) @@ -438,7 +439,8 @@ static inline bool sequential_print_vertical_clearance_valid(const Print &print) return it == print_instances_ordered.end() || (*it)->print_object->height() <= scale_(print.config().extruder_clearance_height.value); } - +// Matches "G92 E0" with various forms of writing the zero and with an optional comment. +boost::regex regex_g92e0 { "^[ \\t]*[gG]92[ \\t]*[eE](0(\\.0*)?|\\.0+)[ \\t]*(;.*)?$" }; // Precondition: Print::validate() requires the Print::apply() to be called its invocation. std::string Print::validate(std::string* warning) const @@ -652,6 +654,18 @@ std::string Print::validate(std::string* warning) const return err_msg; } } + { + bool before_layer_gcode_resets_extruder = boost::regex_search(m_config.before_layer_gcode.value, regex_g92e0); + bool layer_gcode_resets_extruder = boost::regex_search(m_config.layer_gcode.value, regex_g92e0); + if (m_config.use_relative_e_distances) { + // See GH issues #6336 #5073 + if (! before_layer_gcode_resets_extruder && ! layer_gcode_resets_extruder) + return "Relative extruder addressing requires resetting the extruder position at each layer to prevent loss of floating point accuracy. Add \"G92 E0\" to layer_gcode."; + } else if (before_layer_gcode_resets_extruder) + return "\"G92 E0\" was found in before_layer_gcode, which is incompatible with absolute extruder addressing."; + else if (layer_gcode_resets_extruder) + return "\"G92 E0\" was found in layer_gcode, which is incompatible with absolute extruder addressing."; + } return std::string(); } From 1a57db092f57cd72280fa0cfecf890fbfea1633f Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 31 Jan 2022 10:18:56 +0100 Subject: [PATCH 06/19] Print Settings: "Output options": Switched a places of "Post-processing scripts" and "G-code substitutions" --- src/slic3r/GUI/Tab.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index bdebb5833..225887c98 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1689,18 +1689,6 @@ void TabPrint::build() option.opt.full_width = true; optgroup->append_single_option_line(option); - optgroup = page->new_optgroup(L("Post-processing scripts"), 0); - line = { "", "" }; - line.full_width = 1; - line.widget = [this](wxWindow* parent) { - return description_line_widget(parent, &m_post_process_explanation); - }; - optgroup->append_line(line); - option = optgroup->get_option("post_process"); - option.opt.full_width = true; - option.opt.height = 5;//50; - optgroup->append_single_option_line(option); - optgroup = page->new_optgroup(L("Other")); create_line_with_widget(optgroup.get(), "gcode_substitutions", "g-code-substitutions_301694", [this](wxWindow* parent) { @@ -1713,6 +1701,18 @@ void TabPrint::build() }; optgroup->append_line(line); + optgroup = page->new_optgroup(L("Post-processing scripts"), 0); + line = { "", "" }; + line.full_width = 1; + line.widget = [this](wxWindow* parent) { + return description_line_widget(parent, &m_post_process_explanation); + }; + optgroup->append_line(line); + option = optgroup->get_option("post_process"); + option.opt.full_width = true; + option.opt.height = 5;//50; + optgroup->append_single_option_line(option); + page = add_options_page(L("Notes"), "note.png"); optgroup = page->new_optgroup(L("Notes"), 0); option = optgroup->get_option("notes"); From e3ef90941f0ddcc18f604b6c528aa5ea602bbc4a Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Mon, 31 Jan 2022 11:08:55 +0100 Subject: [PATCH 07/19] Hopefully fixed get_wraped_wxString() and did not introduce new bugs. --- src/slic3r/GUI/MsgDialog.cpp | 39 ++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/slic3r/GUI/MsgDialog.cpp b/src/slic3r/GUI/MsgDialog.cpp index 79ff4214a..368bc8618 100644 --- a/src/slic3r/GUI/MsgDialog.cpp +++ b/src/slic3r/GUI/MsgDialog.cpp @@ -294,37 +294,38 @@ InfoDialog::InfoDialog(wxWindow* parent, const wxString &title, const wxString& wxString get_wraped_wxString(const wxString& text_in, size_t line_len /*=80*/) { #ifdef __WXMSW__ - char slash = '\\'; + static constexpr const char slash = '\\'; #else - char slash = '/'; + static constexpr const char slash = '/'; #endif - char space = ' '; - char new_line = '\n'; + static constexpr const char space = ' '; + static constexpr const char new_line = '\n'; wxString text = text_in; int idx = -1; size_t cur_len = 0; - size_t text_len = text.Len(); + size_t text_len = text.size(); - for (size_t i = 0; i < text_len; i++) { - cur_len++; - if (text[i] == space || text[i] == slash) - idx = i; + for (size_t i = 0; i < text_len; ++ i) { if (text[i] == new_line) { idx = -1; cur_len = 0; - continue; - } - if (cur_len >= line_len && idx >= 0) { - if (text[idx] == slash) { - text.insert(static_cast(idx) + 1, 1, new_line); - idx++; - text_len++; + } else { + ++ cur_len; + if (text[i] == space || text[i] == slash) + idx = i; + if (cur_len >= line_len && idx >= 0) { + if (text[idx] == slash) { + text.insert(static_cast(++ idx), 1, new_line); + ++ text_len; + ++ i; + } + else // space + text[idx] = new_line; + cur_len = i - static_cast(idx); + idx = -1; } - else // space - text[idx] = new_line; - cur_len = i - static_cast(idx); } } return text; From 3e7a4d4648904b64c9f2d1c2948d81878f2a5eeb Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Mon, 31 Jan 2022 11:25:43 +0100 Subject: [PATCH 08/19] Follow-up to 58d64bae7762e225a9755a79c80068f56a81b5f5 Fixed Perl integration tests, missing G92 E0 in layer_change G-code for relative extruder addressing. --- t/gcode.t | 1 + 1 file changed, 1 insertion(+) diff --git a/t/gcode.t b/t/gcode.t index a43b5049c..e9725d5ed 100644 --- a/t/gcode.t +++ b/t/gcode.t @@ -133,6 +133,7 @@ use Slic3r::Test; my $config = Slic3r::Config::new_from_defaults; $config->set('retract_length', [1000000]); $config->set('use_relative_e_distances', 1); + $config->set('layer_gcode', 'G92 E0\n'); my $print = Slic3r::Test::init_print('20mm_cube', config => $config); Slic3r::Test::gcode($print); ok $print->print->total_used_filament > 0, 'final retraction is not considered in total used filament'; From 56e189943f2161acc5a95708949cf234e72f2c51 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Mon, 31 Jan 2022 11:27:32 +0100 Subject: [PATCH 09/19] Follow-up to 3e7a4d4648904b64c9f2d1c2948d81878f2a5eeb Allowed for localization of error messages. --- src/libslic3r/Print.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index ebd2e8f66..dc47b382d 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -660,11 +660,11 @@ std::string Print::validate(std::string* warning) const if (m_config.use_relative_e_distances) { // See GH issues #6336 #5073 if (! before_layer_gcode_resets_extruder && ! layer_gcode_resets_extruder) - return "Relative extruder addressing requires resetting the extruder position at each layer to prevent loss of floating point accuracy. Add \"G92 E0\" to layer_gcode."; + return L("Relative extruder addressing requires resetting the extruder position at each layer to prevent loss of floating point accuracy. Add \"G92 E0\" to layer_gcode."); } else if (before_layer_gcode_resets_extruder) - return "\"G92 E0\" was found in before_layer_gcode, which is incompatible with absolute extruder addressing."; + return L("\"G92 E0\" was found in before_layer_gcode, which is incompatible with absolute extruder addressing."); else if (layer_gcode_resets_extruder) - return "\"G92 E0\" was found in layer_gcode, which is incompatible with absolute extruder addressing."; + return L("\"G92 E0\" was found in layer_gcode, which is incompatible with absolute extruder addressing."); } return std::string(); From f368de9a2d84ad40b7ff419617f998dab4ff1579 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Mon, 31 Jan 2022 11:51:48 +0100 Subject: [PATCH 10/19] Follow-up to 3e7a4d4648904b64c9f2d1c2948d81878f2a5eeb Fixed Perl integration tests, missing G92 E0 in layer_change G-code for relative extruder addressing. --- t/gcode.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/gcode.t b/t/gcode.t index e9725d5ed..b95505e43 100644 --- a/t/gcode.t +++ b/t/gcode.t @@ -133,7 +133,7 @@ use Slic3r::Test; my $config = Slic3r::Config::new_from_defaults; $config->set('retract_length', [1000000]); $config->set('use_relative_e_distances', 1); - $config->set('layer_gcode', 'G92 E0\n'); + $config->set('layer_gcode', "G92 E0\n"); my $print = Slic3r::Test::init_print('20mm_cube', config => $config); Slic3r::Test::gcode($print); ok $print->print->total_used_filament > 0, 'final retraction is not considered in total used filament'; From 08abdc27a05b2314059338ae77ff941f7c3e64f2 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 31 Jan 2022 13:13:06 +0100 Subject: [PATCH 11/19] #7792 - Fixed relative positions of objects loaded from plain (non zipped) amf files --- src/slic3r/GUI/Plater.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 868f9ec56..db41c18ec 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2586,8 +2586,13 @@ std::vector Plater::priv::load_files(const std::vector& input_ } for (ModelObject* model_object : model.objects) { - if (!type_3mf && !type_zip_amf) + if (!type_3mf && !type_zip_amf) { model_object->center_around_origin(false); + if (type_any_amf && model_object->instances.empty()) { + ModelInstance* instance = model_object->add_instance(); + instance->set_offset(-model_object->origin_translation); + } + } model_object->ensure_on_bed(is_project_file); } @@ -2603,7 +2608,7 @@ std::vector Plater::priv::load_files(const std::vector& input_ } if (one_by_one) { - if (type_3mf && !is_project_file) + if ((type_3mf && !is_project_file) || (type_any_amf && !type_zip_amf)) model.center_instances_around_point(this->bed.build_volume().bed_center()); auto loaded_idxs = load_model_objects(model.objects, is_project_file); obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end()); From 7bd8b3b8925f02b57a4be38b318d91112fce1227 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 31 Jan 2022 14:26:31 +0100 Subject: [PATCH 12/19] #7791 - Fixed reload from disk command for plain (non zipped) amf files --- src/libslic3r/Format/AMF.cpp | 36 +++++++++++++++++++++++------------- src/slic3r/GUI/Plater.cpp | 22 +++++++++++++++------- 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src/libslic3r/Format/AMF.cpp b/src/libslic3r/Format/AMF.cpp index 235cdecb5..a8b66b15b 100644 --- a/src/libslic3r/Format/AMF.cpp +++ b/src/libslic3r/Format/AMF.cpp @@ -283,25 +283,28 @@ void AMFParserContext::startElement(const char *name, const char **atts) m_value[0] = type; node_type_new = NODE_TYPE_METADATA; } - } else if (strcmp(name, "material") == 0) { + } + else if (strcmp(name, "material") == 0) { const char *material_id = get_attribute(atts, "id"); m_material = m_model.add_material((material_id == nullptr) ? "_" : material_id); node_type_new = NODE_TYPE_MATERIAL; - } else if (strcmp(name, "object") == 0) { + } + else if (strcmp(name, "object") == 0) { const char *object_id = get_attribute(atts, "id"); if (object_id == nullptr) this->stop(); else { assert(m_object_vertices.empty()); m_object = m_model.add_object(); + m_object->name = std::string(object_id); m_object_instances_map[object_id].idx = int(m_model.objects.size())-1; node_type_new = NODE_TYPE_OBJECT; } - } else if (strcmp(name, "constellation") == 0) { - node_type_new = NODE_TYPE_CONSTELLATION; - } else if (strcmp(name, "custom_gcodes_per_height") == 0) { - node_type_new = NODE_TYPE_CUSTOM_GCODE; } + else if (strcmp(name, "constellation") == 0) + node_type_new = NODE_TYPE_CONSTELLATION; + else if (strcmp(name, "custom_gcodes_per_height") == 0) + node_type_new = NODE_TYPE_CUSTOM_GCODE; break; case 2: if (strcmp(name, "metadata") == 0) { @@ -309,12 +312,14 @@ void AMFParserContext::startElement(const char *name, const char **atts) m_value[0] = get_attribute(atts, "type"); node_type_new = NODE_TYPE_METADATA; } - } else if (strcmp(name, "layer_config_ranges") == 0 && m_path[1] == NODE_TYPE_OBJECT) + } + else if (strcmp(name, "layer_config_ranges") == 0 && m_path[1] == NODE_TYPE_OBJECT) node_type_new = NODE_TYPE_LAYER_CONFIG; else if (strcmp(name, "mesh") == 0) { if (m_path[1] == NODE_TYPE_OBJECT) node_type_new = NODE_TYPE_MESH; - } else if (strcmp(name, "instance") == 0) { + } + else if (strcmp(name, "instance") == 0) { if (m_path[1] == NODE_TYPE_CONSTELLATION) { const char *object_id = get_attribute(atts, "objectid"); if (object_id == nullptr) @@ -910,12 +915,17 @@ bool load_amf_file(const char *path, DynamicPrintConfig *config, ConfigSubstitut if (result) ctx.endDocument(); - for (ModelObject* o : model->objects) - { - for (ModelVolume* v : o->volumes) - { - if (v->source.input_file.empty() && (v->type() == ModelVolumeType::MODEL_PART)) + for (ModelObject* o : model->objects) { + unsigned int counter = 0; + for (ModelVolume* v : o->volumes) { + ++counter; + if (v->source.input_file.empty() && v->type() == ModelVolumeType::MODEL_PART) v->source.input_file = path; + if (v->name.empty()) { + v->name = o->name; + if (o->volumes.size() > 1) + v->name += "_" + std::to_string(counter); + } } } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index db41c18ec..a6447745c 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -3691,12 +3691,20 @@ void Plater::priv::reload_from_disk() if (has_source || has_name) { int new_volume_idx = -1; int new_object_idx = -1; -// if (has_source) { -// // take idxs from source -// new_volume_idx = old_volume->source.volume_idx; -// new_object_idx = old_volume->source.object_idx; -// } -// else { + bool match_found = false; + // take idxs from the matching volume + if (has_source && old_volume->source.object_idx < int(new_model.objects.size())) { + const ModelObject* obj = new_model.objects[old_volume->source.object_idx]; + if (old_volume->source.volume_idx < int(obj->volumes.size())) { + if (obj->volumes[old_volume->source.volume_idx]->name == old_volume->name) { + new_volume_idx = old_volume->source.volume_idx; + new_object_idx = old_volume->source.object_idx; + match_found = true; + } + } + } + + if (!match_found && has_name) { // take idxs from the 1st matching volume for (size_t o = 0; o < new_model.objects.size(); ++o) { ModelObject* obj = new_model.objects[o]; @@ -3712,7 +3720,7 @@ void Plater::priv::reload_from_disk() if (found) break; } -// } + } if (new_object_idx < 0 || int(new_model.objects.size()) <= new_object_idx) { fail_list.push_back(from_u8(has_source ? old_volume->source.input_file : old_volume->name)); From c2258dead7dc10c86f412aa25efb8a50c957584d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Mon, 31 Jan 2022 14:26:25 +0100 Subject: [PATCH 13/19] Fixed destructors of DiffViewCtrl and ObjectList after 8342b7f95bf52208f33fa4ed89da7a84e4260e9d and 0726b46da275642bb9f5ea3258be4550607bfe5b. --- src/slic3r/GUI/GUI_ObjectList.cpp | 3 ++- src/slic3r/GUI/UnsavedChangesDialog.hpp | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 4c86b146e..2b551eaca 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -239,7 +239,8 @@ ObjectList::ObjectList(wxWindow* parent) : ObjectList::~ObjectList() { - delete m_objects_model; + if (m_objects_model) + m_objects_model->DecRef(); } void ObjectList::set_min_height() diff --git a/src/slic3r/GUI/UnsavedChangesDialog.hpp b/src/slic3r/GUI/UnsavedChangesDialog.hpp index 115300a18..9061c0ba2 100644 --- a/src/slic3r/GUI/UnsavedChangesDialog.hpp +++ b/src/slic3r/GUI/UnsavedChangesDialog.hpp @@ -204,7 +204,12 @@ class DiffViewCtrl : public wxDataViewCtrl public: DiffViewCtrl(wxWindow* parent, wxSize size); - ~DiffViewCtrl() override { Clear(); delete model; } + ~DiffViewCtrl() override { + if (model) { + Clear(); + model->DecRef(); + } + } DiffModel* model{ nullptr }; From ba82cfa9e36700cecfdc40c52245cdb083a9c73e Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 31 Jan 2022 14:37:38 +0100 Subject: [PATCH 14/19] Follow-up to https://github.com/prusa3d/PrusaSlicer/commit/e3ef90941f0ddcc18f604b6c528aa5ea602bbc4a - next improvements for get_wraped_wxString --- src/slic3r/GUI/MsgDialog.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/slic3r/GUI/MsgDialog.cpp b/src/slic3r/GUI/MsgDialog.cpp index 368bc8618..dad88f14b 100644 --- a/src/slic3r/GUI/MsgDialog.cpp +++ b/src/slic3r/GUI/MsgDialog.cpp @@ -303,28 +303,32 @@ wxString get_wraped_wxString(const wxString& text_in, size_t line_len /*=80*/) wxString text = text_in; - int idx = -1; + size_t idx = 0; size_t cur_len = 0; size_t text_len = text.size(); for (size_t i = 0; i < text_len; ++ i) { if (text[i] == new_line) { - idx = -1; + idx = i; cur_len = 0; } else { ++ cur_len; if (text[i] == space || text[i] == slash) idx = i; - if (cur_len >= line_len && idx >= 0) { - if (text[idx] == slash) { - text.insert(static_cast(++ idx), 1, new_line); - ++ text_len; - ++ i; + if (cur_len >= line_len) { + cur_len = i - idx; + if (cur_len >= line_len) { + text.insert(++i, 1, new_line); + idx = i; + cur_len = 0; + } + else if (text[idx] == slash) { + text.insert(++idx, 1, new_line); + ++text_len; + ++i; } else // space text[idx] = new_line; - cur_len = i - static_cast(idx); - idx = -1; } } } From 1fe9e5231b4c67d9fd3f3c697bf5139e4f8bb4a9 Mon Sep 17 00:00:00 2001 From: rtyr <36745189+rtyr@users.noreply.github.com> Date: Mon, 31 Jan 2022 14:44:43 +0100 Subject: [PATCH 15/19] Added G92 E0. --- resources/profiles/Jubilee.ini | 1 + resources/profiles/RatRig.ini | 4 ++-- resources/profiles/Voron.ini | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/resources/profiles/Jubilee.ini b/resources/profiles/Jubilee.ini index 477b6a1e3..d9ab64bd7 100644 --- a/resources/profiles/Jubilee.ini +++ b/resources/profiles/Jubilee.ini @@ -498,6 +498,7 @@ use_volumetric_e = 0 variable_layer_height = 0 wipe = 0,0 z_offset = 0 +before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0 default_filament_profile = "Generic PLA @Jubilee; Generic PLA @Jubilee" default_print_profile = 0.2mm V6, aesthetic @Jubilee diff --git a/resources/profiles/RatRig.ini b/resources/profiles/RatRig.ini index ff18030d3..69379e781 100644 --- a/resources/profiles/RatRig.ini +++ b/resources/profiles/RatRig.ini @@ -384,7 +384,7 @@ top_solid_infill_speed = 60% # Common printer preset [printer:*common*] -before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\n;{if layer_num == 2 }SET_FILAMENT_SENSOR SENSOR=my_sensor ENABLE=1{endif}\n\n +before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\nG92 E0\n;{if layer_num == 2 }SET_FILAMENT_SENSOR SENSOR=my_sensor ENABLE=1{endif}\n\n between_objects_gcode = color_change_gcode = M600 cooling_tube_length = 5 @@ -453,7 +453,7 @@ printer_variant = 0.4 [printer:*vminion-klipper*] inherits = *common* -before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\n;{if layer_num == 2 }SET_FILAMENT_SENSOR SENSOR=my_sensor ENABLE=1{endif}\n\n +before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\nG92 E0\n;{if layer_num == 2 }SET_FILAMENT_SENSOR SENSOR=my_sensor ENABLE=1{endif}\n\n default_filament_profile = "Generic PLA @RatRig" default_print_profile = 0.20mm NORMAL V-Minion @RatRig deretract_speed = 40 diff --git a/resources/profiles/Voron.ini b/resources/profiles/Voron.ini index fb024870a..cd0fbd2d9 100644 --- a/resources/profiles/Voron.ini +++ b/resources/profiles/Voron.ini @@ -168,7 +168,7 @@ default_print_profile = 0.4mm 1.2nozzle # Common printer preset [printer:*common*] printer_technology = FFF -before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\n\n +before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\nG92 E0\n between_objects_gcode = deretract_speed = 25 end_gcode = print_end ;end script from macro From 383f6509a9ed94ac223882aaa755e9c4cebe4da2 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 31 Jan 2022 15:36:40 +0100 Subject: [PATCH 16/19] Added tech DISABLE_GCODEVIEWER_INSTANCED_MODELS to easily turn on/off instanced models to render options in gcode preview --- src/libslic3r/Technologies.hpp | 2 ++ src/slic3r/GUI/GCodeViewer.cpp | 24 ++++++++++++++---------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index b089ce1f9..52c9e10d3 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -26,6 +26,8 @@ #define ENABLE_GCODE_VIEWER_DATA_CHECKING 0 // Enable project dirty state manager debug window #define ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW 0 +// Disable using instanced models to render options in gcode preview +#define DISABLE_GCODEVIEWER_INSTANCED_MODELS 1 // Enable rendering of objects using environment map diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 5eea58a0f..367846f0c 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -584,14 +584,16 @@ void GCodeViewer::init() case EMoveType::Retract: case EMoveType::Unretract: case EMoveType::Seam: { -// if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { -// buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::InstancedModel; -// buffer.shader = "gouraud_light_instanced"; -// buffer.model.model.init_from(diamond(16)); -// buffer.model.color = option_color(type); -// buffer.model.instances.format = InstanceVBuffer::EFormat::InstancedModel; -// } -// else { +#if !DISABLE_GCODEVIEWER_INSTANCED_MODELS + if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { + buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::InstancedModel; + buffer.shader = "gouraud_light_instanced"; + buffer.model.model.init_from(diamond(16)); + buffer.model.color = option_color(type); + buffer.model.instances.format = InstanceVBuffer::EFormat::InstancedModel; + } + else { +#endif // !DISABLE_GCODEVIEWER_INSTANCED_MODELS buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::BatchedModel; buffer.vertices.format = VBuffer::EFormat::PositionNormal3; buffer.shader = "gouraud_light"; @@ -599,8 +601,10 @@ void GCodeViewer::init() buffer.model.data = diamond(16); buffer.model.color = option_color(type); buffer.model.instances.format = InstanceVBuffer::EFormat::BatchedModel; -// } - break; +#if !DISABLE_GCODEVIEWER_INSTANCED_MODELS + } +#endif // !DISABLE_GCODEVIEWER_INSTANCED_MODELS + break; } case EMoveType::Wipe: case EMoveType::Extrude: { From be60775077f08a1cc3b58a1e32b6923cdee15873 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Mon, 31 Jan 2022 16:25:20 +0100 Subject: [PATCH 17/19] get_wraped_wxString(): Adapted to work with UTF8 --- src/libslic3r/Utils.hpp | 1 + src/libslic3r/utils.cpp | 31 +++++++------ src/slic3r/GUI/MsgDialog.cpp | 84 ++++++++++++++++++++---------------- 3 files changed, 66 insertions(+), 50 deletions(-) diff --git a/src/libslic3r/Utils.hpp b/src/libslic3r/Utils.hpp index d9419495e..1de3a5ef8 100644 --- a/src/libslic3r/Utils.hpp +++ b/src/libslic3r/Utils.hpp @@ -77,6 +77,7 @@ extern std::string normalize_utf8_nfc(const char *src); // Returns next utf8 sequence length. =number of bytes in string, that creates together one utf-8 character. // Starting at pos. ASCII characters returns 1. Works also if pos is in the middle of the sequence. extern size_t get_utf8_sequence_length(const std::string& text, size_t pos = 0); +extern size_t get_utf8_sequence_length(const char *seq, size_t size); // Safely rename a file even if the target exists. // On Windows, the file explorer (or anti-virus or whatever else) often locks the file diff --git a/src/libslic3r/utils.cpp b/src/libslic3r/utils.cpp index c74e57e99..e00b6e71c 100644 --- a/src/libslic3r/utils.cpp +++ b/src/libslic3r/utils.cpp @@ -866,8 +866,13 @@ std::string normalize_utf8_nfc(const char *src) size_t get_utf8_sequence_length(const std::string& text, size_t pos) { assert(pos < text.size()); + return get_utf8_sequence_length(text.c_str() + pos, text.size() - pos); +} + +size_t get_utf8_sequence_length(const char *seq, size_t size) +{ size_t length = 0; - unsigned char c = text[pos]; + unsigned char c = seq[0]; if (c < 0x80) { // 0x00-0x7F // is ASCII letter length++; @@ -876,8 +881,8 @@ size_t get_utf8_sequence_length(const std::string& text, size_t pos) // pos is in the middle of a utf-8 sequence. Add the utf-8 trailer bytes. else if (c < 0xC0) { // 0x80-0xBF length++; - while (pos + length < text.size()) { - c = text[pos + length]; + while (length < size) { + c = seq[length]; if (c < 0x80 || c >= 0xC0) { break; // prevent overrun } @@ -888,36 +893,36 @@ size_t get_utf8_sequence_length(const std::string& text, size_t pos) // The number of one bits above the topmost zero bit indicates the number of bytes (including this one) in the whole sequence. else if (c < 0xE0) { // 0xC0-0xDF // add a utf-8 sequence (2 bytes) - if (pos + 2 > text.size()) { - return text.size() - pos; // prevent overrun + if (2 > size) { + return size; // prevent overrun } length += 2; } else if (c < 0xF0) { // 0xE0-0xEF // add a utf-8 sequence (3 bytes) - if (pos + 3 > text.size()) { - return text.size() - pos; // prevent overrun + if (3 > size) { + return size; // prevent overrun } length += 3; } else if (c < 0xF8) { // 0xF0-0xF7 // add a utf-8 sequence (4 bytes) - if (pos + 4 > text.size()) { - return text.size() - pos; // prevent overrun + if (4 > size) { + return size; // prevent overrun } length += 4; } else if (c < 0xFC) { // 0xF8-0xFB // add a utf-8 sequence (5 bytes) - if (pos + 5 > text.size()) { - return text.size() - pos; // prevent overrun + if (5 > size) { + return size; // prevent overrun } length += 5; } else if (c < 0xFE) { // 0xFC-0xFD // add a utf-8 sequence (6 bytes) - if (pos + 6 > text.size()) { - return text.size() - pos; // prevent overrun + if (6 > size) { + return size; // prevent overrun } length += 6; } diff --git a/src/slic3r/GUI/MsgDialog.cpp b/src/slic3r/GUI/MsgDialog.cpp index dad88f14b..db4972a5d 100644 --- a/src/slic3r/GUI/MsgDialog.cpp +++ b/src/slic3r/GUI/MsgDialog.cpp @@ -291,48 +291,58 @@ InfoDialog::InfoDialog(wxWindow* parent, const wxString &title, const wxString& finalize(); } -wxString get_wraped_wxString(const wxString& text_in, size_t line_len /*=80*/) +wxString get_wraped_wxString(const wxString& in, size_t line_len /*=80*/) { -#ifdef __WXMSW__ - static constexpr const char slash = '\\'; -#else - static constexpr const char slash = '/'; -#endif - static constexpr const char space = ' '; - static constexpr const char new_line = '\n'; + wxString out; - wxString text = text_in; - - size_t idx = 0; - size_t cur_len = 0; - size_t text_len = text.size(); - - for (size_t i = 0; i < text_len; ++ i) { - if (text[i] == new_line) { - idx = i; - cur_len = 0; - } else { - ++ cur_len; - if (text[i] == space || text[i] == slash) - idx = i; - if (cur_len >= line_len) { - cur_len = i - idx; - if (cur_len >= line_len) { - text.insert(++i, 1, new_line); - idx = i; - cur_len = 0; - } - else if (text[idx] == slash) { - text.insert(++idx, 1, new_line); - ++text_len; - ++i; - } - else // space - text[idx] = new_line; + for (size_t i = 0; i < in.size();) { + // Overwrite the character (space or newline) starting at ibreak? + bool overwrite = false; +#if wxUSE_UNICODE_WCHAR + // On Windows, most likely the internal representation of wxString is wide char. + size_t end = std::min(in.size(), i + line_len); + size_t ibreak = end; + for (size_t j = i; j < end; ++ j) { + if (bool newline = in[j] == '\n'; in[j] == ' ' || in[j] == '\t' || newline) { + ibreak = j; + overwrite = true; + if (newline) + break; + } else if (in[j] == '/' || in[j] == '\\') + ibreak = j + 1; + } +#else + // UTF8 representation of wxString. + // Where to break the line, index of character at the start of a UTF-8 sequence. + size_t ibreak = size_t(-1); + // Overwrite the character at ibreak (it is a whitespace) or not? + for (size_t cnt = 0, j = i; j < in.size();) { + if (bool newline = in[j] == '\n'; in[j] == ' ' || in[j] == '\t' || newline) { + // Overwrite the whitespace. + ibreak = j ++; + overwrite = true; + if (newline) + break; + } else if (in[j] == '/') { + // Insert after the slash. + ibreak = ++ j; + } else + j += get_utf8_sequence_length(in.c_str() + j, in.size() - j); + if (++ cnt == line_len) { + if (ibreak == size_t(-1)) + ibreak = j; + break; } } +#endif + out.append(in.begin() + i, in.begin() + ibreak); + out.append('\n'); + i = ibreak; + if (overwrite) + ++ i; } - return text; + + return out; } } From 0c0250750ba268a3b0ac1cf0f463089f19a8b65c Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 1 Feb 2022 08:07:53 +0100 Subject: [PATCH 18/19] #7843 - Added processing of gcode lines G60 and G61 for Marlin firmwares --- src/libslic3r/GCode/GCodeProcessor.cpp | 45 ++++++++++++++++++++++++++ src/libslic3r/GCode/GCodeProcessor.hpp | 7 ++++ 2 files changed, 52 insertions(+) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index f60ad896b..995964eb5 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -1188,6 +1188,7 @@ void GCodeProcessor::reset() m_start_position = { 0.0f, 0.0f, 0.0f, 0.0f }; m_end_position = { 0.0f, 0.0f, 0.0f, 0.0f }; + m_saved_position = { 0.0f, 0.0f, 0.0f, 0.0f }; m_origin = { 0.0f, 0.0f, 0.0f, 0.0f }; m_cached_position.reset(); m_wiping = false; @@ -1616,6 +1617,13 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line, bool default: break; } break; + case '6': + switch (cmd[2]) { + case '0': { process_G60(line); break; } // Save Current Position + case '1': { process_G61(line); break; } // Return to Saved Position + default: break; + } + break; case '9': switch (cmd[2]) { case '0': { process_G90(line); break; } // Set to Absolute Positioning @@ -2828,6 +2836,43 @@ void GCodeProcessor::process_G28(const GCodeReader::GCodeLine& line) process_G1(new_gline); } +void GCodeProcessor::process_G60(const GCodeReader::GCodeLine& line) +{ + if (m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware) + m_saved_position = m_end_position; +} + +void GCodeProcessor::process_G61(const GCodeReader::GCodeLine& line) +{ + if (m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware) { + bool modified = false; + if (line.has_x()) { + m_end_position[X] = m_saved_position[X]; + modified = true; + } + if (line.has_y()) { + m_end_position[Y] = m_saved_position[Y]; + modified = true; + } + if (line.has_z()) { + m_end_position[Z] = m_saved_position[Z]; + modified = true; + } + if (line.has_e()) { + m_end_position[E] = m_saved_position[E]; + modified = true; + } + if (line.has_f()) + m_feedrate = line.f(); + + if (!modified) + m_end_position = m_saved_position; + + + store_move_vertex(EMoveType::Travel); + } +} + void GCodeProcessor::process_G90(const GCodeReader::GCodeLine& line) { m_global_positioning_type = EPositioningType::Absolute; diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 2f3ee4e5d..153f4a9c5 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -517,6 +517,7 @@ namespace Slic3r { AxisCoords m_start_position; // mm AxisCoords m_end_position; // mm + AxisCoords m_saved_position; // mm AxisCoords m_origin; // mm CachedPosition m_cached_position; bool m_wiping; @@ -661,6 +662,12 @@ namespace Slic3r { // Move to origin void process_G28(const GCodeReader::GCodeLine& line); + // Save Current Position + void process_G60(const GCodeReader::GCodeLine& line); + + // Return to Saved Position + void process_G61(const GCodeReader::GCodeLine& line); + // Set to Absolute Positioning void process_G90(const GCodeReader::GCodeLine& line); From 9dae482e1222ee55e21584f2c2c8d0a1f692a20b Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Tue, 1 Feb 2022 10:03:22 +0100 Subject: [PATCH 19/19] Bumped up version to 2.4.1-beta1 --- src/slic3r/GUI/GUI_App.cpp | 4 ++-- version.inc | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 32b63fa8f..68080cd6b 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -869,8 +869,8 @@ void GUI_App::init_app_config() { // Profiles for the alpha are stored into the PrusaSlicer-alpha directory to not mix with the current release. // SetAppName(SLIC3R_APP_KEY); - SetAppName(SLIC3R_APP_KEY "-alpha"); -// SetAppName(SLIC3R_APP_KEY "-beta"); +// SetAppName(SLIC3R_APP_KEY "-alpha"); + SetAppName(SLIC3R_APP_KEY "-beta"); // SetAppDisplayName(SLIC3R_APP_NAME); // Set the Slic3r data directory at the Slic3r XS module. diff --git a/version.inc b/version.inc index c33dc002e..b976d7d67 100644 --- a/version.inc +++ b/version.inc @@ -3,7 +3,7 @@ set(SLIC3R_APP_NAME "PrusaSlicer") set(SLIC3R_APP_KEY "PrusaSlicer") -set(SLIC3R_VERSION "2.4.1-alpha0") +set(SLIC3R_VERSION "2.4.1-beta1") set(SLIC3R_BUILD_ID "PrusaSlicer-${SLIC3R_VERSION}+UNKNOWN") set(SLIC3R_RC_VERSION "2,4,1,0") set(SLIC3R_RC_VERSION_DOTS "2.4.1.0")