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)
This commit is contained in:
Arthur 2024-08-29 21:20:33 +08:00 committed by Lane.Wei
parent d1d60d0af2
commit 45386c862f
7 changed files with 69 additions and 9 deletions

View File

@ -6409,7 +6409,7 @@ bool GLCanvas3D::_init_main_toolbar()
item.tooltip = _utf8(L("Auto orient")); item.tooltip = _utf8(L("Auto orient"));
item.sprite_id++; item.sprite_id++;
item.left.render_callback = nullptr; 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 item.left.toggable = false; // allow right mouse click
//BBS: GUI refactor: adjust the main toolbar position //BBS: GUI refactor: adjust the main toolbar position
item.left.action_callback = [this]() { 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)); 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; item.left.toggable = true;
//BBS: GUI refactor: adjust the main toolbar position //BBS: GUI refactor: adjust the main toolbar position
item.left.render_callback = [this](float left, float right, float bottom, float top) { item.left.render_callback = [this](float left, float right, float bottom, float top) {

View File

@ -93,6 +93,7 @@ void ArrangeJob::clear_input()
m_locked.clear(); m_locked.clear();
m_unarranged.clear(); m_unarranged.clear();
m_uncompatible_plates.clear(); m_uncompatible_plates.clear();
is_plate_locked.clear();
m_selected.reserve(count + 1 /* for optional wti */); m_selected.reserve(count + 1 /* for optional wti */);
m_unselected.reserve(count + 1 /* for optional wti */); m_unselected.reserve(count + 1 /* for optional wti */);
m_unprintable.reserve(cunprint /* 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); 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 //BBS: add partplate logic
void ArrangeJob::prepare() void ArrangeJob::prepare()
{ {
@ -449,6 +490,9 @@ void ArrangeJob::prepare()
else if (state == Job::JobPrepareState::PREPARE_STATE_MENU) { else if (state == Job::JobPrepareState::PREPARE_STATE_MENU) {
only_on_partplate = true; // only arrange items on current plate only_on_partplate = true; // only arrange items on current plate
prepare_partplate(); 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.")); NotificationManager::NotificationLevel::RegularNotificationLevel, _u8L("Arranging canceled."));
} }
Job::finalize(); 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); m_plater->m_arrange_running.store(false);
} }

View File

@ -22,6 +22,7 @@ class ArrangeJob : public PlaterJob
std::vector<ModelInstance*> m_unarranged; std::vector<ModelInstance*> m_unarranged;
std::map<int, ArrangePolygons> m_selected_groups; // groups of selected items for sequential printing std::map<int, ArrangePolygons> m_selected_groups; // groups of selected items for sequential printing
std::vector<int> m_uncompatible_plates; // plate indices with different printing sequence than global std::vector<int> m_uncompatible_plates; // plate indices with different printing sequence than global
std::vector<bool> is_plate_locked;
arrangement::ArrangeParams params; arrangement::ArrangeParams params;
int current_plate_index = 0; int current_plate_index = 0;
@ -38,6 +39,10 @@ class ArrangeJob : public PlaterJob
//BBS:prepare the items from current selected partplate //BBS:prepare the items from current selected partplate
void prepare_partplate(); void prepare_partplate();
// prepare the items which are selected and not on the current partplate
void prepare_outside_plate();
void prepare_wipe_tower(); void prepare_wipe_tower();
ArrangePolygon prepare_arrange_polygon(void* instance); ArrangePolygon prepare_arrange_polygon(void* instance);

View File

@ -71,7 +71,8 @@ protected:
public: public:
enum JobPrepareState { enum JobPrepareState {
PREPARE_STATE_DEFAULT = 0, PREPARE_STATE_DEFAULT = 0,
PREPARE_STATE_MENU = 1, PREPARE_STATE_MENU = 1,
PREPARE_STATE_OUTSIDE_BED = 2,
}; };
Job(std::shared_ptr<ProgressIndicator> pri); Job(std::shared_ptr<ProgressIndicator> pri);

View File

@ -280,6 +280,7 @@ public:
Vec2d get_size() const { return Vec2d(m_width, m_depth); } Vec2d get_size() const { return Vec2d(m_width, m_depth); }
ModelObjectPtrs get_objects() { return m_model->objects; } ModelObjectPtrs get_objects() { return m_model->objects; }
ModelObjectPtrs get_objects_on_this_plate(); ModelObjectPtrs get_objects_on_this_plate();
std::set<std::pair<int, int>>& get_obj_and_inst_set() { return obj_to_instance_set; }
ModelInstance* get_instance(int obj_id, int instance_id); ModelInstance* get_instance(int obj_id, int instance_id);
BoundingBoxf3 get_objects_bounding_box(); BoundingBoxf3 get_objects_bounding_box();

View File

@ -2618,7 +2618,7 @@ struct Plater::priv
bool can_decrease_instances() const; bool can_decrease_instances() const;
bool can_split_to_objects() const; bool can_split_to_objects() const;
bool can_split_to_volumes() const; bool can_split_to_volumes() const;
bool can_arrange() const; bool can_do_ui_job() const;
bool can_layers_editing() const; bool can_layers_editing() const;
bool can_fix_through_netfabb() const; bool can_fix_through_netfabb() const;
bool can_simplify() const; bool can_simplify() const;
@ -6484,6 +6484,10 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt)
view3D->center_selected_plate(i); 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(); view3D->deselect_all();
} }
#if 0 // do not toggle auto calc when change printer #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); 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(); 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)) 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 //arrange the plate
//take_snapshot("select_orient partplate"); //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)) 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 //arrange the plate
//take_snapshot("select_arrange partplate"); //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_simplify() const { return p->can_simplify(); }
bool Plater::can_split_to_objects() const { return p->can_split_to_objects(); } 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_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_layers_editing() const { return p->can_layers_editing(); }
bool Plater::can_paste_from_clipboard() const bool Plater::can_paste_from_clipboard() const
{ {

View File

@ -513,7 +513,7 @@ public:
bool can_simplify() const; bool can_simplify() const;
bool can_split_to_objects() const; bool can_split_to_objects() const;
bool can_split_to_volumes() const; bool can_split_to_volumes() const;
bool can_arrange() const; bool can_do_ui_job() const;
//BBS //BBS
bool can_cut_to_clipboard() const; bool can_cut_to_clipboard() const;
bool can_layers_editing() const; bool can_layers_editing() const;