From 37f5bfc2cd58ab751b45d8c307253529dd1778db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20=C5=A0ach?= Date: Mon, 9 Dec 2024 17:58:09 +0100 Subject: [PATCH] Disable SLA autoslicing page - Also set instances to unprintable for SLA instead of removing them from the model --- src/libslic3r/MultipleBeds.cpp | 50 +++++++++- src/libslic3r/MultipleBeds.hpp | 11 +-- src/slic3r/GUI/GLCanvas3D.cpp | 55 ++++++----- src/slic3r/GUI/Gizmos/GLGizmoSlaBase.cpp | 1 + src/slic3r/GUI/Plater.cpp | 115 ++++++++++++++--------- src/slic3r/GUI/Plater.hpp | 1 + src/slic3r/GUI/Sidebar.cpp | 5 + 7 files changed, 163 insertions(+), 75 deletions(-) diff --git a/src/libslic3r/MultipleBeds.cpp b/src/libslic3r/MultipleBeds.cpp index a40606d76a..66847e28d4 100644 --- a/src/libslic3r/MultipleBeds.cpp +++ b/src/libslic3r/MultipleBeds.cpp @@ -208,7 +208,7 @@ void restore_object_instances(Model& model, const ObjectInstances &object_instan model.objects = objects; } -void with_single_bed_model(Model &model, const int bed_index, const std::function &callable) { +void with_single_bed_model_fff(Model &model, const int bed_index, const std::function &callable) { const InstanceOffsets original_offssets{MultipleBedsUtils::get_instance_offsets(model)}; const ObjectInstances original_objects{get_object_instances(model)}; const int original_bed{s_multiple_beds.get_active_bed()}; @@ -224,6 +224,44 @@ void with_single_bed_model(Model &model, const int bed_index, const std::functio callable(); } +using InstancesPrintability = std::vector; + +InstancesPrintability get_instances_printability(const Model &model) { + InstancesPrintability result; + for (ModelObject* mo : model.objects) { + for (ModelInstance* mi : mo->instances) { + result.emplace_back(mi->printable); + } + } + return result; +} + +void restore_instances_printability(Model& model, const InstancesPrintability &printability) +{ + size_t i = 0; + for (ModelObject* mo : model.objects) { + for (ModelInstance* mi : mo->instances) { + mi->printable = printability[i++]; + } + } +} + +void with_single_bed_model_sla(Model &model, const int bed_index, const std::function &callable) { + const InstanceOffsets original_offssets{get_instance_offsets(model)}; + const InstancesPrintability original_printability{get_instances_printability(model)}; + const int original_bed{s_multiple_beds.get_active_bed()}; + Slic3r::ScopeGuard guard([&]() { + restore_instance_offsets(model, original_offssets); + restore_instances_printability(model, original_printability); + s_multiple_beds.set_active_bed(original_bed); + }); + + s_multiple_beds.move_from_bed_to_first_bed(model, bed_index); + s_multiple_beds.set_instances_outside_outside_bed_unprintable(model, bed_index); + s_multiple_beds.set_active_bed(bed_index); + callable(); +} + } bool MultipleBeds::is_instance_on_bed(const ObjectID id, const int bed_index) const @@ -252,6 +290,16 @@ void MultipleBeds::remove_instances_outside_outside_bed(Model& model, const int ), model.objects.end()); } +void MultipleBeds::set_instances_outside_outside_bed_unprintable(Model& model, const int bed_index) const { + for (ModelObject* mo : model.objects) { + for (ModelInstance* mi : mo->instances) { + if (!this->is_instance_on_bed(mi->id(), bed_index)) { + mi->printable = false; + } + } + } +} + void MultipleBeds::move_from_bed_to_first_bed(Model& model, const int bed_index) const { if (bed_index < 0 || bed_index >= MAX_NUMBER_OF_BEDS) { diff --git a/src/libslic3r/MultipleBeds.hpp b/src/libslic3r/MultipleBeds.hpp index 92994f645e..9f70bcaa9f 100644 --- a/src/libslic3r/MultipleBeds.hpp +++ b/src/libslic3r/MultipleBeds.hpp @@ -51,6 +51,7 @@ public: void set_active_bed(int i); void remove_instances_outside_outside_bed(Model& model, const int bed) const; + void set_instances_outside_outside_bed_unprintable(Model& model, const int bed_index) const; // Sets !printable to all instances outside the active bed. void move_from_bed_to_first_bed(Model& model, const int bed) const; @@ -113,14 +114,8 @@ ObjectInstances get_object_instances(const Model& model); void restore_instance_offsets(Model& model, const InstanceOffsets &offsets); void restore_object_instances(Model& model, const ObjectInstances &object_instances); - -/** -For each print apply call do: -- move all instances according to their active bed -- apply -- move all instances back to their respective beds -*/ -void with_single_bed_model(Model &model, const int bed_index, const std::function &callable); +void with_single_bed_model_fff(Model &model, const int bed_index, const std::function &callable); +void with_single_bed_model_sla(Model &model, const int bed_index, const std::function &callable); } } // namespace Slic3r diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 151c904e61..618c4b4549 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -6575,9 +6575,9 @@ enum class PrintStatus { std::string get_status_text(PrintStatus status) { switch(status) { - case PrintStatus::idle: return "Idle"; - case PrintStatus::running: return "Running"; - case PrintStatus::finished: return "Finished"; + case PrintStatus::idle: return _u8L("Unsliced"); + case PrintStatus::running: return _u8L("Slicing..."); + case PrintStatus::finished: return _u8L("Sliced"); } return {}; } @@ -6601,7 +6601,7 @@ bool bed_selector_thumbnail( const float side, const float border, const GLuint texture_id, - const PrintStatus status + const std::optional status ) { ImGuiWindow* window = GImGui->CurrentWindow; const ImVec2 current_position = GImGui->CurrentWindow->DC.CursorPos; @@ -6615,16 +6615,18 @@ bool bed_selector_thumbnail( border )}; - const std::string icon{get_status_icon(status)}; + if (status) { + const std::string icon{get_status_icon(*status)}; - window->DrawList->AddText( - GImGui->Font, - GImGui->FontSize, - state_pos, - ImGui::GetColorU32(ImGuiCol_Text), - icon.c_str(), - icon.c_str() + icon.size() - ); + window->DrawList->AddText( + GImGui->Font, + GImGui->FontSize, + state_pos, + ImGui::GetColorU32(ImGuiCol_Text), + icon.c_str(), + icon.c_str() + icon.size() + ); + } return clicked; } @@ -6673,11 +6675,14 @@ void Slic3r::GUI::GLCanvas3D::_render_bed_selector() bool clicked = false; - PrintStatus print_status{PrintStatus::idle}; - if (wxGetApp().plater()->get_fff_prints()[i]->finished()) { - print_status = PrintStatus::finished; - } else if (m_process->fff_print() == wxGetApp().plater()->get_fff_prints()[i].get() && m_process->running()) { - print_status = PrintStatus::running; + std::optional print_status; + if (current_printer_technology() == ptFFF) { + print_status = PrintStatus::idle; + if (wxGetApp().plater()->get_fff_prints()[i]->finished()) { + print_status = PrintStatus::finished; + } else if (m_process->fff_print() == wxGetApp().plater()->get_fff_prints()[i].get() && m_process->running()) { + print_status = PrintStatus::running; + } } if (!previous_print_status[i] || print_status != previous_print_status[i]) { @@ -6710,9 +6715,12 @@ void Slic3r::GUI::GLCanvas3D::_render_bed_selector() if (empty) ImGui::PopItemFlag(); - const std::string status_text{get_status_text(print_status)}; - if (ImGui::IsItemHovered()) - ImGui::SetTooltip("%s", status_text.c_str()); + if (print_status) { + const std::string status_text{get_status_text(*print_status)}; + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("%s", status_text.c_str()); + } + } }; ImGuiWrapper& imgui = *wxGetApp().imgui(); @@ -6736,7 +6744,10 @@ void Slic3r::GUI::GLCanvas3D::_render_bed_selector() ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2()); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, btn_border); - if (slice_all_beds_button(s_multiple_beds.is_autoslicing(), btn_size, btn_padding)) { + if ( + current_printer_technology() == ptFFF && + slice_all_beds_button(s_multiple_beds.is_autoslicing(), btn_size, btn_padding) + ) { if (!s_multiple_beds.is_autoslicing()) { s_multiple_beds.start_autoslice([this](int i, bool user) { this->select_bed(i, user); }); wxGetApp().sidebar().switch_to_autoslicing_mode(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaBase.cpp index ffc49784d3..d18c047fbd 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaBase.cpp @@ -94,6 +94,7 @@ void GLGizmoSlaBase::update_volumes() const int object_idx = m_parent.get_selection().get_object_idx(); const int instance_idx = m_parent.get_selection().get_instance_idx(); + const Geometry::Transformation& inst_trafo = po->model_object()->instances[instance_idx]->get_transformation(); const double current_elevation = po->get_current_elevation(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index bf20fa0aa3..8d91794690 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -563,6 +563,7 @@ struct Plater::priv void generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, Camera::EType camera_type); ThumbnailsList generate_thumbnails(const ThumbnailsParams& params, Camera::EType camera_type); + void regenerate_thumbnails(); void bring_instance_forward() const; @@ -2162,25 +2163,64 @@ void Plater::priv::process_validation_warning(const std::vector& wa } } -std::array apply_to_inactive_beds( +std::vector apply_to_inactive_beds( Model &model, std::vector> &prints, const DynamicPrintConfig &config ) { - std::array result; + std::vector result(MAX_NUMBER_OF_BEDS); for (std::size_t bed_index{0}; bed_index < prints.size(); ++bed_index) { const std::unique_ptr &print{prints[bed_index]}; if (!print || bed_index == s_multiple_beds.get_active_bed()) { continue; } - using MultipleBedsUtils::with_single_bed_model; - with_single_bed_model(model, bed_index, [&](){ + using MultipleBedsUtils::with_single_bed_model_fff; + with_single_bed_model_fff(model, bed_index, [&](){ result[bed_index] = print->apply(model, config); }); } return result; } +void Plater::priv::regenerate_thumbnails() { + const int num{s_multiple_beds.get_number_of_beds()}; + if (num <= 1 || num > MAX_NUMBER_OF_BEDS) { + return; + } + + ThumbnailData data; + ThumbnailsParams params; + params.parts_only = true; + params.printable_only = true; + params.show_bed = true; + params.transparent_background = true; + int w = 100, h = 100; + + int curr_bound_texture = 0; + glsafe(glGetIntegerv(GL_TEXTURE_BINDING_2D, &curr_bound_texture)); + int curr_unpack_alignment = 0; + glsafe(glGetIntegerv(GL_UNPACK_ALIGNMENT, &curr_unpack_alignment)); + glsafe(glPixelStorei(GL_UNPACK_ALIGNMENT, 1)); + glsafe(glDeleteTextures(s_bed_selector_thumbnail_texture_ids.size(), s_bed_selector_thumbnail_texture_ids.data())); + s_bed_selector_thumbnail_changed.fill(false); + + s_bed_selector_thumbnail_texture_ids.resize(num); + glsafe(glGenTextures(num, s_bed_selector_thumbnail_texture_ids.data())); + for (int i = 0; i < num; ++i) { + s_multiple_beds.set_thumbnail_bed_idx(i); + generate_thumbnail(data, w, h, params, GUI::Camera::EType::Ortho); + s_multiple_beds.set_thumbnail_bed_idx(-1); + glsafe(glBindTexture(GL_TEXTURE_2D, s_bed_selector_thumbnail_texture_ids[i])); + glsafe(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); + glsafe(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); + glsafe(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0)); + glsafe(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, static_cast(w), static_cast(h), 0, GL_RGBA, GL_UNSIGNED_BYTE, data.pixels.data())); + s_bed_selector_thumbnail_changed[i] = true; + } + glsafe(glBindTexture(GL_TEXTURE_2D, curr_bound_texture)); + glsafe(glPixelStorei(GL_UNPACK_ALIGNMENT, curr_unpack_alignment)); +} + // Update background processing thread from the current config and Model. // Returns a bitmask of UpdateBackgroundProcessReturnState. unsigned int Plater::priv::update_background_process(bool force_validation, bool postpone_error_messages) @@ -2236,16 +2276,29 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool Print::ApplyStatus invalidated{Print::ApplyStatus::APPLY_STATUS_INVALIDATED}; bool was_running = background_process.running(); - using MultipleBedsUtils::with_single_bed_model; + using MultipleBedsUtils::with_single_bed_model_fff; + using MultipleBedsUtils::with_single_bed_model_sla; - std::array apply_statuses{ - apply_to_inactive_beds(q->model(), q->p->fff_prints, full_config) + std::vector apply_statuses{ + printer_technology == ptFFF ? + apply_to_inactive_beds(q->model(), q->p->fff_prints, full_config) : + std::vector(1) }; - with_single_bed_model(q->model(), s_multiple_beds.get_active_bed(), [&](){ - // Apply new config to the possibly running background task. - invalidated = background_process.apply(q->model(), full_config); - apply_statuses[s_multiple_beds.get_active_bed()] = invalidated; - }); + + // Apply new config to the possibly running background task. + if (printer_technology == ptFFF) { + with_single_bed_model_fff(q->model(), s_multiple_beds.get_active_bed(), [&](){ + invalidated = background_process.apply(q->model(), full_config); + apply_statuses[s_multiple_beds.get_active_bed()] = invalidated; + }); + } else if (printer_technology == ptSLA) { + with_single_bed_model_sla(q->model(), s_multiple_beds.get_active_bed(), [&](){ + invalidated = background_process.apply(q->model(), full_config); + apply_statuses[0] = invalidated; + }); + } else { + throw std::runtime_error{"Ivalid printer technology!"}; + } const bool any_status_changed{std::any_of( apply_statuses.begin(), @@ -2260,38 +2313,8 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool } // If current bed was invalidated, update thumbnails for all beds: - if (int num = s_multiple_beds.get_number_of_beds(); num > 1 && any_status_changed) { - ThumbnailData data; - ThumbnailsParams params; - params.parts_only = true; - params.printable_only = true; - params.show_bed = true; - params.transparent_background = true; - int w = 100, h = 100; - - int curr_bound_texture = 0; - glsafe(glGetIntegerv(GL_TEXTURE_BINDING_2D, &curr_bound_texture)); - int curr_unpack_alignment = 0; - glsafe(glGetIntegerv(GL_UNPACK_ALIGNMENT, &curr_unpack_alignment)); - glsafe(glPixelStorei(GL_UNPACK_ALIGNMENT, 1)); - glsafe(glDeleteTextures(s_bed_selector_thumbnail_texture_ids.size(), s_bed_selector_thumbnail_texture_ids.data())); - s_bed_selector_thumbnail_changed.fill(false); - - s_bed_selector_thumbnail_texture_ids.resize(num); - glsafe(glGenTextures(num, s_bed_selector_thumbnail_texture_ids.data())); - for (int i = 0; i < num; ++i) { - s_multiple_beds.set_thumbnail_bed_idx(i); - generate_thumbnail(data, w, h, params, GUI::Camera::EType::Ortho); - s_multiple_beds.set_thumbnail_bed_idx(-1); - glsafe(glBindTexture(GL_TEXTURE_2D, s_bed_selector_thumbnail_texture_ids[i])); - glsafe(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); - glsafe(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); - glsafe(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0)); - glsafe(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, static_cast(w), static_cast(h), 0, GL_RGBA, GL_UNSIGNED_BYTE, data.pixels.data())); - s_bed_selector_thumbnail_changed[i] = true; - } - glsafe(glBindTexture(GL_TEXTURE_2D, curr_bound_texture)); - glsafe(glPixelStorei(GL_UNPACK_ALIGNMENT, curr_unpack_alignment)); + if (any_status_changed) { + regenerate_thumbnails(); } // Just redraw the 3D canvas without reloading the scene to consume the update of the layer height profile. @@ -4685,6 +4708,10 @@ void Plater::object_list_changed() p->object_list_changed(); } +void Plater::regenerate_thumbnails() { + p->regenerate_thumbnails(); +} + std::vector Plater::load_files(const std::vector& input_files, bool load_model, bool load_config, bool imperial_units /*= false*/) { return p->load_files(input_files, load_model, load_config, imperial_units); } // To be called when providing a list of files to the GUI slic3r on command line. diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 659cd85351..37c229721c 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -122,6 +122,7 @@ public: void reload_print(); void object_list_changed(); void generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, Camera::EType camera_type); + void regenerate_thumbnails(); std::vector load_files(const std::vector& input_files, bool load_model = true, bool load_config = true, bool imperial_units = false); // To be called when providing a list of files to the GUI slic3r on command line. diff --git a/src/slic3r/GUI/Sidebar.cpp b/src/slic3r/GUI/Sidebar.cpp index a687617a87..3476a97507 100644 --- a/src/slic3r/GUI/Sidebar.cpp +++ b/src/slic3r/GUI/Sidebar.cpp @@ -32,6 +32,7 @@ #include #include #include // IWYU pragma: keep +#include "libslic3r/MultipleBeds.hpp" #include "wx/generic/stattextg.h" #ifdef _WIN32 #include @@ -758,6 +759,10 @@ void Sidebar::on_select_preset(wxCommandEvent& evt) * and for SLA presets they should be deleted */ m_object_list->update_object_list_by_printer_technology(); + s_multiple_beds.stop_autoslice(false); + this->switch_from_autoslicing_mode(); + this->m_plater->regenerate_thumbnails(); + this->m_plater->update(); } #ifdef __WXMSW__