diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index 5ca8f8e2a9..0bd523b261 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -50,7 +50,7 @@ static SettingsFactory::Bundle FREQ_SETTINGS_BUNDLE_FFF = { L("Layers and Perimeters"), { "layer_height" , "perimeters", "top_solid_layers", "bottom_solid_layers" } }, { L("Infill") , { "fill_density", "fill_pattern" } }, { L("Support material") , { "support_material", "support_material_auto", "support_material_threshold", - "support_material_pattern", "support_material_pattern", "support_material_interface_pattern", "support_material_buildplate_only", + "support_material_pattern", "support_material_interface_pattern", "support_material_buildplate_only", "support_material_spacing" } }, { L("Wipe options") , { "wipe_into_infill", "wipe_into_objects" } } }; @@ -581,17 +581,30 @@ wxMenuItem* MenuFactory::append_menu_item_instance_to_object(wxMenu* menu) wxMenuItem* MenuFactory::append_menu_item_printable(wxMenu* menu) { - return append_menu_check_item(menu, wxID_ANY, _L("Printable"), "", [](wxCommandEvent&) { - const Selection& selection = plater()->canvas3D()->get_selection(); - wxDataViewItem item; - if (obj_list()->GetSelectedItemsCount() > 1 && selection.is_single_full_object()) - item = obj_list()->GetModel()->GetItemById(selection.get_object_idx()); - else - item = obj_list()->GetSelection(); + wxMenuItem* menu_item_printable = append_menu_check_item(menu, wxID_ANY, _L("Printable"), "", + [](wxCommandEvent& ) { obj_list()->toggle_printable_state(); }, menu); - if (item) - obj_list()->toggle_printable_state(item); - }, menu); + m_parent->Bind(wxEVT_UPDATE_UI, [](wxUpdateUIEvent& evt) { + ObjectList* list = obj_list(); + wxDataViewItemArray sels; + list->GetSelections(sels); + wxDataViewItem frst_item = sels[0]; + ItemType type = list->GetModel()->GetItemType(frst_item); + bool check; + if (type != itInstance && type != itObject) + check = false; + else { + int obj_idx = list->GetModel()->GetObjectIdByItem(frst_item); + int inst_idx = type == itObject ? 0 : list->GetModel()->GetInstanceIdByItem(frst_item); + check = list->object(obj_idx)->instances[inst_idx]->printable; + } + + evt.Check(check); + plater()->set_current_canvas_as_dirty(); + + }, menu_item_printable->GetId()); + + return menu_item_printable; } void MenuFactory::append_menu_items_osx(wxMenu* menu) @@ -800,7 +813,7 @@ void MenuFactory::create_common_object_menu(wxMenu* menu) append_menu_item_instance_to_object(menu); menu->AppendSeparator(); - wxMenuItem* menu_item_printable = append_menu_item_printable(menu); + append_menu_item_printable(menu); menu->AppendSeparator(); append_menu_item_reload_from_disk(menu); @@ -810,16 +823,6 @@ void MenuFactory::create_common_object_menu(wxMenu* menu) append_menu_item_fix_through_netfabb(menu); append_menu_items_mirror(menu); - - m_parent->Bind(wxEVT_UPDATE_UI, [](wxUpdateUIEvent& evt) { - const Selection& selection = get_selection(); - int instance_idx = selection.get_instance_idx(); - evt.Enable(selection.is_single_full_instance() || selection.is_single_full_object()); - if (instance_idx != -1) { - evt.Check(obj_list()->object(selection.get_object_idx())->instances[instance_idx]->printable); - plater()->set_current_canvas_as_dirty();//view3D->set_as_dirty(); - } - }, menu_item_printable->GetId()); } void MenuFactory::create_object_menu() @@ -882,6 +885,14 @@ void MenuFactory::create_part_menu() } +void MenuFactory::create_instance_menu() +{ + wxMenu* menu = &m_instance_menu; + // create "Instance to Object" menu item + append_menu_item_instance_to_object(menu); + append_menu_item_printable(menu); +} + void MenuFactory::init(wxWindow* parent) { m_parent = parent; @@ -890,9 +901,7 @@ void MenuFactory::init(wxWindow* parent) create_object_menu(); create_sla_object_menu(); create_part_menu(); - - // create "Instance to Object" menu item - append_menu_item_instance_to_object(&m_instance_menu); + create_instance_menu(); } wxMenu* MenuFactory::default_menu() @@ -959,6 +968,8 @@ 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) + append_menu_item_printable(menu); return menu; } diff --git a/src/slic3r/GUI/GUI_Factories.hpp b/src/slic3r/GUI/GUI_Factories.hpp index 3cc5759a12..ffa17933ce 100644 --- a/src/slic3r/GUI/GUI_Factories.hpp +++ b/src/slic3r/GUI/GUI_Factories.hpp @@ -76,6 +76,7 @@ private: void create_object_menu(); void create_sla_object_menu(); void create_part_menu(); + void create_instance_menu(); wxMenu* append_submenu_add_generic(wxMenu* menu, ModelVolumeType type); void append_menu_items_add_volume(wxMenu* menu); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index f37276bebe..58560c8bd7 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -837,7 +837,7 @@ void ObjectList::list_manipulation(const wxPoint& mouse_pos, bool evt_context_me { const wxString title = col->GetTitle(); if (title == " ") - toggle_printable_state(item); + toggle_printable_state(); else if (title == _("Editing")) show_context_menu(evt_context_menu); else if (title == _("Name")) @@ -3837,37 +3837,59 @@ void ObjectList::update_printable_state(int obj_idx, int instance_idx) m_objects_model->SetPrintableState(printable, obj_idx, instance_idx); } -void ObjectList::toggle_printable_state(wxDataViewItem item) +void ObjectList::toggle_printable_state() { - const ItemType type = m_objects_model->GetItemType(item); - if (!(type&(itObject|itInstance/*|itVolume*/))) + wxDataViewItemArray sels; + GetSelections(sels); + + wxDataViewItem frst_item = sels[0]; + + ItemType type = m_objects_model->GetItemType(frst_item); + if (!(type & (itObject | itInstance))) return; - if (type & itObject) + + int obj_idx = m_objects_model->GetObjectIdByItem(frst_item); + int inst_idx = type == itObject ? 0 : m_objects_model->GetInstanceIdByItem(frst_item); + bool printable = !object(obj_idx)->instances[inst_idx]->printable; + + const wxString snapshot_text = sels.Count() > 1 ? (printable ? _L("Set Printable group") : _L("Set Unprintable group")) : + object(obj_idx)->instances.size() == 1 ? from_u8((boost::format("%1% %2%") + % (printable ? _L("Set Printable") : _L("Set Unprintable")) + % object(obj_idx)->name).str()) : + (printable ? _L("Set Printable Instance") : _L("Set Unprintable Instance")); + take_snapshot(snapshot_text); + + std::vector obj_idxs; + for (auto item : sels) { - const int obj_idx = m_objects_model->GetObjectIdByItem(item); - ModelObject* object = (*m_objects)[obj_idx]; + type = m_objects_model->GetItemType(item); + if (!(type & (itObject | itInstance))) + continue; - // get object's printable and change it - const bool printable = !m_objects_model->IsPrintable(item); + obj_idx = m_objects_model->GetObjectIdByItem(item); + ModelObject* obj = object(obj_idx); - const wxString snapshot_text = from_u8((boost::format("%1% %2%") - % (printable ? _(L("Set Printable")) : _(L("Set Unprintable"))) - % object->name).str()); - take_snapshot(snapshot_text); + obj_idxs.emplace_back(static_cast(obj_idx)); - // set printable value for all instances in object - for (auto inst : object->instances) - inst->printable = printable; - - // update printable state on canvas - wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_object((size_t)obj_idx); + // set printable value for selected instance/instances in object + if (type == itInstance) { + inst_idx = m_objects_model->GetInstanceIdByItem(item); + obj->instances[m_objects_model->GetInstanceIdByItem(item)]->printable = printable; + } + else + for (auto inst : obj->instances) + inst->printable = printable; // update printable state in ObjectList - m_objects_model->SetObjectPrintableState(printable ? piPrintable : piUnprintable , item); + m_objects_model->SetObjectPrintableState(printable ? piPrintable : piUnprintable, item); } - else - wxGetApp().plater()->canvas3D()->get_selection().toggle_instance_printable_state(); + + sort(obj_idxs.begin(), obj_idxs.end()); + obj_idxs.erase(unique(obj_idxs.begin(), obj_idxs.end()), obj_idxs.end()); + + // update printable state on canvas + wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_objects(obj_idxs); // update scene wxGetApp().plater()->update(); diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 35a8fdee0b..d70c53849d 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -369,7 +369,7 @@ public: void update_after_undo_redo(); //update printable state for item from objects model void update_printable_state(int obj_idx, int instance_idx); - void toggle_printable_state(wxDataViewItem item); + void toggle_printable_state(); void set_extruder_for_selected_items(const int extruder) const ; diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 214c2632a6..faf25ff8bc 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -1466,41 +1466,6 @@ std::vector Selection::get_unselected_volume_idxs_from(const std:: return idxs; } -void Selection::toggle_instance_printable_state() -{ - int instance_idx = get_instance_idx(); - if (instance_idx == -1) - return; - - int obj_idx = get_object_idx(); - if ((0 <= obj_idx) && (obj_idx < (int)m_model->objects.size())) - { - ModelObject* model_object = m_model->objects[obj_idx]; - if ((0 <= instance_idx) && (instance_idx < (int)model_object->instances.size())) - { - ModelInstance* instance = model_object->instances[instance_idx]; - const bool printable = !instance->printable; - - wxString snapshot_text = model_object->instances.size() == 1 ? from_u8((boost::format("%1% %2%") - % (printable ? _utf8(L("Set Printable")) : _utf8(L("Set Unprintable"))) - % model_object->name).str()) : - (printable ? _(L("Set Printable Instance")) : _(L("Set Unprintable Instance"))); - wxGetApp().plater()->take_snapshot(snapshot_text); - - instance->printable = printable; - - for (GLVolume* volume : *m_volumes) - { - if ((volume->object_idx() == obj_idx) && (volume->instance_idx() == instance_idx)) - volume->printable = instance->printable; - } - - wxGetApp().obj_list()->update_printable_state(obj_idx, instance_idx); - wxGetApp().plater()->update(); - } - } -} - void Selection::update_valid() { m_valid = (m_volumes != nullptr) && (m_model != nullptr); diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index 4da9e44a38..a9095adcbf 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -286,6 +286,7 @@ public: bool is_from_single_instance() const { return get_instance_idx() != -1; } bool is_from_single_object() const; bool is_sla_compliant() const; + bool is_instance_mode() const { return m_mode == Instance; } bool contains_volume(unsigned int volume_idx) const { return m_list.find(volume_idx) != m_list.end(); } // returns true if the selection contains all the given indices @@ -355,8 +356,6 @@ public: // returns the list of idxs of the volumes contained in the given list but not in the selection std::vector get_unselected_volume_idxs_from(const std::vector& volume_idxs) const; - void toggle_instance_printable_state(); - private: void update_valid(); void update_type();