diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index f8ba951c69..78dec96942 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -108,6 +108,8 @@ void GLCanvas3D::select_bed(int i) if (i == old_bed || i == -1) return; wxGetApp().plater()->canvas3D()->m_process->stop(); + m_sequential_print_clearance.m_evaluating = true; + reset_sequential_print_clearance(); // The stop call above schedules some events that would be processed after the switch. // Among else, on_process_completed would be called, which would stop slicing of @@ -908,6 +910,8 @@ void GLCanvas3D::SequentialPrintClearance::set_contours(const ContoursList& cont if (contours.empty()) return; + const Vec3d bed_offset = generate_fill ? s_multiple_beds.get_bed_translation(s_multiple_beds.get_active_bed()) : Vec3d::Zero(); + if (generate_fill) { GLModel::Geometry fill_data; fill_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3 }; @@ -921,7 +925,7 @@ void GLCanvas3D::SequentialPrintClearance::set_contours(const ContoursList& cont fill_data.reserve_vertices(fill_data.vertices_count() + triangulation.size()); fill_data.reserve_indices(fill_data.indices_count() + triangulation.size()); for (const Vec3d& v : triangulation) { - fill_data.add_vertex((Vec3f)(v.cast() + 0.0125f * Vec3f::UnitZ())); // add a small positive z to avoid z-fighting + fill_data.add_vertex((Vec3f)((bed_offset + v).cast() + 0.0125f * Vec3f::UnitZ())); // add a small positive z to avoid z-fighting ++vertices_counter; if (vertices_counter % 3 == 0) fill_data.add_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1); @@ -930,6 +934,8 @@ void GLCanvas3D::SequentialPrintClearance::set_contours(const ContoursList& cont m_fill.init_from(std::move(fill_data)); } + const Transform3d bed_transform = Geometry::translation_transform(bed_offset); + for (size_t i = 0; i < contours.contours.size(); ++i) { GLModel& model = m_contours.emplace_back(GLModel()); model.init_from(contours.contours[i], 0.025f); // add a small positive z to avoid z-fighting @@ -938,14 +944,14 @@ void GLCanvas3D::SequentialPrintClearance::set_contours(const ContoursList& cont if (contours.trafos.has_value()) { // create the requested instances for (const auto& instance : *contours.trafos) { - m_instances.emplace_back(instance.first, instance.second); + m_instances.emplace_back(instance.first, bed_transform * instance.second); } } else { // no instances have been specified // create one instance for every polygon for (size_t i = 0; i < contours.contours.size(); ++i) { - m_instances.emplace_back(i, Transform3f::Identity()); + m_instances.emplace_back(i, bed_transform); } } } @@ -963,9 +969,9 @@ void GLCanvas3D::SequentialPrintClearance::update_instances_trafos(const std::ve void GLCanvas3D::SequentialPrintClearance::render() { - const ColorRGBA FILL_COLOR = { 1.0f, 0.0f, 0.0f, 0.5f }; - const ColorRGBA NO_FILL_COLOR = { 1.0f, 1.0f, 1.0f, 0.75f }; - const ColorRGBA NO_FILL_EVALUATING_COLOR = { 1.0f, 1.0f, 0.0f, 1.0f }; + static const ColorRGBA FILL_COLOR = { 1.0f, 0.0f, 0.0f, 0.5f }; + static const ColorRGBA NO_FILL_COLOR = { 1.0f, 1.0f, 1.0f, 0.75f }; + static const ColorRGBA NO_FILL_EVALUATING_COLOR = { 1.0f, 1.0f, 0.0f, 1.0f }; if (m_contours.empty() || m_instances.empty()) return; @@ -1013,10 +1019,13 @@ void GLCanvas3D::SequentialPrintClearance::render() glsafe(::glLineWidth(2.0f)); #endif // !SLIC3R_OPENGL_ES + const ColorRGBA color = (!m_evaluating && !m_dragging && m_fill.is_initialized()) ? FILL_COLOR : + m_evaluating ? NO_FILL_EVALUATING_COLOR : NO_FILL_COLOR; + for (const auto& [id, trafo] : m_instances) { shader->set_uniform("view_model_matrix", camera.get_view_matrix() * trafo); assert(id < m_contours.size()); - m_contours[id].set_color((!m_evaluating && m_fill.is_initialized()) ? FILL_COLOR : m_evaluating ? NO_FILL_EVALUATING_COLOR : NO_FILL_COLOR); + m_contours[id].set_color(color); m_contours[id].render(); } @@ -3545,7 +3554,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) c == GLGizmosManager::EType::Scale || c == GLGizmosManager::EType::Rotate) { show_sinking_contours(); - if (current_printer_technology() == ptFFF && fff_print()->config().complete_objects) + if (_is_sequential_print_enabled()) update_sequential_clearance(true); } } @@ -3705,7 +3714,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_selection.setup_cache(); if (!evt.CmdDown()) m_mouse.drag.start_position_3D = m_mouse.scene_position; - m_sequential_print_clearance_first_displacement = true; + m_sequential_print_clearance.m_first_displacement = true; + if (_is_sequential_print_enabled()) + update_sequential_clearance(true); m_sequential_print_clearance.start_dragging(); } } @@ -3755,7 +3766,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) TransformationType trafo_type; trafo_type.set_relative(); m_selection.translate(cur_pos - m_mouse.drag.start_position_3D, trafo_type); - if (current_printer_technology() == ptFFF && fff_print()->config().complete_objects) + if (_is_sequential_print_enabled()) update_sequential_clearance(false); wxGetApp().obj_manipul()->set_dirty(); m_dirty = true; @@ -3834,6 +3845,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) else if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp()) { m_mouse.position = pos.cast(); + if (evt.LeftUp() && m_sequential_print_clearance.is_dragging()) + m_sequential_print_clearance.stop_dragging(); + if (m_layers_editing.state != LayersEditing::Unknown) { m_layers_editing.state = LayersEditing::Unknown; _stop_timer(); @@ -3844,7 +3858,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) s_virtual_bed_timer.Stop(); do_move(L("Move Object")); wxGetApp().obj_manipul()->set_dirty(); - m_sequential_print_clearance.stop_dragging(); // Let the plater know that the dragging finished, so a delayed refresh // of the scene with the background processing data should be performed. post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED)); @@ -4094,7 +4107,7 @@ void GLCanvas3D::do_move(const std::string& snapshot_type) post_event(SimpleEvent(EVT_GLCANVAS_WIPETOWER_TOUCHED)); } - if (current_printer_technology() == ptFFF && fff_print()->config().complete_objects) { + if (_is_sequential_print_enabled()) { update_sequential_clearance(true); m_sequential_print_clearance.m_evaluating = true; } @@ -4192,7 +4205,7 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type) if (!done.empty()) post_event(SimpleEvent(EVT_GLCANVAS_INSTANCE_ROTATED)); - if (current_printer_technology() == ptFFF && fff_print()->config().complete_objects) { + if (_is_sequential_print_enabled()) { update_sequential_clearance(true); m_sequential_print_clearance.m_evaluating = true; } @@ -4269,7 +4282,7 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type) if (!done.empty()) post_event(SimpleEvent(EVT_GLCANVAS_INSTANCE_SCALED)); - if (current_printer_technology() == ptFFF && fff_print()->config().complete_objects) { + if (_is_sequential_print_enabled()) { update_sequential_clearance(true); m_sequential_print_clearance.m_evaluating = true; } @@ -4529,7 +4542,7 @@ void GLCanvas3D::mouse_up_cleanup() void GLCanvas3D::update_sequential_clearance(bool force_contours_generation) { - if (current_printer_technology() != ptFFF || !fff_print()->config().complete_objects) + if (!_is_sequential_print_enabled()) return; if (m_layers_editing.is_enabled()) @@ -4591,7 +4604,7 @@ void GLCanvas3D::update_sequential_clearance(bool force_contours_generation) // calculates objects 2d hulls (see also: Print::sequential_print_horizontal_clearance_valid()) // this is done only the first time this method is called while moving the mouse, // the results are then cached for following displacements - if (force_contours_generation || m_sequential_print_clearance_first_displacement) { + if (force_contours_generation || m_sequential_print_clearance.m_first_displacement) { m_sequential_print_clearance.m_evaluating = false; m_sequential_print_clearance.m_hulls_2d_cache.clear(); const float shrink_factor = static_cast(scale_(0.5 * fff_print()->config().extruder_clearance_radius.value - EPSILON)); @@ -4640,7 +4653,7 @@ void GLCanvas3D::update_sequential_clearance(bool force_contours_generation) } set_sequential_print_clearance_contours(contours, false); - m_sequential_print_clearance_first_displacement = false; + m_sequential_print_clearance.m_first_displacement = false; } else { if (!m_sequential_print_clearance.empty()) { @@ -6121,7 +6134,7 @@ void GLCanvas3D::_render_selection() void GLCanvas3D::_render_sequential_clearance() { - if (current_printer_technology() != ptFFF || !fff_print()->config().complete_objects) + if (!_is_sequential_print_enabled()) return; if (m_layers_editing.is_enabled()) @@ -6246,10 +6259,8 @@ void GLCanvas3D::_render_overlays() if (m_layers_editing.last_object_id >= 0 && m_layers_editing.object_max_z() > 0.0f) m_layers_editing.render_overlay(*this); - const ConfigOptionBool* opt = dynamic_cast(m_config->option("complete_objects")); - bool sequential_print = opt != nullptr && opt->value; std::vector sorted_instances; - if (sequential_print) { + if (_is_sequential_print_enabled()) { for (ModelObject* model_object : m_model->objects) for (ModelInstance* model_instance : model_object->instances) { sorted_instances.emplace_back(model_instance); @@ -7065,6 +7076,11 @@ std::pair GLCanvas3D::_is_any_volume_outside() const return std::make_pair(false, nullptr); } +bool GLCanvas3D::_is_sequential_print_enabled() const +{ + return current_printer_technology() == ptFFF && fff_print()->config().complete_objects; +} + void GLCanvas3D::_update_selection_from_hover() { bool ctrl_pressed = wxGetKeyState(WXK_CONTROL); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 2f7fc33a31..23760bd1ea 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -628,6 +628,7 @@ private: std::vector> m_instances; bool m_evaluating{ false }; bool m_dragging{ false }; + bool m_first_displacement{ true }; std::vector> m_hulls_2d_cache; @@ -645,7 +646,6 @@ private: }; SequentialPrintClearance m_sequential_print_clearance; - bool m_sequential_print_clearance_first_displacement{ true }; struct ToolbarHighlighter { @@ -990,7 +990,7 @@ public: void reset_sequential_print_clearance() { m_sequential_print_clearance.m_evaluating = false; if (m_sequential_print_clearance.is_dragging()) - m_sequential_print_clearance_first_displacement = true; + m_sequential_print_clearance.m_first_displacement = true; else m_sequential_print_clearance.set_contours(ContoursList(), false); set_as_dirty(); @@ -999,6 +999,8 @@ public: void set_sequential_print_clearance_contours(const ContoursList& contours, bool generate_fill) { m_sequential_print_clearance.set_contours(contours, generate_fill); + if (generate_fill) + m_sequential_print_clearance.m_evaluating = false; set_as_dirty(); request_extra_frame(); } @@ -1117,6 +1119,7 @@ private: void _set_warning_notification(EWarning warning, bool state); std::pair _is_any_volume_outside() const; + bool _is_sequential_print_enabled() const; // updates the selection from the content of m_hover_volume_idxs void _update_selection_from_hover(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 946062f3a3..8669484e61 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2310,8 +2310,17 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool } std::vector warnings; std::string err = background_process.validate(&warnings); - if (!err.empty()) + if (!err.empty()) { + if (s_multiple_beds.get_number_of_beds() > 1 && printer_technology == ptFFF) { + // user changed bed seletion, + // sequential print clearance contours were changed too + GLCanvas3D* canvas = view3D->get_canvas3d(); + GLCanvas3D::ContoursList contours; + contours.contours = background_process.fff_print()->get_sequential_print_clearance_contours(); + canvas->set_sequential_print_clearance_contours(contours, true); + } return return_state; + } } if (! this->delayed_error_message.empty())