Added progress bar and cancellation into UI, seq arrange is now executed from the main toolbar

This commit is contained in:
Lukas Matena 2024-12-09 10:00:58 +01:00
parent dc7ea52d88
commit c9b3f29c5b
8 changed files with 162 additions and 26 deletions

View File

@ -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

View File

@ -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

View File

@ -6,7 +6,6 @@
#include <string>
#include "libseqarrange/seq_interface.hpp"
namespace Slic3r {
@ -79,17 +78,36 @@ static std::vector<Sequential::ObjectToPrint> 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<Sequential::ObjectToPrint> objects = get_objects_to_print(model, printer_geometry);
// Everything ready - let libseqarrange do the actual arrangement.
std::vector<Sequential::ScheduledPlate> 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<void(int)> 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();

View File

@ -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<void(int)> 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<Sequential::ObjectToPrint> m_objects;
// This is the output, filled in by process_seq_arrange.
std::vector<Sequential::ScheduledPlate> m_plates;
};
}
#endif // slic3r_Arrange_Helper_hpp

View File

@ -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<std::chrono::seconds>(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();
}

View File

@ -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

View File

@ -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<SeqArrange> m_seq_arrange;
};
} // namespace GUI
} // namespace Slic3r
#endif // ARRANGEJOB2_HPP

View File

@ -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<SeqArrangeJob>(this->model()));
else {
auto& w = get_ui_job_worker();
arrange(w, mode);
}
}
}