diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index b5848cabac..0f85891ee2 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -398,7 +398,6 @@ void PrintObject::ironing() } } - void PrintObject::generate_support_spots() { if (this->set_started(posSupportSpotsSearch)) { @@ -421,8 +420,6 @@ void PrintObject::generate_support_spots() } } else { SupportSpotsGenerator::Issues issues = SupportSpotsGenerator::full_search(this); - //TODO fix -// if (!issues.supports_nedded.empty()) { auto obj_transform = this->trafo_centered(); for (ModelVolume *model_volume : this->model_object()->volumes) { if (model_volume->type() == ModelVolumeType::MODEL_PART) { @@ -438,7 +435,7 @@ void PrintObject::generate_support_spots() } model_volume->supported_facets.set(selector.selector); -#if 1 +#if 0 //DEBUG export indexed_triangle_set copy = model_volume->mesh().its; its_transform(copy, obj_transform * model_transformation); its_write_obj(copy, @@ -446,7 +443,6 @@ void PrintObject::generate_support_spots() #endif } } -// } } m_print->throw_if_canceled(); @@ -456,7 +452,6 @@ void PrintObject::generate_support_spots() } } - void PrintObject::generate_support_material() { if (this->set_started(posSupportMaterial)) { diff --git a/src/libslic3r/SupportSpotsGenerator.hpp b/src/libslic3r/SupportSpotsGenerator.hpp index 7be312bcb4..cc11c27c7e 100644 --- a/src/libslic3r/SupportSpotsGenerator.hpp +++ b/src/libslic3r/SupportSpotsGenerator.hpp @@ -8,7 +8,7 @@ namespace Slic3r { namespace SupportSpotsGenerator { struct Params { - // the algorithm should use the following units for all computations: distance [mm], mass [g], time [s], force [N] + // the algorithm should use the following units for all computations: distance [mm], mass [g], time [s], force [g*mm/s^2] const float bridge_distance = 12.0f; //mm const float bridge_distance_decrease_by_curvature_factor = 3.0f; // allowed bridge distance = bridge_distance / (this factor * (curvature / PI) ) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index 49e97ee1f1..36f48d0087 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -10,6 +10,8 @@ #include "slic3r/GUI/GUI_ObjectList.hpp" #include "slic3r/GUI/format.hpp" #include "slic3r/Utils/UndoRedo.hpp" +#include "libslic3r/Print.hpp" +#include "slic3r/GUI/MsgDialog.hpp" #include @@ -39,6 +41,7 @@ bool GLGizmoFdmSupports::on_init() { m_shortcut_key = WXK_CONTROL_L; + m_desc["auto_generate"] = _L("Auto-generate supports"); m_desc["clipping_of_view"] = _L("Clipping of view") + ": "; m_desc["reset_direction"] = _L("Reset direction"); m_desc["cursor_size"] = _L("Brush size") + ": "; @@ -91,7 +94,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l if (! m_c->selection_info()->model_object()) return; - const float approx_height = m_imgui->scaled(23.f); + const float approx_height = m_imgui->scaled(25.f); y = std::min(y, bottom_limit - approx_height); m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); @@ -153,6 +156,12 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l ImGui::Separator(); + bool generate = m_imgui->button(m_desc.at("auto_generate")); + if (generate) + auto_generate(); + + ImGui::Separator(); + float position_before_text_y = ImGui::GetCursorPos().y; ImGui::AlignTextToFramePadding(); m_imgui->text_wrapped(m_desc["highlight_by_angle"] + ":", autoset_slider_label_max_width); @@ -369,6 +378,50 @@ void GLGizmoFdmSupports::select_facets_by_angle(float threshold_deg, bool block) m_parent.set_as_dirty(); } +void GLGizmoFdmSupports::data_changed() +{ + GLGizmoPainterBase::data_changed(); + if (! m_c->selection_info()) + return; + + ModelObject* mo = m_c->selection_info()->model_object(); + if (mo && this->waiting_for_autogenerated_supports) { + get_data_from_backend(); + } +} + +void GLGizmoFdmSupports::get_data_from_backend() +{ + if (! has_backend_supports()) + return; + ModelObject* mo = m_c->selection_info()->model_object(); + + // find the respective PrintObject, we need a pointer to it + for (const PrintObject* po : m_parent.fff_print()->objects()) { + if (po->model_object()->id() == mo->id()) { + std::unordered_map mvs; + for (const ModelVolume* mv : po->model_object()->volumes) { + if (mv->is_model_part()) { + mvs.emplace(mv->id().id, mv); + } + } + // NOTE: Copying the data into ModelVolumes stops the background processing. + int mesh_id = -1.0f; + for (ModelVolume* mv : mo->volumes){ + if (mv->is_model_part()){ + mesh_id++; + mv->supported_facets.assign(mvs[mv->id().id]->supported_facets); + m_triangle_selectors[mesh_id]->deserialize(mv->supported_facets.get_data(), true); + m_triangle_selectors[mesh_id]->request_update_render_data(); + } + } + this->waiting_for_autogenerated_supports = false; + m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); + m_parent.set_as_dirty(); + + } + } +} void GLGizmoFdmSupports::update_model_object() const @@ -391,8 +444,6 @@ void GLGizmoFdmSupports::update_model_object() const } } - - void GLGizmoFdmSupports::update_from_model_object() { wxBusyCursor wait; @@ -417,6 +468,46 @@ void GLGizmoFdmSupports::update_from_model_object() } } +bool GLGizmoFdmSupports::has_backend_supports() const +{ + const ModelObject* mo = m_c->selection_info()->model_object(); + if (! mo) + return false; + + // find SlaPrintObject with this ID + for (const PrintObject* po : m_parent.fff_print()->objects()) { + if (po->model_object()->id() == mo->id()) + return po->is_step_done(posSupportSpotsSearch); + } + return false; +} + +void GLGizmoFdmSupports::reslice_FDM_supports(bool postpone_error_messages) const { + wxGetApp().CallAfter( + [this, postpone_error_messages]() { + wxGetApp().plater()->reslice_FFF_until_step(posSupportSpotsSearch, + *m_c->selection_info()->model_object(), postpone_error_messages); + }); +} + +void GLGizmoFdmSupports::auto_generate() +{ + ModelObject *mo = m_c->selection_info()->model_object(); + bool not_painted = std::all_of(mo->volumes.begin(), mo->volumes.end(), [](const ModelVolume* vol){ + return vol->type() != ModelVolumeType::MODEL_PART || vol->supported_facets.empty(); + }); + + MessageDialog dlg(GUI::wxGetApp().plater(), + _L("Autogeneration will erase all currently painted areas.") + "\n\n" + + _L("Are you sure you want to do it?") + "\n", + _L("Warning"), wxICON_WARNING | wxYES | wxNO); + + if (not_painted || dlg.ShowModal() == wxID_YES) { + Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Autogenerate support points")); + this->waiting_for_autogenerated_supports = true; + wxGetApp().CallAfter([this]() { reslice_FDM_supports(); }); + } +} PainterGizmoType GLGizmoFdmSupports::get_painter_type() const diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp index f4c21a174b..2820298b6f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp @@ -26,6 +26,7 @@ protected: private: bool on_init() override; + void data_changed() override; void update_model_object() const override; void update_from_model_object() override; @@ -41,8 +42,11 @@ private: std::map m_desc; + bool waiting_for_autogenerated_supports = false; bool has_backend_supports() const; void reslice_FDM_supports(bool postpone_error_messages = false) const; + void auto_generate(); + void get_data_from_backend(); };