diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index d7b9b92f1..9b9cc74c6 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -1975,7 +1975,7 @@ sub _get_export_file { # (i.e. when an object is added/removed/moved/rotated/scaled) sub update { my ($self, $force_autocenter) = @_; - + $self->Freeze; if (wxTheApp->{app_config}->get("autocenter") || $force_autocenter) { $self->{model}->center_instances_around_point($self->bed_centerf); } @@ -2001,6 +2001,7 @@ sub update { Slic3r::GUI::_3DScene::reload_scene($self->{canvas3D}, 0); $self->{preview3D}->reset_gcode_preview_data if $self->{preview3D}; $self->{preview3D}->reload_print if $self->{preview3D}; + $self->Thaw; } # When a printer technology is changed, the UI needs to be updated to show/hide needed preset combo boxes. diff --git a/xs/src/slic3r/GUI/GUI_ObjectParts.cpp b/xs/src/slic3r/GUI/GUI_ObjectParts.cpp index 1820af155..c7d7f35f8 100644 --- a/xs/src/slic3r/GUI/GUI_ObjectParts.cpp +++ b/xs/src/slic3r/GUI/GUI_ObjectParts.cpp @@ -780,9 +780,9 @@ void object_ctrl_context_menu() { wxDataViewItem item; wxDataViewColumn* col; - printf("object_ctrl_context_menu\n"); +// printf("object_ctrl_context_menu\n"); const wxPoint pt = get_mouse_position_in_control(); - printf("mouse_position_in_control: x = %d, y = %d\n", pt.x, pt.y); +// printf("mouse_position_in_control: x = %d, y = %d\n", pt.x, pt.y); m_objects_ctrl->HitTest(pt, item, col); if (!item) #ifdef __WXOSX__ // #ys_FIXME temporary workaround for OSX @@ -796,9 +796,9 @@ void object_ctrl_context_menu() #else return; #endif // __WXOSX__ - printf("item exists\n"); +// printf("item exists\n"); const wxString title = col->GetTitle(); - printf("title = *%s*\n", title.data().AsChar()); +// printf("title = *%s*\n", title.data().AsChar()); if (title == " ") show_context_menu(); @@ -844,6 +844,15 @@ void object_ctrl_item_value_change(wxDataViewEvent& event) } } +void show_manipulation_og(const bool show) +{ + wxGridSizer* grid_sizer = get_optgroup(ogFrequentlyObjectSettings)->get_grid_sizer(); + if (show == grid_sizer->IsShown(2)) + return; + for (size_t id = 2; id < 12; id++) + grid_sizer->Show(id, show); +} + //update_optgroup void update_settings_list() { @@ -864,8 +873,11 @@ void update_settings_list() m_option_sizer->Clear(true); - if (m_config) + bool show_manipulations = true; + const auto item = m_objects_ctrl->GetSelection(); + if (m_config && m_objects_model->IsSettingsItem(item)) { + show_manipulations = false; auto extra_column = [](wxWindow* parent, const Line& line) { auto opt_key = (line.get_options())[0].opt_id; //we assume that we have one option per line @@ -884,49 +896,57 @@ void update_settings_list() std::map> cat_options; auto opt_keys = (*m_config)->keys(); - if (opt_keys.size() == 1 && opt_keys[0] == "extruder") - return; + if (!(opt_keys.size() == 1 && opt_keys[0] == "extruder")) + // return; + { + auto extruders_cnt = get_preset_bundle()->printers.get_selected_preset().printer_technology() == ptSLA ? 1 : + get_preset_bundle()->printers.get_edited_preset().config.option("nozzle_diameter")->values.size(); - auto extruders_cnt = get_preset_bundle()->printers.get_selected_preset().printer_technology() == ptSLA ? 1 : - get_preset_bundle()->printers.get_edited_preset().config.option("nozzle_diameter")->values.size(); + for (auto& opt_key : opt_keys) { + auto category = (*m_config)->def()->get(opt_key)->category; + if (category.empty() || + (category == "Extruders" && extruders_cnt == 1)) continue; - for (auto& opt_key : opt_keys) { - auto category = (*m_config)->def()->get(opt_key)->category; - if (category.empty() || - (category == "Extruders" && extruders_cnt==1)) continue; + std::vector< std::string > new_category; - std::vector< std::string > new_category; - - auto& cat_opt = cat_options.find(category) == cat_options.end() ? new_category : cat_options.at(category); - cat_opt.push_back(opt_key); - if (cat_opt.size() == 1) - cat_options[category] = cat_opt; - } + auto& cat_opt = cat_options.find(category) == cat_options.end() ? new_category : cat_options.at(category); + cat_opt.push_back(opt_key); + if (cat_opt.size() == 1) + cat_options[category] = cat_opt; + } - m_og_settings.resize(0); - for (auto& cat : cat_options) { - if (cat.second.size() == 1 && cat.second[0] == "extruder") - continue; + m_og_settings.resize(0); + for (auto& cat : cat_options) { + if (cat.second.size() == 1 && cat.second[0] == "extruder") + continue; - auto optgroup = std::make_shared(parent, cat.first, *m_config, false, ogDEFAULT, extra_column); - optgroup->label_width = 100; - optgroup->sidetext_width = 70; + auto optgroup = std::make_shared(parent, cat.first, *m_config, false, ogDEFAULT, extra_column); + optgroup->label_width = 150; + optgroup->sidetext_width = 70; - for (auto& opt : cat.second) - { - if (opt == "extruder") - continue; - Option option = optgroup->get_option(opt); - option.opt.width = 70; - optgroup->append_single_option_line(option); - } - optgroup->reload_config(); - m_option_sizer->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 0); - m_og_settings.push_back(optgroup); - } + for (auto& opt : cat.second) + { + if (opt == "extruder") + continue; + Option option = optgroup->get_option(opt); + option.opt.width = 70; + optgroup->append_single_option_line(option); + } + optgroup->reload_config(); + m_option_sizer->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 0); + m_og_settings.push_back(optgroup); + } + + if (m_og_settings.empty()) { + m_objects_ctrl->Select(m_objects_model->Delete(item)); + show_manipulations = true; + } + } } + show_manipulation_og(show_manipulations); + #ifdef __linux__ no_updates.reset(nullptr); #endif @@ -937,7 +957,7 @@ void update_settings_list() void get_settings_choice(wxMenu *menu, int id, bool is_part) { - auto category_name = menu->GetLabel(id); + const auto category_name = menu->GetLabel(id); wxArrayString names; wxArrayInt selections; @@ -987,12 +1007,12 @@ void get_settings_choice(wxMenu *menu, int id, bool is_part) // *** EXPERIMINT *** -// const auto item = m_objects_ctrl->GetSelection(); -// if (item) -// { -// if (!m_objects_model->HasSettings(item)) -// m_objects_model->AddSettingsChild(item); -// } + const auto item = m_objects_ctrl->GetSelection(); + if (item) { + const auto settings_item = m_objects_model->HasSettings(item); + m_objects_ctrl->Select(settings_item ? settings_item : + m_objects_model->AddSettingsChild(item)); + } // ******************** update_settings_list(); @@ -1124,6 +1144,8 @@ void show_context_menu() const auto item = m_objects_ctrl->GetSelection(); if (item) { + if (m_objects_model->IsSettingsItem(item)) + return; const auto menu = m_objects_model->GetParent(item) == wxDataViewItem(0) ? create_add_part_popupmenu() : create_part_settings_popupmenu(); @@ -1251,36 +1273,58 @@ void on_btn_load(wxWindow* parent, bool is_modifier /*= false*/, bool is_lambda/ #endif //__WXMSW__ } +void remove_settings_from_config() +{ + auto opt_keys = (*m_config)->keys(); + if (opt_keys.size() == 1 && opt_keys[0] == "extruder") + return; + int extruder = -1; + if ((*m_config)->has("extruder")) + extruder = (*m_config)->option("extruder")->value; + + (*m_config)->clear(); + + if (extruder >=0 ) + (*m_config)->set_key_value("extruder", new ConfigOptionInt(extruder)); +} + +bool remove_subobject_from_object(const int volume_id) +{ + const auto volume = (*m_objects)[m_selected_object_id]->volumes[volume_id]; + + // if user is deleting the last solid part, throw error + int solid_cnt = 0; + for (auto vol : (*m_objects)[m_selected_object_id]->volumes) + if (!vol->modifier) + ++solid_cnt; + if (!volume->modifier && solid_cnt == 1) { + Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last solid part from this object."))); + return false; + } + + (*m_objects)[m_selected_object_id]->delete_volume(volume_id); + m_parts_changed = true; + + parts_changed(m_selected_object_id); + return true; +} + void on_btn_del() { auto item = m_objects_ctrl->GetSelection(); if (!item) return; - auto volume_id = m_objects_model->GetVolumeIdByItem(item); - if (volume_id < 0) + const auto volume_id = m_objects_model->GetVolumeIdByItem(item); + if (volume_id ==-1) return; - auto volume = (*m_objects)[m_selected_object_id]->volumes[volume_id]; - - // if user is deleting the last solid part, throw error - int solid_cnt = 0; - for (auto vol : (*m_objects)[m_selected_object_id]->volumes) - if (!vol->modifier) - ++solid_cnt; - if (!volume->modifier && solid_cnt == 1) { - Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last solid part from this object."))); - return; - } - - (*m_objects)[m_selected_object_id]->delete_volume(volume_id); - m_parts_changed = true; - - parts_changed(m_selected_object_id); + + if (volume_id ==-2) + remove_settings_from_config(); + else if (!remove_subobject_from_object(volume_id)) + return; m_objects_ctrl->Select(m_objects_model->Delete(item)); part_selection_changed(); -// #ifdef __WXMSW__ -// object_ctrl_selection_changed(); -// #endif //__WXMSW__ } void on_btn_split(const bool split_part) @@ -1404,33 +1448,49 @@ void part_selection_changed() auto item = m_objects_ctrl->GetSelection(); int obj_idx = -1; auto og = get_optgroup(ogFrequentlyObjectSettings); + m_config = nullptr; + wxString object_name = wxEmptyString; if (item) { + const bool is_settings_item = m_objects_model->IsSettingsItem(item); bool is_part = false; - if (m_objects_model->GetParent(item) == wxDataViewItem(0)) { + wxString og_name = wxEmptyString; + if (m_objects_model->GetParent(item) == wxDataViewItem(0)) { obj_idx = m_objects_model->GetIdByItem(item); - og->set_name(" " + _(L("Object Settings")) + " "); + og_name = _(L("Object manipulation")); m_config = std::make_shared(&(*m_objects)[obj_idx]->config); } else { auto parent = m_objects_model->GetParent(item); - // Take ID of the parent object to "inform" perl-side which object have to be selected on the scene + // Take ID of the parent object to "inform" perl-side which object have to be selected on the scene obj_idx = m_objects_model->GetIdByItem(parent); - og->set_name(" " + _(L("Part Settings")) + " "); - is_part = true; - auto volume_id = m_objects_model->GetVolumeIdByItem(item); - m_config = std::make_shared(&(*m_objects)[obj_idx]->volumes[volume_id]->config); + if (is_settings_item) { + if (m_objects_model->GetParent(parent) == wxDataViewItem(0)) { + og_name = _(L("Object Settings to modify")); + m_config = std::make_shared(&(*m_objects)[obj_idx]->config); + } + else { + og_name = _(L("Part Settings to modify")); + is_part = true; + auto main_parent = m_objects_model->GetParent(parent); + obj_idx = m_objects_model->GetIdByItem(main_parent); + const auto volume_id = m_objects_model->GetVolumeIdByItem(parent); + m_config = std::make_shared(&(*m_objects)[obj_idx]->volumes[volume_id]->config); + } + } + else { + og_name = _(L("Part manipulation")); + is_part = true; + const auto volume_id = m_objects_model->GetVolumeIdByItem(item); + m_config = std::make_shared(&(*m_objects)[obj_idx]->volumes[volume_id]->config); + } } - auto config = m_config; - og->set_value("object_name", m_objects_model->GetName(item)); + og->set_name(" " + og_name + " "); + object_name = m_objects_model->GetName(item); m_default_config = std::make_shared(*DynamicPrintConfig::new_from_defaults_keys(get_options(is_part))); } - else { - wxString empty_str = wxEmptyString; - og->set_value("object_name", empty_str); - m_config = nullptr; - } + og->set_value("object_name", object_name); update_settings_list(); @@ -1609,7 +1669,7 @@ void on_begin_drag(wxDataViewEvent &event) wxDataViewItem item(event.GetItem()); // only allow drags for item, not containers - if (m_objects_model->GetParent(item) == wxDataViewItem(0)) { + if (m_objects_model->GetParent(item) == wxDataViewItem(0) || m_objects_model->IsSettingsItem(item)) { event.Veto(); return; } @@ -1633,7 +1693,7 @@ void on_drop_possible(wxDataViewEvent &event) // only allow drags for item or background, not containers if (item.IsOk() && m_objects_model->GetParent(item) == wxDataViewItem(0) || - event.GetDataFormat() != wxDF_UNICODETEXT) + event.GetDataFormat() != wxDF_UNICODETEXT || m_objects_model->IsSettingsItem(item)) event.Veto(); } @@ -1643,7 +1703,7 @@ void on_drop(wxDataViewEvent &event) // only allow drops for item, not containers if (item.IsOk() && m_objects_model->GetParent(item) == wxDataViewItem(0) || - event.GetDataFormat() != wxDF_UNICODETEXT) { + event.GetDataFormat() != wxDF_UNICODETEXT || m_objects_model->IsSettingsItem(item)) { event.Veto(); return; } diff --git a/xs/src/slic3r/GUI/OptionsGroup.cpp b/xs/src/slic3r/GUI/OptionsGroup.cpp index 339c7358f..f2cfbd74e 100644 --- a/xs/src/slic3r/GUI/OptionsGroup.cpp +++ b/xs/src/slic3r/GUI/OptionsGroup.cpp @@ -158,7 +158,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/* // if we have an extra column, build it if (extra_column) { if (extra_column) { - grid_sizer->Add(extra_column(parent(), line), 0, wxALIGN_CENTER_VERTICAL, 0); + grid_sizer->Add(extra_column(parent(), line), 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 3); } else { // if the callback provides no sizer for the extra cell, put a spacer diff --git a/xs/src/slic3r/GUI/wxExtensions.cpp b/xs/src/slic3r/GUI/wxExtensions.cpp index 2588dd3d6..a975ac4d6 100644 --- a/xs/src/slic3r/GUI/wxExtensions.cpp +++ b/xs/src/slic3r/GUI/wxExtensions.cpp @@ -397,23 +397,26 @@ wxDataViewItem PrusaObjectDataViewModel::AddChild( const wxDataViewItem &parent_ PrusaObjectDataViewModelNode *root = (PrusaObjectDataViewModelNode*)parent_item.GetID(); if (!root) return wxDataViewItem(0); - wxString extruder_str = extruder == 0 ? "default" : wxString::Format("%d", extruder); + const wxString extruder_str = extruder == 0 ? "default" : wxString::Format("%d", extruder); - if (root->GetChildren().Count() == 0 && create_frst_child) + if (create_frst_child && (root->GetChildren().Count() == 0 || + (root->GetChildren().Count() == 1 && root->GetChildren().Item(0)->m_type == "settings"))) { - auto icon_solid_mesh = wxIcon(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("package.png")), wxBITMAP_TYPE_PNG); - auto node = new PrusaObjectDataViewModelNode(root, root->m_name, icon_solid_mesh, extruder_str, 0); + const auto icon_solid_mesh = wxIcon(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG); + const auto node = new PrusaObjectDataViewModelNode(root, root->m_name, icon_solid_mesh, extruder_str, 0); root->Append(node); // notify control - wxDataViewItem child((void*)node); + const wxDataViewItem child((void*)node); ItemAdded(parent_item, child); } - auto volume_id = root->GetChildCount(); - auto node = new PrusaObjectDataViewModelNode(root, name, icon, extruder_str, volume_id); + const auto volume_id = root->GetChildren().Item(0)->m_type == "settings" ? + root->GetChildCount() - 1 : root->GetChildCount(); + + const auto node = new PrusaObjectDataViewModelNode(root, name, icon, extruder_str, volume_id); root->Append(node); // notify control - wxDataViewItem child((void*)node); + const wxDataViewItem child((void*)node); ItemAdded(parent_item, child); return child; } @@ -455,7 +458,7 @@ wxDataViewItem PrusaObjectDataViewModel::Delete(const wxDataViewItem &item) //update volume_id value for remaining child-nodes auto children = node_parent->GetChildren(); - for (size_t i = 0; i < node_parent->GetChildCount(); i++) + for (size_t i = 0; i < node_parent->GetChildCount() && v_id>=0; i++) { auto volume_id = children[i]->GetVolumeId(); if (volume_id > v_id) @@ -684,20 +687,25 @@ wxDataViewItem PrusaObjectDataViewModel::ReorganizeChildren(int current_volume_i if (!node_parent) // happens if item.IsOk()==false return ret_item; - PrusaObjectDataViewModelNode *deleted_node = node_parent->GetNthChild(current_volume_id); + const size_t shift = node_parent->GetChildren().Item(0)->m_type == "settings" ? 1 : 0; + + PrusaObjectDataViewModelNode *deleted_node = node_parent->GetNthChild(current_volume_id+shift); node_parent->GetChildren().Remove(deleted_node); ItemDeleted(parent, wxDataViewItem(deleted_node)); - node_parent->Insert(deleted_node, new_volume_id); + node_parent->Insert(deleted_node, new_volume_id+shift); ItemAdded(parent, wxDataViewItem(deleted_node)); + const auto settings_item = HasSettings(wxDataViewItem(deleted_node)); + if (settings_item) + ItemAdded(wxDataViewItem(deleted_node), settings_item); //update volume_id value for child-nodes auto children = node_parent->GetChildren(); int id_frst = current_volume_id < new_volume_id ? current_volume_id : new_volume_id; int id_last = current_volume_id > new_volume_id ? current_volume_id : new_volume_id; for (int id = id_frst; id <= id_last; ++id) - children[id]->SetVolumeId(id); + children[id+shift]->SetVolumeId(id); - return wxDataViewItem(node_parent->GetNthChild(new_volume_id)); + return wxDataViewItem(node_parent->GetNthChild(new_volume_id+shift)); } bool PrusaObjectDataViewModel::IsEnabled(const wxDataViewItem &item, unsigned int col) const @@ -759,20 +767,28 @@ unsigned int PrusaObjectDataViewModel::GetChildren(const wxDataViewItem &parent, return count; } -bool PrusaObjectDataViewModel::HasSettings(const wxDataViewItem &item) const +wxDataViewItem PrusaObjectDataViewModel::HasSettings(const wxDataViewItem &item) const { if (!item.IsOk()) - return false; + return wxDataViewItem(0); PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); if (node->GetChildCount() == 0) - return false; + return wxDataViewItem(0); auto& children = node->GetChildren(); if (children[0]->m_type == "settings") - return true; + return wxDataViewItem((void*)children[0]);; - return false; + return wxDataViewItem(0); +} + +bool PrusaObjectDataViewModel::IsSettingsItem(const wxDataViewItem &item) const +{ + if (!item.IsOk()) + return false; + PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); + return node->m_type == "settings"; } // ---------------------------------------------------------------------------- diff --git a/xs/src/slic3r/GUI/wxExtensions.hpp b/xs/src/slic3r/GUI/wxExtensions.hpp index 13fc764ce..3ead72f2f 100644 --- a/xs/src/slic3r/GUI/wxExtensions.hpp +++ b/xs/src/slic3r/GUI/wxExtensions.hpp @@ -195,7 +195,7 @@ public: PrusaObjectDataViewModelNode( PrusaObjectDataViewModelNode* parent) : m_parent(parent), - m_name("SETTINGS LIST"), + m_name("Settings to modified"), m_copy(wxEmptyString), m_type("settings"), m_extruder(wxEmptyString) {} @@ -362,7 +362,7 @@ public: wxDataViewItem AddChild(const wxDataViewItem &parent_item, const wxString &name, const wxIcon& icon, - const int = 0, + const int extruder = 0, const bool create_frst_child = true); wxDataViewItem AddSettingsChild(const wxDataViewItem &parent_item); wxDataViewItem Delete(const wxDataViewItem &item); @@ -409,7 +409,8 @@ public: // In our case it is an item with all columns virtual bool HasContainerColumns(const wxDataViewItem& WXUNUSED(item)) const override { return true; } - bool HasSettings(const wxDataViewItem &item) const; + wxDataViewItem HasSettings(const wxDataViewItem &item) const; + bool IsSettingsItem(const wxDataViewItem &item) const; };