From ad29cd395b4582da7332d6fcfc910cc5d614e953 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 10 Feb 2025 16:05:36 +0100 Subject: [PATCH] Seq arrange now handles selected-bed-only arrange --- src/libslic3r/ArrangeHelper.cpp | 40 +++++++++++++++++++-------- src/libslic3r/ArrangeHelper.hpp | 3 +- src/slic3r/GUI/GLCanvas3D.cpp | 4 +-- src/slic3r/GUI/Jobs/SeqArrangeJob.cpp | 4 +-- src/slic3r/GUI/Jobs/SeqArrangeJob.hpp | 2 +- src/slic3r/GUI/Plater.cpp | 37 ++++++++----------------- src/slic3r/GUI/Plater.hpp | 3 +- 7 files changed, 48 insertions(+), 45 deletions(-) diff --git a/src/libslic3r/ArrangeHelper.cpp b/src/libslic3r/ArrangeHelper.cpp index 131188720b..d0a5e7f718 100644 --- a/src/libslic3r/ArrangeHelper.cpp +++ b/src/libslic3r/ArrangeHelper.cpp @@ -115,7 +115,7 @@ static Sequential::SolverConfiguration get_solver_config(const Sequential::Print return Sequential::SolverConfiguration(printer_geometry); } -static std::vector get_objects_to_print(const Model& model, const Sequential::PrinterGeometry& printer_geometry) +static std::vector get_objects_to_print(const Model& model, const Sequential::PrinterGeometry& printer_geometry, int selected_bed) { // First extract the heights of interest. std::vector heights; @@ -126,9 +126,16 @@ static std::vector get_objects_to_print(const Model& // Now collect all objects and projections of convex hull above respective heights. std::vector>> objects; // first = object id, the vector = ids of its instances for (const ModelObject* mo : model.objects) { - size_t inst_id = 0; const TriangleMesh& raw_mesh = mo->raw_mesh(); + int inst_id = -1; + for (const ModelInstance* mi : mo->instances) { + ++inst_id; + if (selected_bed != -1) { + auto it = s_multiple_beds.get_inst_map().find(mi->id()); + if (it == s_multiple_beds.get_inst_map().end() || it->second != selected_bed) + continue; + } coord_t height = scaled(mo->instance_bounding_box(inst_id).size().z()); Sequential::ObjectToPrint* new_object = (inst_id == 0 ? &objects.emplace_back(std::make_pair(Sequential::ObjectToPrint{int(mo->id().id), inst_id + 1 < mo->instances.size(), height, {}}, std::vector())).first @@ -140,7 +147,6 @@ static std::vector get_objects_to_print(const Model& Polygon pgn = its_convex_hull_2d_above(raw_mesh.its, mi->get_matrix_no_offset().cast(), height - mi->get_offset().z()); new_object->pgns_at_height.emplace_back(std::make_pair(scaled(height), pgn)); } - ++inst_id; } } @@ -161,21 +167,21 @@ static std::vector get_objects_to_print(const Model& -void arrange_model_sequential(Model& model, const ConfigBase& config) +void arrange_model_sequential(Model& model, const ConfigBase& config, bool current_bed_only) { - SeqArrange seq_arrange(model, config); + SeqArrange seq_arrange(model, config, current_bed_only); seq_arrange.process_seq_arrange([](int) {}); seq_arrange.apply_seq_arrange(model); } -SeqArrange::SeqArrange(const Model& model, const ConfigBase& config) +SeqArrange::SeqArrange(const Model& model, const ConfigBase& config, bool current_bed_only) { + m_selected_bed = current_bed_only ? s_multiple_beds.get_active_bed() : -1; m_printer_geometry = get_printer_geometry(config); m_solver_configuration = get_solver_config(m_printer_geometry); - m_objects = get_objects_to_print(model, m_printer_geometry); - + m_objects = get_objects_to_print(model, m_printer_geometry, m_selected_bed); } @@ -206,8 +212,16 @@ void SeqArrange::apply_seq_arrange(Model& model) const // Save the move data from this file to move_data_all. size_t bed_idx = 0; 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. + int real_bed = bed_idx; + + if (m_selected_bed != -1) { + if (bed_idx == 0) + real_bed = m_selected_bed; + else + real_bed += s_multiple_beds.get_number_of_beds() - 1; + } + + Vec3d bed_offset = s_multiple_beds.get_bed_translation(real_bed); for (ModelObject* mo : model.objects) { for (ModelInstance* mi : mo->instances) { const ObjectID& oid = (mi == mo->instances.front() ? mo->id() : mi->id()); @@ -218,10 +232,12 @@ void SeqArrange::apply_seq_arrange(Model& model) const } } for (const Sequential::ScheduledObject& object : plate.scheduled_objects) - move_data_all.push_back({ object, bed_idx }); + move_data_all.push_back({ object, size_t(real_bed) }); ++bed_idx; } + + // Now reorder the objects in the model so they are in the same order as requested. auto comp = [&move_data_all](ModelObject* mo1, ModelObject* mo2) { auto it1 = std::find_if(move_data_all.begin(), move_data_all.end(), [&mo1](const auto& md) { return md.scheduled_object.id == mo1->id().id; }); @@ -241,7 +257,7 @@ bool check_seq_printability(const Model& model, const ConfigBase& config) { Sequential::PrinterGeometry printer_geometry = get_printer_geometry(config); Sequential::SolverConfiguration solver_config = get_solver_config(printer_geometry); - std::vector objects = get_objects_to_print(model, printer_geometry); + std::vector objects = get_objects_to_print(model, printer_geometry, -1); if (printer_geometry.extruder_slices.empty()) { // If there are no data for extruder (such as extruder_clearance_radius set to 0), diff --git a/src/libslic3r/ArrangeHelper.hpp b/src/libslic3r/ArrangeHelper.hpp index 91a0921967..1136829f8a 100644 --- a/src/libslic3r/ArrangeHelper.hpp +++ b/src/libslic3r/ArrangeHelper.hpp @@ -19,7 +19,7 @@ namespace Slic3r { // into a separate thread without copying the Model or sharing it with UI thread. class SeqArrange { public: - explicit SeqArrange(const Model& model, const ConfigBase& config); + explicit SeqArrange(const Model& model, const ConfigBase& config, bool current_bed_only); void process_seq_arrange(std::function progress_fn); void apply_seq_arrange(Model& model) const; @@ -28,6 +28,7 @@ namespace Slic3r { Sequential::PrinterGeometry m_printer_geometry; Sequential::SolverConfiguration m_solver_configuration; std::vector m_objects; + int m_selected_bed = -1; // This is the output, filled in by process_seq_arrange. std::vector m_plates; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index bf86c2ed43..32bb68bdf5 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1342,10 +1342,10 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas *canvas, Bed3D &bed) return this->is_arrange_alignment_enabled(); }); m_arrange_settings_dialog.on_arrange_btn([]{ - wxGetApp().plater()->arrange(); + wxGetApp().plater()->arrange(false); }); m_arrange_settings_dialog.on_arrange_bed_btn([]{ - wxGetApp().plater()->arrange_current_bed(); + wxGetApp().plater()->arrange(true); }); } diff --git a/src/slic3r/GUI/Jobs/SeqArrangeJob.cpp b/src/slic3r/GUI/Jobs/SeqArrangeJob.cpp index 07a8658c59..2fb0f0d952 100644 --- a/src/slic3r/GUI/Jobs/SeqArrangeJob.cpp +++ b/src/slic3r/GUI/Jobs/SeqArrangeJob.cpp @@ -14,9 +14,9 @@ namespace Slic3r { namespace GUI { -SeqArrangeJob::SeqArrangeJob(const Model& model, const DynamicPrintConfig& config) +SeqArrangeJob::SeqArrangeJob(const Model& model, const DynamicPrintConfig& config, bool current_bed_only) { - m_seq_arrange.reset(new SeqArrange(model, config)); + m_seq_arrange.reset(new SeqArrange(model, config, current_bed_only)); } diff --git a/src/slic3r/GUI/Jobs/SeqArrangeJob.hpp b/src/slic3r/GUI/Jobs/SeqArrangeJob.hpp index 0c9ffb683b..c604ebb772 100644 --- a/src/slic3r/GUI/Jobs/SeqArrangeJob.hpp +++ b/src/slic3r/GUI/Jobs/SeqArrangeJob.hpp @@ -17,7 +17,7 @@ namespace GUI { class SeqArrangeJob : public Job { public: - explicit SeqArrangeJob(const Model& model, const DynamicPrintConfig& config); + explicit SeqArrangeJob(const Model& model, const DynamicPrintConfig& config, bool current_bed_only); virtual void process(Ctl &ctl) override; virtual void finalize(bool /*canceled*/, std::exception_ptr&) override; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index dd27b21659..ae5add653d 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -715,8 +715,8 @@ void Plater::priv::init() view3D_canvas->Bind(EVT_GLCANVAS_OBJECT_SELECT, &priv::on_object_select, this); view3D_canvas->Bind(EVT_GLCANVAS_RIGHT_CLICK, &priv::on_right_click, this); view3D_canvas->Bind(EVT_GLCANVAS_REMOVE_OBJECT, [this](SimpleEvent&) { q->remove_selected(); }); - view3D_canvas->Bind(EVT_GLCANVAS_ARRANGE, [this](SimpleEvent&) { this->q->arrange(); }); - view3D_canvas->Bind(EVT_GLCANVAS_ARRANGE_CURRENT_BED, [this](SimpleEvent&) { this->q->arrange_current_bed(); }); + view3D_canvas->Bind(EVT_GLCANVAS_ARRANGE, [this](SimpleEvent&) { this->q->arrange(false); }); + view3D_canvas->Bind(EVT_GLCANVAS_ARRANGE_CURRENT_BED, [this](SimpleEvent&) { this->q->arrange(true); }); view3D_canvas->Bind(EVT_GLCANVAS_SELECT_ALL, [this](SimpleEvent&) { this->q->select_all(); }); view3D_canvas->Bind(EVT_GLCANVAS_QUESTION_MARK, [](SimpleEvent&) { wxGetApp().keyboard_shortcuts(); }); view3D_canvas->Bind(EVT_GLCANVAS_INCREASE_INSTANCES, [this](Event& evt) @@ -747,8 +747,8 @@ void Plater::priv::init() view3D_canvas->Bind(EVT_GLTOOLBAR_DELETE, [this](SimpleEvent&) { q->remove_selected(); }); view3D_canvas->Bind(EVT_GLTOOLBAR_DELETE_ALL, [this](SimpleEvent&) { delete_all_objects_from_model(); }); // view3D_canvas->Bind(EVT_GLTOOLBAR_DELETE_ALL, [q](SimpleEvent&) { q->reset_with_confirm(); }); - view3D_canvas->Bind(EVT_GLTOOLBAR_ARRANGE, [this](SimpleEvent&) { this->q->arrange(); }); - view3D_canvas->Bind(EVT_GLTOOLBAR_ARRANGE_CURRENT_BED, [this](SimpleEvent&) { this->q->arrange_current_bed(); }); + view3D_canvas->Bind(EVT_GLTOOLBAR_ARRANGE, [this](SimpleEvent&) { this->q->arrange(false); }); + view3D_canvas->Bind(EVT_GLTOOLBAR_ARRANGE_CURRENT_BED, [this](SimpleEvent&) { this->q->arrange(true); }); view3D_canvas->Bind(EVT_GLTOOLBAR_COPY, [this](SimpleEvent&) { q->copy_selection_to_clipboard(); }); view3D_canvas->Bind(EVT_GLTOOLBAR_PASTE, [this](SimpleEvent&) { q->paste_from_clipboard(); }); view3D_canvas->Bind(EVT_GLTOOLBAR_MORE, [this](SimpleEvent&) { q->increase_instances(); }); @@ -7111,19 +7111,19 @@ static std::string concat_strings(const std::set &strings, }); } -void Plater::arrange() +void Plater::arrange(bool current_bed_only) { - const auto mode{ - wxGetKeyState(WXK_SHIFT) ? - ArrangeSelectionMode::SelectionOnly : - ArrangeSelectionMode::Full - }; + ArrangeSelectionMode mode; + if (current_bed_only) + mode = wxGetKeyState(WXK_SHIFT) ? ArrangeSelectionMode::CurrentBedSelectionOnly : ArrangeSelectionMode::CurrentBedFull; + else + mode = wxGetKeyState(WXK_SHIFT) ? ArrangeSelectionMode::SelectionOnly : ArrangeSelectionMode::Full; const bool sequential = p->config->has("complete_objects") && p->config->opt_bool("complete_objects"); if (p->can_arrange()) { if (sequential) - replace_job(this->get_ui_job_worker(), std::make_unique(this->model(), *p->config)); + replace_job(this->get_ui_job_worker(), std::make_unique(this->model(), *p->config, current_bed_only)); else { auto& w = get_ui_job_worker(); arrange(w, mode); @@ -7131,19 +7131,6 @@ void Plater::arrange() } } -void Plater::arrange_current_bed() -{ - const auto mode{ - wxGetKeyState(WXK_SHIFT) ? - ArrangeSelectionMode::CurrentBedSelectionOnly : - ArrangeSelectionMode::CurrentBedFull - }; - if (p->can_arrange()) { - auto &w = get_ui_job_worker(); - arrange(w, mode); - } -} - void Plater::arrange(Worker &w, const ArrangeSelectionMode &mode) { arr2::Scene arrscene{build_scene(*this, mode)}; @@ -7731,7 +7718,7 @@ PlaterAfterLoadAutoArrange::PlaterAfterLoadAutoArrange() PlaterAfterLoadAutoArrange::~PlaterAfterLoadAutoArrange() { if (m_enabled) - wxGetApp().plater()->arrange(); + wxGetApp().plater()->arrange(false); } }} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 10e5d769fb..879a125f2b 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -305,8 +305,7 @@ public: void render_sliders(GLCanvas3D& canvas); - void arrange(); - void arrange_current_bed(); + void arrange(bool current_bed_only); void arrange(Worker &w, const ArrangeSelectionMode &selected); void set_current_canvas_as_dirty();