Implemented FR #6994 - Set Number of Instances for multiple selected meshes

This commit is contained in:
YuSanka 2022-12-29 19:26:38 +01:00
parent b71e0bfd34
commit 4d5b85e675
5 changed files with 51 additions and 30 deletions

View file

@ -1218,9 +1218,15 @@ wxMenu* MenuFactory::multi_selection_menu()
append_menu_item_merge_to_multipart_object(menu);
if (extruders_count() > 1)
append_menu_item_change_extruder(menu);
if (list_model()->GetItemType(sels[0]) != itVolume)
if (list_model()->GetItemType(sels[0]) != itVolume) {
append_menu_item_printable(menu);
if (wxGetApp().get_mode() != comSimple)
append_menu_item(menu, wxID_ANY, _L("Set number of instances") + dots, _L("Change the number of instances of the selected objects"),
[](wxCommandEvent&) { plater()->set_number_of_copies(); }, "number_of_copies", nullptr,
[]() { return plater()->can_increase_instances(); }, m_parent);
}
return menu;
}

View file

@ -1941,7 +1941,7 @@ struct Plater::priv
bool can_delete() const;
bool can_delete_all() const;
bool can_increase_instances() const;
bool can_decrease_instances() const;
bool can_decrease_instances(int obj_idx = -1) const;
bool can_split_to_objects() const;
bool can_split_to_volumes() const;
bool can_arrange() const;
@ -5004,18 +5004,18 @@ bool Plater::priv::can_increase_instances() const
// Prevent strobo effect during editing emboss parameters.
if (q->canvas3D()->get_gizmos_manager().get_current_type() == GLGizmosManager::Emboss) return false;
const int obj_idx = get_selected_object_idx();
return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) &&
!sidebar->obj_list()->has_selected_cut_object();
const auto obj_idxs = get_selection().get_object_idxs();
return !obj_idxs.empty() && !sidebar->obj_list()->has_selected_cut_object();
}
bool Plater::priv::can_decrease_instances() const
bool Plater::priv::can_decrease_instances(int obj_idx /*= -1*/) const
{
if (!m_worker.is_idle()
|| q->canvas3D()->get_gizmos_manager().is_in_editing_mode())
return false;
const int obj_idx = get_selected_object_idx();
if (obj_idx < 0)
obj_idx = get_selected_object_idx();
return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) &&
(model.objects[obj_idx]->instances.size() > 1) &&
!sidebar->obj_list()->has_selected_cut_object();
@ -6273,13 +6273,14 @@ void Plater::remove_selected()
p->view3D->delete_selected();
}
void Plater::increase_instances(size_t num)
void Plater::increase_instances(size_t num, int obj_idx/* = -1*/)
{
if (! can_increase_instances()) { return; }
Plater::TakeSnapshot snapshot(this, _L("Increase Instances"));
int obj_idx = p->get_selected_object_idx();
if (obj_idx < 0)
obj_idx = p->get_selected_object_idx();
ModelObject* model_object = p->model.objects[obj_idx];
ModelInstance* model_instance = model_object->instances.back();
@ -6307,13 +6308,14 @@ void Plater::increase_instances(size_t num)
this->p->schedule_background_process();
}
void Plater::decrease_instances(size_t num)
void Plater::decrease_instances(size_t num, int obj_idx/* = -1*/)
{
if (! can_decrease_instances()) { return; }
if (! can_decrease_instances(obj_idx)) { return; }
Plater::TakeSnapshot snapshot(this, _L("Decrease Instances"));
int obj_idx = p->get_selected_object_idx();
if (obj_idx < 0)
obj_idx = p->get_selected_object_idx();
ModelObject* model_object = p->model.objects[obj_idx];
if (model_object->instances.size() > num) {
@ -6354,26 +6356,27 @@ static long GetNumberFromUser( const wxString& msg,
#endif
}
void Plater::set_number_of_copies(/*size_t num*/)
void Plater::set_number_of_copies()
{
int obj_idx = p->get_selected_object_idx();
if (obj_idx == -1)
const auto obj_idxs = get_selection().get_object_idxs();
if (obj_idxs.empty())
return;
ModelObject* model_object = p->model.objects[obj_idx];
const size_t init_cnt = obj_idxs.size() == 1 ? p->model.objects[*obj_idxs.begin()]->instances.size() : 1;
const int num = GetNumberFromUser( " ", _L("Enter the number of copies:"),
_L("Copies of the selected object"), model_object->instances.size(), 0, 1000, this );
_L("Copies of the selected object"), init_cnt, 0, 1000, this );
if (num < 0)
return;
TakeSnapshot snapshot(this, wxString::Format(_L("Set numbers of copies to %d"), num));
Plater::TakeSnapshot snapshot(this, wxString::Format(_L("Set numbers of copies to %d"), num));
int diff = num - (int)model_object->instances.size();
if (diff > 0)
increase_instances(diff);
else if (diff < 0)
decrease_instances(-diff);
for (const auto obj_idx : obj_idxs) {
ModelObject* model_object = p->model.objects[obj_idx];
const int diff = num - (int)model_object->instances.size();
if (diff > 0)
increase_instances(diff, int(obj_idx));
else if (diff < 0)
decrease_instances(-diff, int(obj_idx));
}
}
void Plater::fill_bed_with_instances()
@ -7665,7 +7668,7 @@ void Plater::init_notification_manager()
bool Plater::can_delete() const { return p->can_delete(); }
bool Plater::can_delete_all() const { return p->can_delete_all(); }
bool Plater::can_increase_instances() const { return p->can_increase_instances(); }
bool Plater::can_decrease_instances() const { return p->can_decrease_instances(); }
bool Plater::can_decrease_instances(int obj_idx/* = -1*/) const { return p->can_decrease_instances(obj_idx); }
bool Plater::can_set_instance_to_object() const { return p->can_set_instance_to_object(); }
bool Plater::can_fix_through_netfabb() const { return p->can_fix_through_netfabb(); }
bool Plater::can_simplify() const { return p->can_simplify(); }

View file

@ -249,9 +249,9 @@ public:
void reset_with_confirm();
bool delete_object_from_model(size_t obj_idx);
void remove_selected();
void increase_instances(size_t num = 1);
void decrease_instances(size_t num = 1);
void set_number_of_copies(/*size_t num*/);
void increase_instances(size_t num = 1, int obj_idx = -1);
void decrease_instances(size_t num = 1, int obj_idx = -1);
void set_number_of_copies();
void fill_bed_with_instances();
bool is_selection_empty() const;
void scale_selection_to_fit_print_volume();
@ -350,7 +350,7 @@ public:
bool can_delete() const;
bool can_delete_all() const;
bool can_increase_instances() const;
bool can_decrease_instances() const;
bool can_decrease_instances(int obj_idx = -1) const;
bool can_set_instance_to_object() const;
bool can_fix_through_netfabb() const;
bool can_simplify() const;

View file

@ -2145,6 +2145,16 @@ std::vector<unsigned int> Selection::get_unselected_volume_idxs_from(const std::
return idxs;
}
std::set<unsigned int> Selection::get_object_idxs() const
{
std::set<unsigned int> idxs;
for (unsigned int i : m_list)
idxs.emplace((*m_volumes)[i]->object_idx());
return idxs;
}
void Selection::update_valid()
{
m_valid = (m_volumes != nullptr) && (m_model != nullptr);

View file

@ -453,6 +453,8 @@ public:
std::vector<unsigned int> get_missing_volume_idxs_from(const std::vector<unsigned int>& volume_idxs) const;
// returns the list of idxs of the volumes contained in the given list but not in the selection
std::vector<unsigned int> get_unselected_volume_idxs_from(const std::vector<unsigned int>& volume_idxs) const;
// returns the list of idxs of the objects which are in the selection
std::set<unsigned int> get_object_idxs() const;
#if ENABLE_WORLD_COORDINATE_DEBUG
void render_debug_window() const;