From e305594f2b7ba8e408fdafd0da5f385ff2c4199d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Fri, 17 May 2024 01:38:46 +0200 Subject: [PATCH 1/8] Fix a compiler warning in TriangleSelector. --- src/libslic3r/TriangleSelector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/TriangleSelector.cpp b/src/libslic3r/TriangleSelector.cpp index c8c03fcfbe..465160a449 100644 --- a/src/libslic3r/TriangleSelector.cpp +++ b/src/libslic3r/TriangleSelector.cpp @@ -1560,7 +1560,7 @@ TriangleSelector::TriangleSplittingData TriangleSelector::serialize() const { } else { // In case this is leaf, we better save information about its state. int n = int(tr.get_state()); - if (n < static_cast(TriangleStateType::Count)) + if (n < static_cast(TriangleStateType::Count)) data.used_states[n] = true; if (n >= 3) { From 0b7616c121983e20956afe465d63b4b908b992fd Mon Sep 17 00:00:00 2001 From: Ben Greiner Date: Fri, 26 Apr 2024 09:19:57 +0200 Subject: [PATCH 2/8] Remove deprecated boost filesystem convenience include (PR #12652) --- src/slic3r/GUI/RemovableDriveManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/slic3r/GUI/RemovableDriveManager.cpp b/src/slic3r/GUI/RemovableDriveManager.cpp index b963173b63..d4ecf4b208 100644 --- a/src/slic3r/GUI/RemovableDriveManager.cpp +++ b/src/slic3r/GUI/RemovableDriveManager.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #endif From d0e70e035abcaa19ff843935d3dace7ef78c868e Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 14 May 2024 16:46:14 +0200 Subject: [PATCH 3/8] Follow-up 26d52595 : Fixed a crash on move the GCodeViewer on other monitor --- src/slic3r/GUI/MainFrame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index b6644e0f75..ad6603fcf0 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -1053,7 +1053,7 @@ void MainFrame::on_dpi_changed(const wxRect& suggested_rect) this->SetFont(this->normal_font()); #ifdef _WIN32 - if (m_tmp_top_bar->IsShown()) + if (m_tmp_top_bar && m_tmp_top_bar->IsShown()) m_tmp_top_bar->Rescale(); m_tabpanel->Rescale(); #endif From e405d75a529510abf6bd21b8a5f98b13ef26d2de Mon Sep 17 00:00:00 2001 From: DJ Delorie Date: Sat, 20 Apr 2024 00:12:14 -0400 Subject: [PATCH 4/8] Fix skirt separation math (SPE-2285, PR#12621) In the code as-is, the half-width of the skirt extrusion is added to the user-specified distance. However, the user-specified distance is scaled to internal units while the half-width is not, resulting in math like "250000 + 0.125" for a skirt extrusion of 0.5mm The fix is to include the half-width inside the scaling function so that it is also scaled, resulting in math like "250000 + 125000". The user-visible result is that if you have no brim and set the skirt spacing to zero, the skirt will actually touch the model and not be offset by half an extrusion width. --- src/libslic3r/Print.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index ddf38250af..2cf539c966 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -1173,7 +1173,7 @@ void Print::_make_skirt() // Initial offset of the brim inner edge from the object (possible with a support & raft). // The skirt will touch the brim if the brim is extruded. - auto distance = float(scale_(m_config.skirt_distance.value) - spacing/2.); + auto distance = float(scale_(m_config.skirt_distance.value - spacing/2.)); // Draw outlines from outside to inside. // Loop while we have less skirts than required or any extruder hasn't reached the min length if any. std::vector extruded_length(extruders.size(), 0.); From 70d7911ee3c840cf88dc7a7c1fba7ac1acea9ada Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 10 May 2024 16:57:36 +0200 Subject: [PATCH 5/8] DoubleSliderForLayers improvements: 1. Fixed tooltips on ticks 2. Implemented posibility to edit colored band and ticks --- src/slic3r/GUI/DoubleSliderForLayers.cpp | 112 ++++++++++++++++++++--- src/slic3r/GUI/DoubleSliderForLayers.hpp | 6 +- 2 files changed, 101 insertions(+), 17 deletions(-) diff --git a/src/slic3r/GUI/DoubleSliderForLayers.cpp b/src/slic3r/GUI/DoubleSliderForLayers.cpp index e4dc8b866a..4ca62c07ee 100644 --- a/src/slic3r/GUI/DoubleSliderForLayers.cpp +++ b/src/slic3r/GUI/DoubleSliderForLayers.cpp @@ -203,6 +203,10 @@ void DSForLayers::draw_ticks(const ImRect& slideable_region) if (ImGui::IsMouseHoveringRect(tick_hover_box.Min, tick_hover_box.Max)) { ImGui::RenderFrame(tick_hover_box.Min, tick_hover_box.Max, tick_hovered_clr, false); + if (tick_it->type == ColorChange || tick_it->type == ToolChange) { + m_focus = fiTick; + ImGuiPureWrap::tooltip(get_tooltip(tick_it->tick), ImGui::GetFontSize() * 20.f); + } break; } ++tick_it; @@ -228,22 +232,22 @@ void DSForLayers::draw_ticks(const ImRect& slideable_region) bool activate_this_tick = false; if (tick_it == active_tick_it && m_allow_editing) { // delete tick - if (render_button(ImGui::RemoveTick, ImGui::RemoveTickHovered, btn_label, icon_pos, m_ctrl.IsActiveHigherThumb() ? fiHigherThumb : fiLowerThumb, tick_it->tick)) { + if (render_button(ImGui::RemoveTick, ImGui::RemoveTickHovered, btn_label, icon_pos, fiActionIcon, tick_it->tick)) { m_ticks.ticks.erase(tick_it); process_ticks_changed(); break; } } else if (m_draw_mode != dmRegular)// if we have non-regular draw mode, all ticks should be marked with error icon - activate_this_tick = render_button(ImGui::ErrorTick, ImGui::ErrorTickHovered, btn_label, icon_pos, fiActionIcon, tick_it->tick); + activate_this_tick = render_button(ImGui::ErrorTick, ImGui::ErrorTickHovered, btn_label, icon_pos, fiTick, tick_it->tick); else if (tick_it->type == ColorChange || tick_it->type == ToolChange) { if (m_ticks.is_conflict_tick(*tick_it, m_mode, m_values[tick_it->tick])) - activate_this_tick = render_button(ImGui::ErrorTick, ImGui::ErrorTickHovered, btn_label, icon_pos, fiActionIcon, tick_it->tick); + activate_this_tick = render_button(ImGui::ErrorTick, ImGui::ErrorTickHovered, btn_label, icon_pos, fiTick, tick_it->tick); } else if (tick_it->type == CustomGCode::PausePrint) - activate_this_tick = render_button(ImGui::PausePrint, ImGui::PausePrintHovered, btn_label, icon_pos, fiActionIcon, tick_it->tick); + activate_this_tick = render_button(ImGui::PausePrint, ImGui::PausePrintHovered, btn_label, icon_pos, fiTick, tick_it->tick); else - activate_this_tick = render_button(ImGui::EditGCode, ImGui::EditGCodeHovered, btn_label, icon_pos, fiActionIcon, tick_it->tick); + activate_this_tick = render_button(ImGui::EditGCode, ImGui::EditGCodeHovered, btn_label, icon_pos, fiTick, tick_it->tick); if (activate_this_tick) { m_ctrl.IsActiveHigherThumb() ? SetHigherPos(tick_it->tick) : SetLowerPos(tick_it->tick); @@ -297,10 +301,14 @@ void DSForLayers::draw_colored_band(const ImRect& groove, const ImRect& slideabl ImRect main_band = ImRect(blank_rect); main_band.Expand(blank_padding); - auto draw_band = [](const ImU32& clr, const ImRect& band_rc) { + auto draw_band = [this](const ImU32& clr, const ImRect& band_rc) { ImGui::RenderFrame(band_rc.Min, band_rc.Max, clr, false, band_rc.GetWidth() * 0.5); //cover round corner ImGui::RenderFrame(ImVec2(band_rc.Min.x, band_rc.Max.y - band_rc.GetWidth() * 0.5), band_rc.Max, clr, false); + + // add tooltip + if (ImGui::IsMouseHoveringRect(band_rc.Min, band_rc.Max)) + m_focus = fiColorBand; }; auto draw_main_band = [&main_band](const ImU32& clr) { @@ -315,6 +323,8 @@ void DSForLayers::draw_colored_band(const ImRect& groove, const ImRect& slideabl static float tick_pos; std::set::const_iterator tick_it = m_ticks.ticks.begin(); + + int rclicked_tick = -1; while (tick_it != m_ticks.ticks.end()) { //get position from tick @@ -337,13 +347,27 @@ void DSForLayers::draw_colored_band(const ImRect& groove, const ImRect& slideabl ImU32 band_clr = IM_COL32(rgba[0] * 255.0f, rgba[1] * 255.0f, rgba[2] * 255.0f, rgba[3] * 255.0f); if (tick_it->tick == 0) draw_main_band(band_clr); - else + else { draw_band(band_clr, band_rect); + + ImGuiContext& g = *GImGui; + if (ImGui::IsMouseHoveringRect(band_rect.Min, band_rect.Max) && + g.IO.MouseClicked[1] && !m_ctrl.IsRClickOnThumb()) { + rclicked_tick = tick_it->tick; + } + } } } } tick_it++; } + + if (m_focus == fiColorBand) { + if (rclicked_tick > 0) + edit_tick(rclicked_tick); + else if (auto tip = get_tooltip(); !tip.empty()) + ImGuiPureWrap::tooltip(tip, ImGui::GetFontSize() * 20.f); + } } void DSForLayers::render_menu() @@ -361,10 +385,13 @@ void DSForLayers::render_menu() ImGui::OpenPopup("slider_add_tick_menu_popup"); else if (m_show_cog_menu) ImGui::OpenPopup("cog_menu_popup"); + else if (m_show_edit_menu) + ImGui::OpenPopup("edit_menu_popup"); if (can_edit()) render_add_tick_menu(); render_cog_menu(); + render_edit_menu(); ImGui::PopStyleColor(1); ImGui::PopStyleVar(4); @@ -373,6 +400,7 @@ void DSForLayers::render_menu() if (context.IO.MouseReleased[0]) { m_show_just_color_change_menu = false; m_show_cog_menu = false; + m_show_edit_menu = false; } } @@ -416,8 +444,10 @@ void DSForLayers::render_add_tick_menu() } } -void DSForLayers::render_multi_extruders_menu() +bool DSForLayers::render_multi_extruders_menu(bool switch_current_code/* = false*/) { + bool ret = false; + std::vector colors; if (m_cb_get_extruder_colors) colors = m_cb_get_extruder_colors(); @@ -428,7 +458,7 @@ void DSForLayers::render_multi_extruders_menu() const int tick = m_ctrl.GetActivePos(); if (m_mode == MultiAsSingle) { - const std::string menu_name = _u8L("Change extruder"); + const std::string menu_name = switch_current_code ? _u8L("Switch code to Change extruder") : _u8L("Change extruder"); if (ImGuiPureWrap::begin_menu(menu_name.c_str())) { std::array active_extruders = m_ticks.get_active_extruders_for_tick(tick, m_mode); for (int i = 1; i <= extruders_cnt; i++) { @@ -439,14 +469,18 @@ void DSForLayers::render_multi_extruders_menu() std::array rgba = decode_color_to_float_array(colors[i - 1]); ImU32 icon_clr = IM_COL32(rgba[0] * 255.0f, rgba[1] * 255.0f, rgba[2] * 255.0f, rgba[3] * 255.0f); - if (ImGuiPureWrap::menu_item_with_icon(item_name.c_str(), "", ImVec2(14, 14) * m_scale, icon_clr, false, !is_active_extruder)) + if (ImGuiPureWrap::menu_item_with_icon(item_name.c_str(), "", ImVec2(14, 14) * m_scale, icon_clr, false, !is_active_extruder)) { add_code_as_tick(ToolChange, i); + ret = true; + } } ImGuiPureWrap::end_menu(); } } - const std::string menu_name = format(_u8L("Add color change (%1%) for:"), gcode(ColorChange)); + const std::string menu_name = switch_current_code ? + format(_u8L("Switch code to Color change (%1%) for:"), gcode(ColorChange)) : + format(_u8L("Add color change (%1%) for:"), gcode(ColorChange)); if (ImGuiPureWrap::begin_menu(menu_name.c_str())) { std::set used_extruders_for_tick = m_ticks.get_used_extruders_for_tick(tick, m_values[tick]); @@ -457,12 +491,15 @@ void DSForLayers::render_multi_extruders_menu() if (is_used_extruder) item_name += " (" + _u8L("used") + ")"; - if (ImGuiPureWrap::menu_item_with_icon(item_name.c_str(), "")) + if (ImGuiPureWrap::menu_item_with_icon(item_name.c_str(), "")) { add_code_as_tick(ColorChange, i); + ret = true; + } } ImGuiPureWrap::end_menu(); } } + return ret; } void DSForLayers::render_color_picker() @@ -519,6 +556,50 @@ void DSForLayers::render_cog_menu() } } +void DSForLayers::render_edit_menu() +{ + if (!m_show_edit_menu) + return; + + const ImVec2 icon_sz = ImVec2(14, 14); + if (m_ticks.has_tick(m_ctrl.GetActivePos()) && ImGui::BeginPopup("edit_menu_popup")) { + std::set::iterator it = m_ticks.ticks.find(TickCode{ m_ctrl.GetActivePos()}); + + if (it->type == ToolChange) { + if (render_multi_extruders_menu(true)) { + ImGui::EndPopup(); + return; + } + } + else { + std::string edit_item_name = it->type == CustomGCode::ColorChange ? _u8L("Edit color") : + it->type == CustomGCode::PausePrint ? _u8L("Edit pause print message") : + _u8L("Edit custom G-code"); + if (ImGuiPureWrap::menu_item_with_icon(edit_item_name.c_str(), "")) { + edit_tick(); + ImGui::EndPopup(); + return; + } + } + + if (it->type == ColorChange && m_mode == MultiAsSingle) { + if (render_multi_extruders_menu(true)) { + ImGui::EndPopup(); + return; + } + } + + std::string delete_item_name = it->type == CustomGCode::ColorChange ? _u8L("Delete color change") : + it->type == CustomGCode::ToolChange ? _u8L("Delete tool change") : + it->type == CustomGCode::PausePrint ? _u8L("Delete pause print") : + _u8L("Delete custom G-code"); + if (ImGuiPureWrap::menu_item_with_icon(delete_item_name.c_str(), "")) + delete_current_tick(); + + ImGui::EndPopup(); + } +} + bool DSForLayers::render_button(const wchar_t btn_icon, const wchar_t btn_icon_hovered, const std::string& label_id, const ImVec2& pos, FocusedItem focus, int tick /*= -1*/) { ImGui::PushStyleVar(ImGuiStyleVar_::ImGuiStyleVar_WindowBorderSize, 0); @@ -547,6 +628,9 @@ bool DSForLayers::render_button(const wchar_t btn_icon, const wchar_t btn_icon_h ImGui::SetCursorPos(ImVec2(0, 0)); const bool ret = m_imgui->image_button(g.HoveredWindow == g.CurrentWindow ? btn_icon_hovered : btn_icon, tooltip, false); + if (tick > 0 && tick == m_ctrl.GetActivePos() && g.HoveredWindow == g.CurrentWindow && g.IO.MouseClicked[1]) + m_show_edit_menu = true; + ImGuiPureWrap::end(); ImGui::PopStyleColor(2); @@ -814,7 +898,7 @@ std::string DSForLayers::get_tooltip(int tick/*=-1*/) "or Set ruler mode")) % "(Shift + G)").str(); } if (m_focus == fiColorBand) - return m_mode != SingleExtruder ? "" : + return m_mode != SingleExtruder || !can_edit() ? "" : _u8L("Edit current color - Right click the colored slider segment"); if (m_focus == fiSmartWipeTower) return _u8L("This is wipe tower layer"); @@ -884,7 +968,7 @@ std::string DSForLayers::get_tooltip(int tick/*=-1*/) }; tooltip += tick_code_it->type == ColorChange ? - (m_mode == SingleExtruder ? + (m_mode == SingleExtruder && tick_code_it->extruder==1 ? format(_u8L("Color change (\"%1%\")"), gcode(ColorChange)) : format(_u8L("Color change (\"%1%\") for Extruder %2%"), gcode(ColorChange), tick_code_it->extruder)) : tick_code_it->type == CustomGCode::PausePrint ? diff --git a/src/slic3r/GUI/DoubleSliderForLayers.hpp b/src/slic3r/GUI/DoubleSliderForLayers.hpp index 306a131402..a985994f42 100644 --- a/src/slic3r/GUI/DoubleSliderForLayers.hpp +++ b/src/slic3r/GUI/DoubleSliderForLayers.hpp @@ -31,8 +31,6 @@ enum FocusedItem { fiCogIcon, fiColorBand, fiActionIcon, - fiLowerThumb, - fiHigherThumb, fiSmartWipeTower, fiTick }; @@ -138,6 +136,7 @@ private: bool m_allow_editing { true }; bool m_show_estimated_times { false }; bool m_show_cog_menu { false }; + bool m_show_edit_menu { false }; DrawMode m_draw_mode { dmRegular }; Mode m_mode { SingleExtruder }; @@ -163,6 +162,7 @@ private: void draw_ticks(const ImRect& slideable_region); void render_menu(); void render_cog_menu(); + void render_edit_menu(); bool render_button(const wchar_t btn_icon, const wchar_t btn_icon_hovered, const std::string& label_id, const ImVec2& pos, FocusedItem focus, int tick = -1); void add_code_as_tick(Type type, int selected_extruder = -1); @@ -188,7 +188,7 @@ private: std::string m_selectable_color; void render_add_tick_menu(); - void render_multi_extruders_menu(); + bool render_multi_extruders_menu(bool switch_current_code = false); bool render_jump_to_window(const ImVec2& pos, double* active_value, double min_z, double max_z); void render_color_picker(); From 258882ca5a5f4be4d60cfe57dc35ddd1ab1825c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20=C5=A0ach?= Date: Wed, 15 May 2024 11:05:37 +0200 Subject: [PATCH 6/8] Fix SPE-2304. Rear seam not respecting paiting. If a rear seam was projected it was not respecting seam paiting, because it continued to search the points even if they had 'worse' point_type (e.g. common/blocker). Now the search is aborted if there is an enforcer and it is not picked. --- src/libslic3r/GCode/SeamAligned.cpp | 16 ++-------------- src/libslic3r/GCode/SeamChoice.cpp | 3 +++ src/libslic3r/GCode/SeamPerimeters.hpp | 13 +++++++++++++ src/libslic3r/Slicing.hpp | 1 + 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/libslic3r/GCode/SeamAligned.cpp b/src/libslic3r/GCode/SeamAligned.cpp index 209a5a85d2..936b600bb8 100644 --- a/src/libslic3r/GCode/SeamAligned.cpp +++ b/src/libslic3r/GCode/SeamAligned.cpp @@ -236,26 +236,14 @@ double VisibilityCalculator::get_angle_visibility_modifier( return -angle_smooth_weight; } -std::vector extract_points( - const Perimeters::Perimeter &perimeter, const Perimeters::PointType point_type -) { - std::vector result; - for (std::size_t i{0}; i < perimeter.positions.size(); ++i) { - if (perimeter.point_types[i] == point_type) { - result.push_back(perimeter.positions[i]); - } - } - return result; -} - std::vector get_starting_positions(const Shells::Shell<> &shell) { const Perimeters::Perimeter &perimeter{shell.front().boundary}; - std::vector enforcers{extract_points(perimeter, Perimeters::PointType::enforcer)}; + std::vector enforcers{Perimeters::extract_points(perimeter, Perimeters::PointType::enforcer)}; if (!enforcers.empty()) { return enforcers; } - std::vector common{extract_points(perimeter, Perimeters::PointType::common)}; + std::vector common{Perimeters::extract_points(perimeter, Perimeters::PointType::common)}; if (!common.empty()) { return common; } diff --git a/src/libslic3r/GCode/SeamChoice.cpp b/src/libslic3r/GCode/SeamChoice.cpp index 6db562e2a1..dfcb4b4b08 100644 --- a/src/libslic3r/GCode/SeamChoice.cpp +++ b/src/libslic3r/GCode/SeamChoice.cpp @@ -18,6 +18,9 @@ std::optional maybe_choose_seam_point( return seam_choice; } } + if (!Perimeters::extract_points(perimeter, point_type).empty()) { + return std::nullopt; + } } return std::nullopt; diff --git a/src/libslic3r/GCode/SeamPerimeters.hpp b/src/libslic3r/GCode/SeamPerimeters.hpp index aaebe6e5a6..21c50e0a98 100644 --- a/src/libslic3r/GCode/SeamPerimeters.hpp +++ b/src/libslic3r/GCode/SeamPerimeters.hpp @@ -185,6 +185,19 @@ inline std::size_t get_layer_count( } return layer_count; } + +inline std::vector extract_points( + const Perimeters::Perimeter &perimeter, const Perimeters::PointType point_type +) { + std::vector result; + for (std::size_t i{0}; i < perimeter.positions.size(); ++i) { + if (perimeter.point_types[i] == point_type) { + result.push_back(perimeter.positions[i]); + } + } + return result; +} + } // namespace Slic3r::Seams::Perimeters #endif // libslic3r_SeamPerimeters_hpp_ diff --git a/src/libslic3r/Slicing.hpp b/src/libslic3r/Slicing.hpp index 9e4b0499cc..f1f99e5952 100644 --- a/src/libslic3r/Slicing.hpp +++ b/src/libslic3r/Slicing.hpp @@ -13,6 +13,7 @@ #include #include +#include "Point.hpp" #include "libslic3r.h" #include "Utils.hpp" From b7ce546cfc43235291f4d94bc8cfe172aa591f5c Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 13 May 2024 16:57:19 +0200 Subject: [PATCH 7/8] Workaround for SPE-2295 - Crash when re-cutting with dowel connectors --- src/slic3r/GUI/Selection.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index e9fdef933a..a2955acc96 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -832,8 +832,14 @@ std::pair Selection::get_bounding_box_in_reference_s const GLVolume& vol = *get_volume(id); const Transform3d vol_world_rafo = vol.world_matrix(); const TriangleMesh* mesh = vol.convex_hull(); - if (mesh == nullptr) + if (mesh == nullptr) { + // workaround to avoid a crash, see spe-2295 -> Crash when re-cutting with dowel connectors + const int obj_id = vol.object_idx(); + const int vol_id = vol.volume_idx(); + if (m_model->objects[obj_id]->volumes.size() <= vol_id) + continue; mesh = &m_model->objects[vol.object_idx()]->volumes[vol.volume_idx()]->mesh(); + } assert(mesh != nullptr); for (const stl_vertex& v : mesh->its.vertices) { const Vec3d world_v = vol_world_rafo * v.cast(); From 80d35831faec3706c1047cdeaffbb6557bc0def2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20=C5=A0ach?= Date: Fri, 10 May 2024 17:04:36 +0200 Subject: [PATCH 8/8] Fix SPE-2297 - slowdown after overhang. The bug lies in the fact that SmoothPathCache comapare path attributes in `resolve_or_fit_split_with_seam`. For some paths it does the following: If attributes of paths are the same it merges the paths. Since the == operator of ExtrusionAttributes did not consider overhang_attributes in the comparison, some paths were merged even though they had different overhang_attributes. This led to the wrong overhang attributes being applied to some paths. Now the == operator of ExtrusionAttributes takes overhang_attributes into account and it fixes the issue. --- src/libslic3r/ExtrusionEntity.hpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/ExtrusionEntity.hpp b/src/libslic3r/ExtrusionEntity.hpp index 6238447c2c..a42fae5677 100644 --- a/src/libslic3r/ExtrusionEntity.hpp +++ b/src/libslic3r/ExtrusionEntity.hpp @@ -115,6 +115,19 @@ struct OverhangAttributes { float proximity_to_curled_lines; //value between 0 and 1 }; +inline bool operator==(const OverhangAttributes &lhs, const OverhangAttributes &rhs) { + if (std::abs(lhs.start_distance_from_prev_layer - rhs.start_distance_from_prev_layer) > std::numeric_limits::epsilon()) { + return false; + } + if (std::abs(lhs.end_distance_from_prev_layer - rhs.end_distance_from_prev_layer) > std::numeric_limits::epsilon()) { + return false; + } + if (std::abs(lhs.proximity_to_curled_lines - rhs.proximity_to_curled_lines) > std::numeric_limits::epsilon()) { + return false; + } + return true; +} + struct ExtrusionAttributes : ExtrusionFlow { ExtrusionAttributes() = default; @@ -132,7 +145,7 @@ struct ExtrusionAttributes : ExtrusionFlow inline bool operator==(const ExtrusionAttributes &lhs, const ExtrusionAttributes &rhs) { return static_cast(lhs) == static_cast(rhs) && - lhs.role == rhs.role; + lhs.role == rhs.role && lhs.overhang_attributes == rhs.overhang_attributes; } class ExtrusionPath : public ExtrusionEntity