diff --git a/src/libslic3r/TriangleSelector.cpp b/src/libslic3r/TriangleSelector.cpp index 976e35391..52085b178 100644 --- a/src/libslic3r/TriangleSelector.cpp +++ b/src/libslic3r/TriangleSelector.cpp @@ -12,7 +12,7 @@ namespace Slic3r { #ifndef _NDEBUG bool TriangleSelector::verify_triangle_midpoints(const Triangle &tr) const { - for (int i = 0; i < 3; ++ i) { + for (int i = 0; i < 3; ++ i) { int v1 = tr.verts_idxs[i]; int v2 = tr.verts_idxs[next_idx_modulo(i, 3)]; int vmid = this->triangle_midpoint(tr, v1, v2); @@ -168,7 +168,7 @@ bool TriangleSelector::select_triangle(int facet_idx, EnforcerBlockerType type, for (int i = 0; i < 3; ++ i) neighbors(i) = neighbors_src.neighbor[i]; assert(this->verify_triangle_neighbors(m_triangles[facet_idx], neighbors)); - + if (! select_triangle_recursive(facet_idx, neighbors, type, triangle_splitting)) return false; @@ -249,11 +249,11 @@ int TriangleSelector::triangle_midpoint(const Triangle &tr, int vertexi, int ver assert(tr.verts_idxs[next_idx_modulo(edge, 3)] == vertexj); if (tr.number_of_split_sides() == 1) { - return edge == next_idx_modulo(tr.special_side(), 3) ? + return edge == next_idx_modulo(tr.special_side(), 3) ? m_triangles[tr.children[0]].verts_idxs[2] : this->triangle_midpoint(m_triangles[tr.children[edge == tr.special_side() ? 0 : 1]], vertexi, vertexj); } else if (tr.number_of_split_sides() == 2) { - return edge == next_idx_modulo(tr.special_side(), 3) ? + return edge == next_idx_modulo(tr.special_side(), 3) ? this->triangle_midpoint(m_triangles[tr.children[2]], vertexi, vertexj) : edge == tr.special_side() ? m_triangles[tr.children[0]].verts_idxs[1] : @@ -261,7 +261,7 @@ int TriangleSelector::triangle_midpoint(const Triangle &tr, int vertexi, int ver } else { assert(tr.number_of_split_sides() == 3); assert(tr.special_side() == 0); - return + return (edge == 0) ? m_triangles[tr.children[0]].verts_idxs[1] : (edge == 1) ? m_triangles[tr.children[1]].verts_idxs[2] : m_triangles[tr.children[2]].verts_idxs[2]; @@ -282,7 +282,7 @@ int TriangleSelector::triangle_midpoint_or_allocate(int itriangle, int vertexi, Vec3f c = 0.5f * (m_vertices[vertexi].v + m_vertices[vertexj].v); #ifdef EXPENSIVE_DEBUG_CHECKS // Verify that the vertex is really a new one. - auto it = std::find_if(m_vertices.begin(), m_vertices.end(), [this, c](const Vertex &v) { + auto it = std::find_if(m_vertices.begin(), m_vertices.end(), [this, c](const Vertex &v) { return v.ref_cnt > 0 && (v.v - c).norm() < EPSILON; }); assert(it == m_vertices.end()); #endif // EXPENSIVE_DEBUG_CHECKS @@ -736,7 +736,7 @@ TriangleSelector::TriangleSelector(const TriangleMesh& mesh) } -void TriangleSelector::reset(const EnforcerBlockerType reset_state) +void TriangleSelector::reset() { m_vertices.clear(); m_triangles.clear(); @@ -749,10 +749,10 @@ void TriangleSelector::reset(const EnforcerBlockerType reset_state) m_triangles.reserve(m_mesh->its.indices.size()); for (size_t i=0; iits.indices.size(); ++i) { const stl_triangle_vertex_indices& ind = m_mesh->its.indices[i]; - push_triangle(ind[0], ind[1], ind[2], i, reset_state); + push_triangle(ind[0], ind[1], ind[2], i); } m_orig_size_vertices = m_vertices.size(); - m_orig_size_indices = m_triangles.size(); + m_orig_size_indices = m_triangles.size(); } @@ -930,8 +930,8 @@ std::pair>, std::vector> TriangleSelector: // In case this is leaf, we better save information about its state. int n = int(tr.get_state()); if (n >= 3) { - assert(n <= 15); - if (n <= 15) { + assert(n <= 16); + if (n <= 16) { // Store "11" plus 4 bits of (n-3). data.second.insert(data.second.end(), { true, true }); n -= 3; @@ -963,9 +963,9 @@ std::pair>, std::vector> TriangleSelector: return out.data; } -void TriangleSelector::deserialize(const std::pair>, std::vector> &data, const EnforcerBlockerType init_state) +void TriangleSelector::deserialize(const std::pair>, std::vector> &data) { - reset(init_state); // dump any current state + reset(); // dump any current state // Vector to store all parents that have offsprings. struct ProcessingInfo { @@ -1058,7 +1058,7 @@ void TriangleSelector::deserialize(const std::pair>, std::vector> serialize() const; // Load serialized data. Assumes that correct mesh is loaded. - void deserialize(const std::pair>, std::vector> &data, const EnforcerBlockerType init_state = EnforcerBlockerType{0}); + void deserialize(const std::pair>, std::vector> &data); // For all triangles, remove the flag indicating that the triangle was selected by seed fill. void seed_fill_unselect_all_triangles(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index 0b6d7660b..e3af11468 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -58,6 +58,20 @@ static std::vector get_extruders_names() return extruders_out; } +static std::vector get_extruder_id_for_volumes(const ModelObject &model_object) +{ + std::vector extruders_idx; + extruders_idx.reserve(model_object.volumes.size()); + for (const ModelVolume *model_volume : model_object.volumes) { + if (!model_volume->is_model_part()) + continue; + + extruders_idx.emplace_back(model_volume->extruder_id()); + } + + return extruders_idx; +} + void GLGizmoMmuSegmentation::init_extruders_data() { m_original_extruders_names = get_extruders_names(); @@ -114,12 +128,15 @@ void GLGizmoMmuSegmentation::set_painter_gizmo_data(const Selection &selection) if (m_state != On) return; - int prev_extruders_count = int(m_original_extruders_colors.size()); + ModelObject *model_object = m_c->selection_info()->model_object(); + int prev_extruders_count = int(m_original_extruders_colors.size()); if (prev_extruders_count != wxGetApp().extruders_edited_cnt() || get_extruders_colors() != m_original_extruders_colors) { this->init_extruders_data(); // Reinitialize triangle selectors because of change of extruder count need also change the size of GLIndexedVertexArray if (prev_extruders_count != wxGetApp().extruders_edited_cnt()) this->init_model_triangle_selectors(); + } else if (model_object != nullptr && get_extruder_id_for_volumes(*model_object) != m_original_volumes_extruder_idxs) { + this->init_model_triangle_selectors(); } } @@ -280,8 +297,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott for (ModelVolume *mv : mo->volumes) { if (mv->is_model_part()) { ++idx; - size_t extruder_id = (mv->extruder_id() > 0) ? mv->extruder_id() - 1 : 0; - m_triangle_selectors[idx]->reset(EnforcerBlockerType(extruder_id)); + m_triangle_selectors[idx]->reset(); } } @@ -395,10 +411,11 @@ void GLGizmoMmuSegmentation::init_model_triangle_selectors() // This mesh does not account for the possible Z up SLA offset. const TriangleMesh *mesh = &mv->mesh(); - size_t extruder_id = (mv->extruder_id() > 0) ? mv->extruder_id() - 1 : 0; - m_triangle_selectors.emplace_back(std::make_unique(*mesh, m_modified_extruders_colors)); - m_triangle_selectors.back()->deserialize(mv->mmu_segmentation_facets.get_data(), EnforcerBlockerType(extruder_id)); + int extruder_idx = (mv->extruder_id() > 0) ? mv->extruder_id() - 1 : 0; + m_triangle_selectors.emplace_back(std::make_unique(*mesh, m_modified_extruders_colors, m_original_extruders_colors[size_t(extruder_idx)])); + m_triangle_selectors.back()->deserialize(mv->mmu_segmentation_facets.get_data()); } + m_original_volumes_extruder_idxs = get_extruder_id_for_volumes(*mo); } void GLGizmoMmuSegmentation::update_from_model_object() @@ -468,9 +485,10 @@ void TriangleSelectorMmuGui::render(ImGuiWrapper *imgui) assert(shader->get_name() == "gouraud"); for (size_t color_idx = 0; color_idx < m_iva_colors.size(); ++color_idx) { + const std::array &color_source = (color_idx == 0) ? m_default_volume_color : m_colors[color_idx - 1]; if (render_colors[color_idx]) { - std::array color = {float(m_colors[color_idx][0]) / 255.0f, float(m_colors[color_idx][1]) / 255.0f, - float(m_colors[color_idx][2]) / 255.0f, 1.f}; + std::array color = {float(color_source[0]) / 255.0f, float(color_source[1]) / 255.0f, + float(color_source[2]) / 255.0f, 1.f}; shader->set_uniform("uniform_color", color); m_iva_colors[color_idx].render(); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp index 0d28da252..811e4cd28 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp @@ -7,9 +7,10 @@ namespace Slic3r::GUI { class TriangleSelectorMmuGui : public TriangleSelectorGUI { public: - explicit TriangleSelectorMmuGui(const TriangleMesh& mesh, const std::vector> &colors) - : TriangleSelectorGUI(mesh), m_colors(colors) { - m_iva_colors = std::vector(colors.size()); + explicit TriangleSelectorMmuGui(const TriangleMesh& mesh, const std::vector> &colors, const std::array &default_volume_color) + : TriangleSelectorGUI(mesh), m_colors(colors), m_default_volume_color(default_volume_color) { + // Plus 1 is because the first position is allocated for non-painted triangles. + m_iva_colors = std::vector(colors.size() + 1); } ~TriangleSelectorMmuGui() override = default; @@ -19,7 +20,8 @@ public: private: const std::vector> &m_colors; - std::vector m_iva_colors; + std::vector m_iva_colors; + const std::array m_default_volume_color; }; class GLGizmoMmuSegmentation : public GLGizmoPainterBase @@ -37,8 +39,8 @@ protected: std::array get_cursor_sphere_left_button_color() const override; std::array get_cursor_sphere_right_button_color() const override; - EnforcerBlockerType get_left_button_state_type() const override { return EnforcerBlockerType(m_first_selected_extruder_idx); } - EnforcerBlockerType get_right_button_state_type() const override { return EnforcerBlockerType(m_second_selected_extruder_idx); } + EnforcerBlockerType get_left_button_state_type() const override { return EnforcerBlockerType(m_first_selected_extruder_idx + 1); } + EnforcerBlockerType get_right_button_state_type() const override { return EnforcerBlockerType(m_second_selected_extruder_idx + 1); } void on_render_input_window(float x, float y, float bottom_limit) override; std::string on_get_name() const override; @@ -52,6 +54,7 @@ protected: std::vector m_original_extruders_names; std::vector> m_original_extruders_colors; std::vector> m_modified_extruders_colors; + std::vector m_original_volumes_extruder_idxs; private: bool on_init() override;