From c9b3f29c5ba07e5de63d056eeee4e41e004c0c67 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 9 Dec 2024 10:00:58 +0100 Subject: [PATCH] Added progress bar and cancellation into UI, seq arrange is now executed from the main toolbar --- resources/localization/list.txt | 1 + src/slic3r/CMakeLists.txt | 2 + src/slic3r/GUI/ArrangeHelper.cpp | 46 +++++++++++++++------ src/slic3r/GUI/ArrangeHelper.hpp | 28 ++++++++++++- src/slic3r/GUI/GLCanvas3D.cpp | 13 +----- src/slic3r/GUI/Jobs/SeqArrangeJob.cpp | 57 +++++++++++++++++++++++++++ src/slic3r/GUI/Jobs/SeqArrangeJob.hpp | 30 ++++++++++++++ src/slic3r/GUI/Plater.cpp | 11 +++++- 8 files changed, 162 insertions(+), 26 deletions(-) create mode 100644 src/slic3r/GUI/Jobs/SeqArrangeJob.cpp create mode 100644 src/slic3r/GUI/Jobs/SeqArrangeJob.hpp diff --git a/resources/localization/list.txt b/resources/localization/list.txt index 1e3f94b9f8..849aff0267 100644 --- a/resources/localization/list.txt +++ b/resources/localization/list.txt @@ -79,6 +79,7 @@ src/slic3r/GUI/GUI_Preview.cpp src/slic3r/GUI/HintNotification.cpp src/slic3r/GUI/ImGuiWrapper.cpp src/slic3r/GUI/Jobs/ArrangeJob2.cpp +src/slic3r/GUI/Jobs/SeqArrangeJob.cpp src/slic3r/GUI/Jobs/EmbossJob.cpp src/slic3r/GUI/Jobs/PlaterWorker.hpp src/slic3r/GUI/Jobs/RotoptimizeJob.hpp diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 878c154c57..739b6032bb 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -250,6 +250,8 @@ set(SLIC3R_GUI_SOURCES GUI/Jobs/PlaterWorker.hpp GUI/Jobs/ArrangeJob2.hpp GUI/Jobs/ArrangeJob2.cpp + GUI/Jobs/SeqArrangeJob.hpp + GUI/Jobs/SeqArrangeJob.cpp GUI/Jobs/CreateFontNameImageJob.cpp GUI/Jobs/CreateFontNameImageJob.hpp GUI/Jobs/CreateFontStyleImagesJob.cpp diff --git a/src/slic3r/GUI/ArrangeHelper.cpp b/src/slic3r/GUI/ArrangeHelper.cpp index 48141d99a1..69e42afc06 100644 --- a/src/slic3r/GUI/ArrangeHelper.cpp +++ b/src/slic3r/GUI/ArrangeHelper.cpp @@ -6,7 +6,6 @@ #include -#include "libseqarrange/seq_interface.hpp" namespace Slic3r { @@ -79,17 +78,36 @@ static std::vector get_objects_to_print(const Model& void arrange_model_sequential(Model& model) { - Sequential::PrinterGeometry printer_geometry = get_printer_geometry(); - Sequential::SolverConfiguration solver_config = get_solver_config(printer_geometry); - std::vector objects = get_objects_to_print(model, printer_geometry); - - // Everything ready - let libseqarrange do the actual arrangement. - std::vector plates = - Sequential::schedule_ObjectsForSequentialPrint( - solver_config, - printer_geometry, - objects); + SeqArrange seq_arrange(model); + seq_arrange.process_seq_arrange([](int) {}); + seq_arrange.apply_seq_arrange(model); +} + + +SeqArrange::SeqArrange(const Model& model) +{ + m_printer_geometry = get_printer_geometry(); + m_solver_configuration = get_solver_config(m_printer_geometry); + m_objects = get_objects_to_print(model, m_printer_geometry); + +} + + + +void SeqArrange::process_seq_arrange(std::function progress_fn) +{ + m_plates = + Sequential::schedule_ObjectsForSequentialPrint( + m_solver_configuration, + m_printer_geometry, + m_objects, progress_fn); +} + + + +void SeqArrange::apply_seq_arrange(Model& model) const +{ // Extract the result and move the objects in Model accordingly. struct MoveData { Sequential::ScheduledObject scheduled_object; @@ -102,7 +120,7 @@ void arrange_model_sequential(Model& model) // Now iterate through all the files, read the data and move the objects accordingly. // Save the move data from this file to move_data_all. size_t bed_idx = 0; - for (const Sequential::ScheduledPlate& plate : plates) { + for (const Sequential::ScheduledPlate& plate : m_plates) { Vec3d bed_offset = s_multiple_beds.get_bed_translation(bed_idx); // Iterate the same way as when exporting. for (ModelObject* mo : model.objects) { @@ -130,6 +148,10 @@ void arrange_model_sequential(Model& model) + + + + bool check_seq_printability(const Model& model) { Sequential::PrinterGeometry printer_geometry = get_printer_geometry(); diff --git a/src/slic3r/GUI/ArrangeHelper.hpp b/src/slic3r/GUI/ArrangeHelper.hpp index 953babe43e..f602cefddb 100644 --- a/src/slic3r/GUI/ArrangeHelper.hpp +++ b/src/slic3r/GUI/ArrangeHelper.hpp @@ -1,11 +1,37 @@ #ifndef slic3r_Arrange_Helper_hpp #define slic3r_Arrange_Helper_hpp -class Model; +#include "libseqarrange/seq_interface.hpp" + + namespace Slic3r { + + class Model; + void arrange_model_sequential(Model& model); bool check_seq_printability(const Model& model); + + + // This is just a helper class to collect data for seq. arrangement, running the arrangement + // and applying the results to model. It is here so the processing itself can be offloaded + // into a separate thread without copying the Model or sharing it with UI thread. + class SeqArrange { + public: + explicit SeqArrange(const Model& model); + void process_seq_arrange(std::function progress_fn); + void apply_seq_arrange(Model& model) const; + + private: + // Following three are inputs, filled in by the constructor. + Sequential::PrinterGeometry m_printer_geometry; + Sequential::SolverConfiguration m_solver_configuration; + std::vector m_objects; + + // This is the output, filled in by process_seq_arrange. + std::vector m_plates; + }; + } #endif // slic3r_Arrange_Helper_hpp \ No newline at end of file diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 4848105926..1b07ecb7e8 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2223,23 +2223,14 @@ void GLCanvas3D::render() { // This is just temporary pipe to export data to the separate arrange algorithm // and importing the result back. TESTING ONLY !!! - ImGui::Begin("TESTING ONLY (arrange)"); - if (ImGui::Button("Do sequential arrange")) { - arrange_model_sequential(wxGetApp().plater()->model()); - reload_scene(true, true); - wxGetApp().obj_list()->update_after_undo_redo(); - } - static auto time_start = std::chrono::high_resolution_clock::now(); auto time_now = std::chrono::high_resolution_clock::now(); int time_limit_s = 1; static bool last_res = 0; bool valid = std::chrono::duration_cast(time_now - time_start).count() < time_limit_s; - ImGui::Text(""); - ImGui::Separator(); - ImGui::Text(""); - if (ImGui::Button("Test:")) { + ImGui::Begin("TESTING ONLY (arrange)"); + if (ImGui::Button("Test seq printability:")) { last_res = check_seq_printability(wxGetApp().plater()->model()); time_start = std::chrono::high_resolution_clock::now(); } diff --git a/src/slic3r/GUI/Jobs/SeqArrangeJob.cpp b/src/slic3r/GUI/Jobs/SeqArrangeJob.cpp new file mode 100644 index 0000000000..663096712f --- /dev/null +++ b/src/slic3r/GUI/Jobs/SeqArrangeJob.cpp @@ -0,0 +1,57 @@ +#include "SeqArrangeJob.hpp" + +#include "slic3r/GUI/ArrangeHelper.hpp" +#include "slic3r/GUI/GLCanvas3D.hpp" +#include "slic3r/GUI/GUI_App.hpp" +#include "slic3r/GUI/GUI_ObjectList.hpp" +#include "slic3r/GUI/I18N.hpp" +#include "slic3r/GUI/Plater.hpp" + + + + +namespace Slic3r { namespace GUI { + + +SeqArrangeJob::SeqArrangeJob(const Model& model) +{ + m_seq_arrange.reset(new SeqArrange(model)); +} + + +void SeqArrangeJob::process(Ctl& ctl) +{ + class SeqArrangeJobException : std::exception {}; + + try { + m_seq_arrange->process_seq_arrange([&](int progress) { + ctl.update_status(progress, _u8L("Arranging for sequential print")); + if (ctl.was_canceled()) + throw SeqArrangeJobException(); + } + ); + } catch (const SeqArrangeJobException&) { + // The task was canceled. Just make sure that the progress notification disappears. + ctl.update_status(100, ""); + } +} + + + +void SeqArrangeJob::finalize(bool canceled, std::exception_ptr&) +{ + // If the task was cancelled, the stopping exception was already caught + // in 'process' function. Let any other exception propagate further. + if (! canceled) { + m_seq_arrange->apply_seq_arrange(wxGetApp().model()); + wxGetApp().plater()->canvas3D()->reload_scene(true, true); + wxGetApp().obj_list()->update_after_undo_redo(); + } + m_seq_arrange.reset(); +} + + + + +} // namespace GUI +} // namespace Slic3r diff --git a/src/slic3r/GUI/Jobs/SeqArrangeJob.hpp b/src/slic3r/GUI/Jobs/SeqArrangeJob.hpp new file mode 100644 index 0000000000..8ae2a284e2 --- /dev/null +++ b/src/slic3r/GUI/Jobs/SeqArrangeJob.hpp @@ -0,0 +1,30 @@ +#ifndef SEQARRANGEJOB_HPP +#define SEQARRANGEJOB_HPP + +#include "Job.hpp" + +namespace Slic3r { + +class Model; + + +class SeqArrange; + +namespace GUI { + + +class SeqArrangeJob : public Job +{ +public: + explicit SeqArrangeJob(const Model& model); + virtual void process(Ctl &ctl) override; + virtual void finalize(bool /*canceled*/, std::exception_ptr&) override; + +private: + std::unique_ptr m_seq_arrange; +}; + +} // namespace GUI +} // namespace Slic3r + +#endif // ARRANGEJOB2_HPP diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 5184d4d708..dbc6ce0c62 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -106,6 +106,7 @@ #include "ConfigWizardWebViewPage.hpp" #include "Jobs/RotoptimizeJob.hpp" +#include "Jobs/SeqArrangeJob.hpp" #include "Jobs/SLAImportJob.hpp" #include "Jobs/SLAImportDialog.hpp" #include "Jobs/NotificationProgressIndicator.hpp" @@ -7151,9 +7152,15 @@ void Plater::arrange() ArrangeSelectionMode::Full }; + const bool sequential = p->config->has("complete_objects") && p->config->opt_bool("complete_objects"); + if (p->can_arrange()) { - auto &w = get_ui_job_worker(); - arrange(w, mode); + if (sequential) + replace_job(this->get_ui_job_worker(), std::make_unique(this->model())); + else { + auto& w = get_ui_job_worker(); + arrange(w, mode); + } } }