Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/slic3r/GUI/GUI_ObjectList.cpp')
-rw-r--r--src/slic3r/GUI/GUI_ObjectList.cpp371
1 files changed, 318 insertions, 53 deletions
diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp
index dffaf7afc..62c00d02d 100644
--- a/src/slic3r/GUI/GUI_ObjectList.cpp
+++ b/src/slic3r/GUI/GUI_ObjectList.cpp
@@ -21,6 +21,25 @@ namespace GUI
wxDEFINE_EVENT(EVT_OBJ_LIST_OBJECT_SELECT, SimpleEvent);
+typedef std::map<std::string, std::vector<std::string>> FreqSettingsBundle;
+
+// pt_FFF
+FreqSettingsBundle 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_buildplate_only",
+ "support_material_spacing" } },
+ { L("Extruders") , { "wipe_into_infill", "wipe_into_objects" } }
+};
+
+// pt_SLA
+FreqSettingsBundle FREQ_SETTINGS_BUNDLE_SLA =
+{
+ { L("Pad and Support") , { "supports_enable", "pad_enable" } }
+};
+
ObjectList::ObjectList(wxWindow* parent) :
wxDataViewCtrl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_MULTIPLE),
m_parent(parent)
@@ -51,6 +70,7 @@ ObjectList::ObjectList(wxWindow* parent) :
create_object_popupmenu(&m_menu_object);
create_part_popupmenu(&m_menu_part);
create_sla_object_popupmenu(&m_menu_sla_object);
+ create_instance_popupmenu(&m_menu_instance);
// describe control behavior
Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxEvent& event) {
@@ -97,7 +117,7 @@ void ObjectList::create_objects_ctrl()
// temporary workaround for the correct behavior of the Scrolled sidebar panel:
// 1. set a height of the list to some big value
// 2. change it to the normal min value (200) after first whole App updating/layouting
- SetMinSize(wxSize(-1, 1500)); // #ys_FIXME
+ SetMinSize(wxSize(-1, 3000)); // #ys_FIXME
m_sizer = new wxBoxSizer(wxVERTICAL);
m_sizer->Add(this, 1, wxGROW | wxLEFT, 20);
@@ -400,15 +420,28 @@ void ObjectList::OnContextMenu(wxDataViewEvent&)
void ObjectList::show_context_menu()
{
+ if (multiple_selection() && selected_instances_of_same_object())
+ {
+ wxGetApp().plater()->PopupMenu(&m_menu_instance);
+
+ wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) {
+ evt.Enable(can_split_instances()); }, m_menu_item_split_instances->GetId());
+ return;
+ }
+
const auto item = GetSelection();
if (item)
{
- if (!(m_objects_model->GetItemType(item) & (itObject | itVolume)))
+ const ItemType type = m_objects_model->GetItemType(item);
+ if (!(type & (itObject | itVolume | itInstance)))
return;
- wxMenu* menu = m_objects_model->GetParent(item) != wxDataViewItem(0) ? &m_menu_part :
+
+ wxMenu* menu = type & itInstance ? &m_menu_instance :
+ m_objects_model->GetParent(item) != wxDataViewItem(0) ? &m_menu_part :
wxGetApp().plater()->printer_technology() == ptFFF ? &m_menu_object : &m_menu_sla_object;
- append_menu_item_settings(menu);
+ if (!(type & itInstance))
+ append_menu_item_settings(menu);
wxGetApp().plater()->PopupMenu(menu);
@@ -443,15 +476,35 @@ void ObjectList::OnBeginDrag(wxDataViewEvent &event)
{
const wxDataViewItem item(event.GetItem());
- // only allow drags for item, not containers
- if (multiple_selection() || GetSelection()!=item ||
- m_objects_model->GetParent(item) == wxDataViewItem(0) ||
- m_objects_model->GetItemType(item) != itVolume ) {
+ const bool mult_sel = multiple_selection();
+
+ if (mult_sel && !selected_instances_of_same_object() ||
+ !mult_sel && (GetSelection() != item ||
+ m_objects_model->GetParent(item) == wxDataViewItem(0) ) ) {
+ event.Veto();
+ return;
+ }
+
+ const ItemType& type = m_objects_model->GetItemType(item);
+ if (!(type & (itVolume | itInstance))) {
event.Veto();
return;
}
- m_dragged_data.init(m_objects_model->GetObjectIdByItem(item), m_objects_model->GetVolumeIdByItem(item));
+ if (mult_sel)
+ {
+ m_dragged_data.init(m_objects_model->GetObjectIdByItem(item),type);
+ std::set<int>& sub_obj_idxs = m_dragged_data.inst_idxs();
+ wxDataViewItemArray sels;
+ GetSelections(sels);
+ for (auto sel : sels )
+ sub_obj_idxs.insert(m_objects_model->GetInstanceIdByItem(sel));
+ }
+ else
+ m_dragged_data.init(m_objects_model->GetObjectIdByItem(item),
+ type&itVolume ? m_objects_model->GetVolumeIdByItem(item) :
+ m_objects_model->GetInstanceIdByItem(item),
+ type);
/* Under MSW or OSX, DnD moves an item to the place of another selected item
* But under GTK, DnD moves an item between another two items.
@@ -470,31 +523,41 @@ void ObjectList::OnBeginDrag(wxDataViewEvent &event)
event.SetDragFlags(wxDrag_DefaultMove); // allows both copy and move;
}
+bool ObjectList::can_drop(const wxDataViewItem& item) const
+{
+ return m_dragged_data.type() == itInstance && !item.IsOk() ||
+ m_dragged_data.type() == itVolume && item.IsOk() &&
+ m_objects_model->GetItemType(item) == itVolume &&
+ m_dragged_data.obj_idx() == m_objects_model->GetObjectIdByItem(item);
+}
+
void ObjectList::OnDropPossible(wxDataViewEvent &event)
{
- wxDataViewItem item(event.GetItem());
+ const wxDataViewItem& item = event.GetItem();
- // only allow drags for item or background, not containers
- if (!item.IsOk() ||
- m_objects_model->GetParent(item) == wxDataViewItem(0) ||
- m_objects_model->GetItemType(item) != itVolume ||
- m_dragged_data.obj_idx() != m_objects_model->GetObjectIdByItem(item))
+ if (!can_drop(item))
event.Veto();
}
void ObjectList::OnDrop(wxDataViewEvent &event)
{
- wxDataViewItem item(event.GetItem());
+ const wxDataViewItem& item = event.GetItem();
- if (!item.IsOk() || m_objects_model->GetParent(item) == wxDataViewItem(0) ||
- m_objects_model->GetItemType(item) != itVolume ||
- m_dragged_data.obj_idx() != m_objects_model->GetObjectIdByItem(item)) {
+ if (!can_drop(item))
+ {
event.Veto();
m_dragged_data.clear();
return;
}
- const int from_volume_id = m_dragged_data.vol_idx();
+ if (m_dragged_data.type() == itInstance)
+ {
+ instances_to_separated_object(m_dragged_data.obj_idx(), m_dragged_data.inst_idxs());
+ m_dragged_data.clear();
+ return;
+ }
+
+ const int from_volume_id = m_dragged_data.sub_obj_idx();
int to_volume_id = m_objects_model->GetVolumeIdByItem(item);
// It looks like a fixed in current version of the wxWidgets
@@ -506,7 +569,7 @@ void ObjectList::OnDrop(wxDataViewEvent &event)
// if (to_volume_id > from_volume_id) to_volume_id--;
// #endif // __WXGTK__
- auto& volumes = (*m_objects)[/*m_selected_object_id*/m_dragged_data.obj_idx()]->volumes;
+ auto& volumes = (*m_objects)[m_dragged_data.obj_idx()]->volumes;
auto delta = to_volume_id < from_volume_id ? -1 : 1;
int cnt = 0;
for (int id = from_volume_id; cnt < abs(from_volume_id - to_volume_id); id += delta, cnt++)
@@ -516,7 +579,7 @@ void ObjectList::OnDrop(wxDataViewEvent &event)
m_objects_model->GetParent(item)));
m_parts_changed = true;
- parts_changed(/*m_selected_object_id*/m_dragged_data.obj_idx());
+ parts_changed(m_dragged_data.obj_idx());
m_dragged_data.clear();
}
@@ -547,6 +610,19 @@ std::vector<std::string> get_options(const bool is_part)
{
return get_options(is_part, wxGetApp().plater()->printer_technology() == ptSLA);
}
+
+const std::vector<std::string>& get_options_for_bundle(const wxString& bundle_name)
+{
+ const FreqSettingsBundle& bundle = wxGetApp().plater()->printer_technology() == ptSLA ?
+ FREQ_SETTINGS_BUNDLE_SLA : FREQ_SETTINGS_BUNDLE_FFF;
+
+ for (auto& it : bundle)
+ {
+ if (bundle_name == _(it.first))
+ return it.second;
+ }
+ return std::vector<std::string> {};
+}
// category -> vector ( option ; label )
typedef std::map< std::string, std::vector< std::pair<std::string, std::string> > > settings_menu_hierarchy;
@@ -633,16 +709,39 @@ void ObjectList::get_settings_choice(const wxString& category_name)
// Add settings item for object
- const auto item = GetSelection();
+ update_settings_item();
+}
+
+void ObjectList::get_freq_settings_choice(const wxString& bundle_name)
+{
+ const std::vector<std::string>& options = get_options_for_bundle(bundle_name);
+
+ auto opt_keys = m_config->keys();
+
+ for (auto& opt_key : options)
+ {
+ if ( find(opt_keys.begin(), opt_keys.end(), opt_key) == opt_keys.end() )
+ m_config->set_key_value(opt_key, m_default_config->option(opt_key)->clone());
+ }
+
+ // Add settings item for object
+ update_settings_item();
+}
+
+void ObjectList::update_settings_item()
+{
+ auto item = GetSelection();
if (item) {
- const auto settings_item = m_objects_model->GetSettingsItem(item);
+ if (m_objects_model->GetItemType(item) == itInstance)
+ item = m_objects_model->GetTopParent(item);
+ const auto settings_item = m_objects_model->IsSettingsItem(item) ? item : m_objects_model->GetSettingsItem(item);
select_item(settings_item ? settings_item :
m_objects_model->AddSettingsChild(item));
}
else {
auto panel = wxGetApp().sidebar().scrolled_panel();
panel->Freeze();
- wxGetApp().obj_settings()->UpdateAndShow(true);//obj_manipul()->update_settings_list();
+ wxGetApp().obj_settings()->UpdateAndShow(true);
panel->Thaw();
}
}
@@ -650,9 +749,11 @@ void ObjectList::get_settings_choice(const wxString& category_name)
void ObjectList::append_menu_item_add_generic(wxMenuItem* menu, const int type) {
auto sub_menu = new wxMenu;
+ if (wxGetApp().get_mode() == comExpert) {
append_menu_item(sub_menu, wxID_ANY, _(L("Load")) + " " + dots, "",
[this, type](wxCommandEvent&) { load_subobject(type); }, "", menu->GetMenu());
sub_menu->AppendSeparator();
+ }
std::vector<std::string> menu_items = { L("Box"), L("Cylinder"), L("Sphere"), L("Slab") };
for (auto& item : menu_items) {
@@ -678,21 +779,25 @@ void ObjectList::append_menu_items_add_volume(wxMenu* menu)
menu->Destroy(settings_id);
}
- if (wxGetApp().get_view_mode() == ConfigMenuModeSimple)
+ const ConfigOptionMode mode = wxGetApp().get_mode();
+
+ if (mode < comExpert)
{
append_menu_item(menu, wxID_ANY, _(L("Add part")), "",
[this](wxCommandEvent&) { load_subobject(ModelVolume::MODEL_PART); }, *m_bmp_vector[ModelVolume::MODEL_PART]);
+ }
+ if (mode == comSimple) {
append_menu_item(menu, wxID_ANY, _(L("Add support enforcer")), "",
- [this](wxCommandEvent&) { load_generic_subobject(_(L("Box")).ToUTF8().data(), ModelVolume::SUPPORT_ENFORCER); },
+ [this](wxCommandEvent&) { load_generic_subobject(_(L("Box")).ToUTF8().data(), ModelVolume::SUPPORT_ENFORCER); },
*m_bmp_vector[ModelVolume::SUPPORT_ENFORCER]);
append_menu_item(menu, wxID_ANY, _(L("Add support blocker")), "",
- [this](wxCommandEvent&) { load_generic_subobject(_(L("Box")).ToUTF8().data(), ModelVolume::SUPPORT_BLOCKER); },
+ [this](wxCommandEvent&) { load_generic_subobject(_(L("Box")).ToUTF8().data(), ModelVolume::SUPPORT_BLOCKER); },
*m_bmp_vector[ModelVolume::SUPPORT_BLOCKER]);
return;
}
-
- for (int type = 0; type < menu_object_types_items.size(); type++)
+
+ for (int type = mode == comExpert ? 0 : 1 ; type < menu_object_types_items.size(); type++)
{
auto& item = menu_object_types_items[type];
@@ -710,23 +815,57 @@ wxMenuItem* ObjectList::append_menu_item_split(wxMenu* menu)
[this](wxCommandEvent&) { split(); }, m_bmp_split, menu);
}
-wxMenuItem* ObjectList::append_menu_item_settings(wxMenu* menu)
+wxMenuItem* ObjectList::append_menu_item_settings(wxMenu* menu_)
{
- // Update (delete old & create new) settings popupmenu
- const auto settings_id = menu->FindItem(_("Add settings"));
+ PrusaMenu* menu = dynamic_cast<PrusaMenu*>(menu_);
+ // Delete old items from settings popupmenu
+ auto settings_id = menu->FindItem(_("Add settings"));
if (settings_id != wxNOT_FOUND)
menu->Destroy(settings_id);
- if (wxGetApp().get_view_mode() == ConfigMenuModeSimple)
+ for (auto& it : FREQ_SETTINGS_BUNDLE_FFF)
+ {
+ settings_id = menu->FindItem(_(it.first));
+ if (settings_id != wxNOT_FOUND)
+ menu->Destroy(settings_id);
+ }
+ for (auto& it : FREQ_SETTINGS_BUNDLE_SLA)
+ {
+ settings_id = menu->FindItem(_(it.first));
+ if (settings_id != wxNOT_FOUND)
+ menu->Destroy(settings_id);
+ }
+
+ menu->DestroySeparators(); // delete old separators
+
+ const auto sel_vol = get_selected_model_volume();
+ if (sel_vol && sel_vol->type() >= ModelVolume::SUPPORT_ENFORCER)
+ return nullptr;
+
+ const ConfigOptionMode mode = wxGetApp().get_mode();
+ if (mode == comSimple)
return nullptr;
+ // Create new items for settings popupmenu
+
+ menu->m_separator_frst = menu->AppendSeparator();
+
+ // Add frequently settings
+ create_freq_settings_popupmenu(menu);
+
+ if (mode == comAdvanced)
+ return nullptr;
+
+ menu->m_separator_scnd = menu->AppendSeparator();
+
+ // Add full settings list
auto menu_item = new wxMenuItem(menu, wxID_ANY, _(L("Add settings")));
menu_item->SetBitmap(m_bmp_cog);
- const auto sel_vol = get_selected_model_volume();
- if (sel_vol && sel_vol->type() >= ModelVolume::SUPPORT_ENFORCER)
- menu_item->Enable(false);
- else
+// const auto sel_vol = get_selected_model_volume();
+// if (sel_vol && sel_vol->type() >= ModelVolume::SUPPORT_ENFORCER)
+// menu_item->Enable(false);
+// else
menu_item->SetSubMenu(create_settings_popupmenu(menu));
return menu->Append(menu_item);
@@ -739,20 +878,27 @@ wxMenuItem* ObjectList::append_menu_item_change_type(wxMenu* menu)
}
-void ObjectList::create_object_popupmenu(wxMenu *menu)
+wxMenuItem* ObjectList::append_menu_item_instance_to_object(wxMenu* menu)
{
- append_menu_items_add_volume(menu);
+ return append_menu_item(menu, wxID_ANY, _(L("Set as a Separated Object")), "",
+ [this](wxCommandEvent&) { split_instances(); }, "", menu);
+}
+void ObjectList::create_object_popupmenu(wxMenu *menu)
+{
// Split object to parts
- menu->AppendSeparator();
m_menu_item_split = append_menu_item_split(menu);
-
- // Settings
menu->AppendSeparator();
+
+ // rest of a object_menu will be added later in:
+ // - append_menu_items_add_volume() -> for "Add (volumes)"
+ // - append_menu_item_settings() -> for "Add (settings)"
}
void ObjectList::create_sla_object_popupmenu(wxMenu *menu)
{
+ // rest of a object_sla_menu will be added later in:
+ // - append_menu_item_settings() -> for "Add (settings)"
}
void ObjectList::create_part_popupmenu(wxMenu *menu)
@@ -763,8 +909,13 @@ void ObjectList::create_part_popupmenu(wxMenu *menu)
menu->AppendSeparator();
append_menu_item_change_type(menu);
- // Append settings popupmenu
- menu->AppendSeparator();
+ // rest of a object_sla_menu will be added later in:
+ // - append_menu_item_settings() -> for "Add (settings)"
+}
+
+void ObjectList::create_instance_popupmenu(wxMenu*menu)
+{
+ m_menu_item_split_instances = append_menu_item_instance_to_object(menu);
}
wxMenu* ObjectList::create_settings_popupmenu(wxMenu *parent_menu)
@@ -784,6 +935,24 @@ wxMenu* ObjectList::create_settings_popupmenu(wxMenu *parent_menu)
return menu;
}
+void ObjectList::create_freq_settings_popupmenu(wxMenu *menu)
+{
+ const FreqSettingsBundle& bundle = wxGetApp().plater()->printer_technology() == ptFFF ?
+ FREQ_SETTINGS_BUNDLE_FFF : FREQ_SETTINGS_BUNDLE_SLA;
+
+ auto extruders_cnt = wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA ? 1 :
+ wxGetApp().preset_bundle->printers.get_edited_preset().config.option<ConfigOptionFloats>("nozzle_diameter")->values.size();
+
+ for (auto& it : bundle) {
+ if (it.first.empty() || it.first == "Extruders" && extruders_cnt == 1)
+ continue;
+
+ append_menu_item(menu, wxID_ANY, _(it.first), "",
+ [menu, this](wxCommandEvent& event) { get_freq_settings_choice(menu->GetLabel(event.GetId())); },
+ CATEGORY_ICON.find(it.first) == CATEGORY_ICON.end() ? wxNullBitmap : CATEGORY_ICON.at(it.first), menu);
+ }
+}
+
void ObjectList::update_opt_keys(t_config_option_keys& opt_keys)
{
auto full_current_opts = get_options(false);
@@ -843,13 +1012,15 @@ void ObjectList::load_part( ModelObject* model_object,
delta = model_object->origin_translation - object->origin_translation;
}
for (auto volume : object->volumes) {
+#if !ENABLE_VOLUMES_CENTERING_FIXES
volume->center_geometry();
+#endif // !ENABLE_VOLUMES_CENTERING_FIXES
volume->translate(delta);
auto new_volume = model_object->add_volume(*volume);
new_volume->set_type(static_cast<ModelVolume::Type>(type));
new_volume->name = boost::filesystem::path(input_file).filename().string();
- part_names.Add(new_volume->name);
+ part_names.Add(from_u8(new_volume->name));
// set a default extruder value, since user can't add it manually
new_volume->config.set_key_value("extruder", new ConfigOptionInt(0));
@@ -893,8 +1064,30 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const int
auto new_volume = (*m_objects)[obj_idx]->add_volume(mesh);
new_volume->set_type(static_cast<ModelVolume::Type>(type));
+#if !ENABLE_GENERIC_SUBPARTS_PLACEMENT
new_volume->set_offset(Vec3d(0.0, 0.0, (*m_objects)[obj_idx]->origin_translation(2) - mesh.stl.stats.min(2)));
+#endif // !ENABLE_GENERIC_SUBPARTS_PLACEMENT
+#if !ENABLE_VOLUMES_CENTERING_FIXES
new_volume->center_geometry();
+#endif // !ENABLE_VOLUMES_CENTERING_FIXES
+
+#if ENABLE_GENERIC_SUBPARTS_PLACEMENT
+ const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
+ int instance_idx = selection.get_instance_idx();
+ if (instance_idx != -1)
+ {
+ const GLVolume* v = selection.get_volume(*selection.get_volume_idxs().begin());
+ const Transform3d& inst_m = v->get_instance_transformation().get_matrix(true);
+ TriangleMesh vol_mesh(mesh);
+ vol_mesh.transform(inst_m);
+ Vec3d vol_shift = -vol_mesh.bounding_box().center();
+ vol_mesh.translate((float)vol_shift(0), (float)vol_shift(1), (float)vol_shift(2));
+ Vec3d world_mesh_bb_size = vol_mesh.bounding_box().size();
+ BoundingBoxf3 inst_bb = (*m_objects)[obj_idx]->instance_bounding_box(instance_idx);
+ Vec3d world_target = Vec3d(inst_bb.max(0), inst_bb.min(1), inst_bb.min(2)) + 0.5 * world_mesh_bb_size;
+ new_volume->set_offset(inst_m.inverse() * (world_target - v->get_instance_offset()));
+ }
+#endif // ENABLE_GENERIC_SUBPARTS_PLACEMENT
new_volume->name = name;
// set a default extruder value, since user can't add it manually
@@ -903,7 +1096,8 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const int
m_parts_changed = true;
parts_changed(obj_idx);
- select_item(m_objects_model->AddVolumeChild(GetSelection(), name, type));
+ const auto object_item = m_objects_model->GetTopParent(GetSelection());
+ select_item(m_objects_model->AddVolumeChild(object_item, from_u8(name), type));
#ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
selection_changed();
#endif //no __WXOSX__ //__WXMSW__
@@ -1031,7 +1225,7 @@ void ObjectList::split()
parent = item;
for (auto id = 0; id < model_object->volumes.size(); id++) {
- const auto vol_item = m_objects_model->AddVolumeChild(parent, model_object->volumes[id]->name,
+ const auto vol_item = m_objects_model->AddVolumeChild(parent, from_u8(model_object->volumes[id]->name),
model_object->volumes[id]->is_modifier() ?
ModelVolume::PARAMETER_MODIFIER : ModelVolume::MODEL_PART,
model_object->volumes[id]->config.has("extruder") ?
@@ -1082,13 +1276,38 @@ bool ObjectList::is_splittable()
if (!get_volume_by_item(item, volume) || !volume)
return false;
+ if (volume->is_splittable() != -1) // if is_splittable value is already known
+ return volume->is_splittable() == 0 ? false : true;
+
TriangleMeshPtrs meshptrs = volume->mesh.split();
bool splittable = meshptrs.size() > 1;
for (TriangleMesh* m : meshptrs) { delete m; }
+ volume->set_splittable(splittable ? 1 : 0);
return splittable;
}
+bool ObjectList::selected_instances_of_same_object()
+{
+ wxDataViewItemArray sels;
+ GetSelections(sels);
+
+ const int obj_idx = m_objects_model->GetObjectIdByItem(sels.front());
+
+ for (auto item : sels) {
+ if (! (m_objects_model->GetItemType(item) & itInstance) ||
+ obj_idx != m_objects_model->GetObjectIdByItem(item))
+ return false;
+ }
+ return true;
+}
+
+bool ObjectList::can_split_instances()
+{
+ const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
+ return selection.is_multiple_full_instance() || selection.is_single_full_instance();
+}
+
void ObjectList::part_settings_changed()
{
m_part_settings_changed = true;
@@ -1156,6 +1375,10 @@ void ObjectList::part_selection_changed()
else if (m_objects_model->GetItemType(item) == itInstance) {
og_name = _(L("Instance manipulation"));
update_and_show_manipulations = true;
+
+ // fill m_config by object's values
+ const int obj_idx_ = m_objects_model->GetObjectIdByItem(item);
+ m_config = &(*m_objects)[obj_idx_]->config;
}
}
@@ -1188,7 +1411,7 @@ void ObjectList::part_selection_changed()
void ObjectList::add_object_to_list(size_t obj_idx)
{
auto model_object = (*m_objects)[obj_idx];
- wxString item_name = model_object->name;
+ wxString item_name = from_u8(model_object->name);
const auto item = m_objects_model->Add(item_name,
!model_object->config.has("extruder") ? 0 :
model_object->config.option<ConfigOptionInt>("extruder")->value);
@@ -1207,8 +1430,8 @@ void ObjectList::add_object_to_list(size_t obj_idx)
if (model_object->volumes.size() > 1) {
for (auto id = 0; id < model_object->volumes.size(); id++) {
auto vol_item = m_objects_model->AddVolumeChild(item,
- model_object->volumes[id]->name,
- model_object->volumes[id]->type()/*ModelVolume::MODEL_PART*/,
+ from_u8(model_object->volumes[id]->name),
+ model_object->volumes[id]->type(),
!model_object->volumes[id]->config.has("extruder") ? 0 :
model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value,
false);
@@ -1388,7 +1611,7 @@ bool ObjectList::multiple_selection() const
void ObjectList::update_selections()
{
- auto& selection = wxGetApp().plater()->canvas3D()->get_selection();
+ const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
wxDataViewItemArray sels;
// We doesn't update selection if SettingsItem for the current object/part is selected
@@ -1474,7 +1697,7 @@ void ObjectList::update_selections()
void ObjectList::update_selections_on_canvas()
{
- auto& selection = wxGetApp().plater()->canvas3D()->get_selection();
+ GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
const int sel_cnt = GetSelectedItemsCount();
if (sel_cnt == 0) {
@@ -1698,6 +1921,48 @@ void ObjectList::update_settings_items()
UnselectAll();
}
+void ObjectList::update_object_menu()
+{
+ append_menu_items_add_volume(&m_menu_object);
+}
+
+void ObjectList::instances_to_separated_object(const int obj_idx, const std::set<int>& inst_idxs)
+{
+ // create new object from selected instance
+ ModelObject* model_object = (*m_objects)[obj_idx]->get_model()->add_object(*(*m_objects)[obj_idx]);
+ for (int inst_idx = model_object->instances.size() - 1; inst_idx >= 0; inst_idx--)
+ {
+ if (find(inst_idxs.begin(), inst_idxs.end(), inst_idx) != inst_idxs.end())
+ continue;
+ model_object->delete_instance(inst_idx);
+ }
+
+ // Add new object to the object_list
+ add_object_to_list(m_objects->size() - 1);
+
+ for (std::set<int>::const_reverse_iterator it = inst_idxs.rbegin(); it != inst_idxs.rend(); ++it)
+ {
+ // delete selected instance from the object
+ del_subobject_from_object(obj_idx, *it, itInstance);
+ delete_instance_from_list(obj_idx, *it);
+ }
+}
+
+void ObjectList::split_instances()
+{
+ const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
+ const int obj_idx = selection.get_object_idx();
+ if (obj_idx == -1)
+ return;
+
+ const int inst_idx = selection.get_instance_idx();
+ const std::set<int> inst_idxs = inst_idx < 0 ?
+ selection.get_instance_idxs() :
+ std::set<int>{ inst_idx };
+
+ instances_to_separated_object(obj_idx, inst_idxs);
+}
+
void ObjectList::ItemValueChanged(wxDataViewEvent &event)
{
if (event.GetColumn() == 0)