From 45386c862faefa68429c9ede447eabdcd1e570b1 Mon Sep 17 00:00:00 2001 From: Arthur Date: Thu, 29 Aug 2024 21:20:33 +0800 Subject: [PATCH] NEW: auto arrange after bed size changes 1. auto arrange after bed size changes When the bed size changes from big to small, auto arrange items outside beds, while keeping the inside ones still. This action can be undoed with ctrl+z. 2. Fix the issue that double clicking the orient button of plate causes a never disappearing busy cursor. jira: STUDIO-7978 Change-Id: I5ee1f73b80735777c21438a01cbc4649d8cce3fa (cherry picked from commit f67fd877ea7b07148dc9539938ba319a4f960d0e) --- src/slic3r/GUI/GLCanvas3D.cpp | 4 +-- src/slic3r/GUI/Jobs/ArrangeJob.cpp | 49 ++++++++++++++++++++++++++++++ src/slic3r/GUI/Jobs/ArrangeJob.hpp | 5 +++ src/slic3r/GUI/Jobs/Job.hpp | 3 +- src/slic3r/GUI/PartPlate.hpp | 1 + src/slic3r/GUI/Plater.cpp | 14 ++++++--- src/slic3r/GUI/Plater.hpp | 2 +- 7 files changed, 69 insertions(+), 9 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index dd3601883..717b0780c 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -6409,7 +6409,7 @@ bool GLCanvas3D::_init_main_toolbar() item.tooltip = _utf8(L("Auto orient")); item.sprite_id++; item.left.render_callback = nullptr; - item.enabling_callback = []()->bool { return wxGetApp().plater()->can_arrange(); }; + item.enabling_callback = []()->bool { return wxGetApp().plater()->can_do_ui_job(); }; item.left.toggable = false; // allow right mouse click //BBS: GUI refactor: adjust the main toolbar position item.left.action_callback = [this]() { @@ -6436,7 +6436,7 @@ bool GLCanvas3D::_init_main_toolbar() if (agent) agent->track_update_property("auto_arrange", std::to_string(++auto_arrange_count)); } }; - item.enabling_callback = []()->bool { return wxGetApp().plater()->can_arrange(); }; + item.enabling_callback = []()->bool { return wxGetApp().plater()->can_do_ui_job(); }; item.left.toggable = true; //BBS: GUI refactor: adjust the main toolbar position item.left.render_callback = [this](float left, float right, float bottom, float top) { diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.cpp b/src/slic3r/GUI/Jobs/ArrangeJob.cpp index 615b883d6..062416eed 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.cpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.cpp @@ -93,6 +93,7 @@ void ArrangeJob::clear_input() m_locked.clear(); m_unarranged.clear(); m_uncompatible_plates.clear(); + is_plate_locked.clear(); m_selected.reserve(count + 1 /* for optional wti */); m_unselected.reserve(count + 1 /* for optional wti */); m_unprintable.reserve(cunprint /* for optional wti */); @@ -423,6 +424,46 @@ void ArrangeJob::prepare_partplate() { plate_list.preprocess_exclude_areas(m_unselected, current_plate_index + 1); } +void ArrangeJob::prepare_outside_plate() { + clear_input(); + + Model &model = m_plater->model(); + PartPlateList &plate_list = m_plater->get_partplate_list(); + is_plate_locked.resize(plate_list.get_plate_count()); + for (int plate_idx = 0; plate_idx < plate_list.get_plate_count(); plate_idx++) { + PartPlate *plate = plate_list.get_plate(plate_idx); + assert(plate != nullptr); + if (plate->empty()) { + // no instances on this plate + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << format(": no instances in plate %d!", plate_idx); + continue; + } + + is_plate_locked[plate_idx] = plate->is_locked(); + plate->lock(true); + + // Go through the objects and select the outside ones + for (auto obj_and_inst : plate->get_obj_and_inst_set()) { + int oidx = obj_and_inst.first; + size_t inst_idx = obj_and_inst.second; + ModelObject *mo = model.objects[oidx]; + bool outside_plate = plate->check_outside(oidx, inst_idx); + ArrangePolygon &&ap = prepare_arrange_polygon(mo->instances[inst_idx]); + ArrangePolygons &cont = mo->instances[inst_idx]->printable ? (outside_plate ? m_selected : m_locked) : m_unprintable; + ap.itemid = cont.size(); + cont.emplace_back(std::move(ap)); + } + } + // BBS + if (auto wti = get_wipe_tower(*m_plater, current_plate_index)) { + ArrangePolygon &&ap = get_wipetower_arrange_poly(&wti); + m_unselected.emplace_back(std::move(ap)); + } + + // add the virtual object into unselect list if has + plate_list.preprocess_exclude_areas(m_unselected, current_plate_index + 1); +} + //BBS: add partplate logic void ArrangeJob::prepare() { @@ -449,6 +490,9 @@ void ArrangeJob::prepare() else if (state == Job::JobPrepareState::PREPARE_STATE_MENU) { only_on_partplate = true; // only arrange items on current plate prepare_partplate(); + } else if (state == Job::JobPrepareState::PREPARE_STATE_OUTSIDE_BED) { + only_on_partplate = false; + prepare_outside_plate(); } @@ -730,6 +774,11 @@ void ArrangeJob::finalize() { NotificationManager::NotificationLevel::RegularNotificationLevel, _u8L("Arranging canceled.")); } Job::finalize(); + + // restore lock status + for (int i = 0; i < is_plate_locked.size(); i++) + m_plater->get_partplate_list().get_plate(i)->lock(is_plate_locked[i]); + m_plater->m_arrange_running.store(false); } diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.hpp b/src/slic3r/GUI/Jobs/ArrangeJob.hpp index 7df2d344f..933606e1f 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.hpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.hpp @@ -22,6 +22,7 @@ class ArrangeJob : public PlaterJob std::vector m_unarranged; std::map m_selected_groups; // groups of selected items for sequential printing std::vector m_uncompatible_plates; // plate indices with different printing sequence than global + std::vector is_plate_locked; arrangement::ArrangeParams params; int current_plate_index = 0; @@ -38,6 +39,10 @@ class ArrangeJob : public PlaterJob //BBS:prepare the items from current selected partplate void prepare_partplate(); + + // prepare the items which are selected and not on the current partplate + void prepare_outside_plate(); + void prepare_wipe_tower(); ArrangePolygon prepare_arrange_polygon(void* instance); diff --git a/src/slic3r/GUI/Jobs/Job.hpp b/src/slic3r/GUI/Jobs/Job.hpp index a92dfbfbd..005a80787 100644 --- a/src/slic3r/GUI/Jobs/Job.hpp +++ b/src/slic3r/GUI/Jobs/Job.hpp @@ -71,7 +71,8 @@ protected: public: enum JobPrepareState { PREPARE_STATE_DEFAULT = 0, - PREPARE_STATE_MENU = 1, + PREPARE_STATE_MENU = 1, + PREPARE_STATE_OUTSIDE_BED = 2, }; Job(std::shared_ptr pri); diff --git a/src/slic3r/GUI/PartPlate.hpp b/src/slic3r/GUI/PartPlate.hpp index 216f9dac6..7d1405241 100644 --- a/src/slic3r/GUI/PartPlate.hpp +++ b/src/slic3r/GUI/PartPlate.hpp @@ -280,6 +280,7 @@ public: Vec2d get_size() const { return Vec2d(m_width, m_depth); } ModelObjectPtrs get_objects() { return m_model->objects; } ModelObjectPtrs get_objects_on_this_plate(); + std::set>& get_obj_and_inst_set() { return obj_to_instance_set; } ModelInstance* get_instance(int obj_id, int instance_id); BoundingBoxf3 get_objects_bounding_box(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index cd1876cfe..cdfdda7cd 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2618,7 +2618,7 @@ struct Plater::priv bool can_decrease_instances() const; bool can_split_to_objects() const; bool can_split_to_volumes() const; - bool can_arrange() const; + bool can_do_ui_job() const; bool can_layers_editing() const; bool can_fix_through_netfabb() const; bool can_simplify() const; @@ -6484,6 +6484,10 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) view3D->center_selected_plate(i); } + take_snapshot("Arrange after bed size changes"); + q->set_prepare_state(Job::PREPARE_STATE_OUTSIDE_BED); + q->arrange(); + view3D->deselect_all(); } #if 0 // do not toggle auto calc when change printer @@ -8063,7 +8067,7 @@ bool Plater::priv::can_split_to_volumes() const return (printer_technology != ptSLA) && q->can_split(false); } -bool Plater::priv::can_arrange() const +bool Plater::priv::can_do_ui_job() const { return !model.objects.empty() && !m_ui_jobs.is_any_running() && !q->is_background_process_slicing(); } @@ -13474,7 +13478,7 @@ int Plater::select_plate_by_hover_id(int hover_id, bool right_click, bool isModi } else if ((action == 2)&&(!right_click)) { - if (!p->partplate_list.get_plate(plate_index)->get_objects().empty() && !is_background_process_slicing()) + if (p->can_do_ui_job()) { //arrange the plate //take_snapshot("select_orient partplate"); @@ -13493,7 +13497,7 @@ int Plater::select_plate_by_hover_id(int hover_id, bool right_click, bool isModi } else if ((action == 3)&&(!right_click)) { - if (!p->partplate_list.get_plate(plate_index)->get_objects().empty() && !is_background_process_slicing()) + if (p->can_do_ui_job()) { //arrange the plate //take_snapshot("select_arrange partplate"); @@ -13893,7 +13897,7 @@ bool Plater::can_fix_through_netfabb() const { return p->can_fix_through_netfabb bool Plater::can_simplify() const { return p->can_simplify(); } bool Plater::can_split_to_objects() const { return p->can_split_to_objects(); } bool Plater::can_split_to_volumes() const { return p->can_split_to_volumes(); } -bool Plater::can_arrange() const { return p->can_arrange(); } +bool Plater::can_do_ui_job() const { return p->can_do_ui_job(); } bool Plater::can_layers_editing() const { return p->can_layers_editing(); } bool Plater::can_paste_from_clipboard() const { diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index f56bc6272..0874fa003 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -513,7 +513,7 @@ public: bool can_simplify() const; bool can_split_to_objects() const; bool can_split_to_volumes() const; - bool can_arrange() const; + bool can_do_ui_job() const; //BBS bool can_cut_to_clipboard() const; bool can_layers_editing() const;