From 27f196be59dcf9bf3eecdc5d48dfb78cca1a5923 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 6 Sep 2018 16:36:10 +0200 Subject: [PATCH] Implement "Add generic" menu item like submenu instead of selection dialog --- xs/src/slic3r/GUI/GUI_ObjectParts.cpp | 103 ++++++++++++++++++----- xs/src/slic3r/GUI/GUI_ObjectParts.hpp | 9 +- xs/src/slic3r/GUI/LambdaObjectDialog.cpp | 55 ++++++++---- xs/src/slic3r/GUI/LambdaObjectDialog.hpp | 9 +- 4 files changed, 131 insertions(+), 45 deletions(-) diff --git a/xs/src/slic3r/GUI/GUI_ObjectParts.cpp b/xs/src/slic3r/GUI/GUI_ObjectParts.cpp index 4e92c4570..240f76612 100644 --- a/xs/src/slic3r/GUI/GUI_ObjectParts.cpp +++ b/xs/src/slic3r/GUI/GUI_ObjectParts.cpp @@ -319,15 +319,15 @@ wxBoxSizer* create_edit_object_buttons(wxWindow* win) //*** button's functions btn_load_part->Bind(wxEVT_BUTTON, [win](wxEvent&) { - on_btn_load(win); +// on_btn_load(win); }); btn_load_modifier->Bind(wxEVT_BUTTON, [win](wxEvent&) { - on_btn_load(win, true); +// on_btn_load(win, true); }); btn_load_lambda_modifier->Bind(wxEVT_BUTTON, [win](wxEvent&) { - on_btn_load(win, true, true); +// on_btn_load(win, true, true); }); btn_delete ->Bind(wxEVT_BUTTON, [](wxEvent&) { on_btn_del(); }); @@ -1010,7 +1010,7 @@ void get_settings_choice(wxMenu *menu, int id, bool is_part) } - // *** EXPERIMINT *** + // Add settings item for object const auto item = m_objects_ctrl->GetSelection(); if (item) { const auto settings_item = m_objects_model->HasSettings(item); @@ -1018,11 +1018,20 @@ void get_settings_choice(wxMenu *menu, int id, bool is_part) m_objects_model->AddSettingsChild(item)); part_selection_changed(); } - // ******************** update_settings_list(); } +void menu_item_add_generic(wxMenuItem* &menu, int id) { + auto sub_menu = new wxMenu; + + std::vector menu_items = { L("Box"), L("Cylinder"), L("Sphere"), L("Slab") }; + for (auto& item : menu_items) + sub_menu->Append(new wxMenuItem(sub_menu, ++id, _(item))); + + menu->SetSubMenu(sub_menu); +} + wxMenuItem* menu_item_split(wxMenu* menu, int id) { auto menu_item = new wxMenuItem(menu, id, _(L("Split to parts"))); menu_item->SetBitmap(m_bmp_split); @@ -1043,39 +1052,45 @@ wxMenu *create_add_part_popupmenu() wxMenu *menu = new wxMenu; std::vector menu_items = { L("Add part"), L("Add modifier"), L("Add generic") }; - wxWindowID config_id_base = wxWindow::NewControlId(menu_items.size()+2); + wxWindowID config_id_base = wxWindow::NewControlId(menu_items.size()+4+2); int i = 0; for (auto& item : menu_items) { auto menu_item = new wxMenuItem(menu, config_id_base + i, _(item)); menu_item->SetBitmap(i == 0 ? m_icon_solidmesh : m_icon_modifiermesh); - menu->Append(menu_item); + if (item == "Add generic") + menu_item_add_generic(menu_item, config_id_base + i); + menu->Append(menu_item); i++; } menu->AppendSeparator(); - auto menu_item = menu_item_split(menu, config_id_base + i); + auto menu_item = menu_item_split(menu, config_id_base + i + 4); menu->Append(menu_item); menu_item->Enable(is_splittable_object(false)); menu->AppendSeparator(); // Append settings popupmenu - menu->Append(menu_item_settings(menu, config_id_base + i + 1, false)); + menu->Append(menu_item_settings(menu, config_id_base + i + 5, false)); - wxWindow* win = get_tab_panel()->GetPage(0); - - menu->Bind(wxEVT_MENU, [config_id_base, win, menu](wxEvent &event){ + menu->Bind(wxEVT_MENU, [config_id_base, menu](wxEvent &event){ switch (event.GetId() - config_id_base) { case 0: - on_btn_load(win); + on_btn_load(); break; case 1: - on_btn_load(win, true); + on_btn_load(true); break; case 2: - on_btn_load(win, true, true); +// on_btn_load(true, true); break; - case 3: + case 3: + case 4: + case 5: + case 6: + load_lambda(menu->GetLabel(event.GetId()).ToStdString()); + break; + case 7: //3: on_btn_split(false); break; default:{ @@ -1154,9 +1169,11 @@ void show_context_menu() // ****** -void load_part( wxWindow* parent, ModelObject* model_object, +void load_part( ModelObject* model_object, wxArrayString& part_names, const bool is_modifier) { + wxWindow* parent = get_tab_panel()->GetPage(0); + wxArrayString input_files; open_model(parent, input_files); for (int i = 0; i < input_files.size(); ++i) { @@ -1194,10 +1211,10 @@ void load_part( wxWindow* parent, ModelObject* model_object, } } -void load_lambda( wxWindow* parent, ModelObject* model_object, +void load_lambda( ModelObject* model_object, wxArrayString& part_names, const bool is_modifier) { - auto dlg = new LambdaObjectDialog(parent); + auto dlg = new LambdaObjectDialog(m_objects_ctrl->GetMainWindow()); if (dlg->ShowModal() == wxID_CANCEL) { return; } @@ -1243,7 +1260,49 @@ void load_lambda( wxWindow* parent, ModelObject* model_object, m_parts_changed = true; } -void on_btn_load(wxWindow* parent, bool is_modifier /*= false*/, bool is_lambda/* = false*/) +void load_lambda(const std::string& type_name) +{ + if (m_selected_object_id < 0) return; + + auto dlg = new LambdaObjectDialog(m_objects_ctrl->GetMainWindow(), type_name); + if (dlg->ShowModal() == wxID_CANCEL) + return; + + const std::string name = "lambda-"+type_name; + TriangleMesh mesh; + + const auto params = dlg->ObjectParameters(); + if (type_name == _("Box")) + mesh = make_cube(params.dim[0], params.dim[1], params.dim[2]); + else if (type_name == _("Cylinder")) + mesh = make_cylinder(params.cyl_r, params.cyl_h); + else if (type_name == _("Sphere")) + mesh = make_sphere(params.sph_rho); + else if (type_name == _("Slab")){ + const auto& size = (*m_objects)[m_selected_object_id]->bounding_box().size(); + mesh = make_cube(size(0)*1.5, size(1)*1.5, params.slab_h); + // box sets the base coordinate at 0, 0, move to center of plate and move it up to initial_z + mesh.translate(-size(0)*1.5 / 2.0, -size(1)*1.5 / 2.0, params.slab_z); + } + mesh.repair(); + + auto new_volume = (*m_objects)[m_selected_object_id]->add_volume(mesh); + new_volume->modifier = true; + new_volume->name = name; + // set a default extruder value, since user can't add it manually + new_volume->config.set_key_value("extruder", new ConfigOptionInt(0)); + + m_parts_changed = true; + parts_changed(m_selected_object_id); + + m_objects_ctrl->Select(m_objects_model->AddChild(m_objects_ctrl->GetSelection(), + name, m_icon_modifiermesh)); +#ifdef __WXMSW__ + object_ctrl_selection_changed(); +#endif //__WXMSW__ +} + +void on_btn_load(bool is_modifier /*= false*/, bool is_lambda/* = false*/) { auto item = m_objects_ctrl->GetSelection(); if (!item) @@ -1257,9 +1316,9 @@ void on_btn_load(wxWindow* parent, bool is_modifier /*= false*/, bool is_lambda/ if (obj_idx < 0) return; wxArrayString part_names; if (is_lambda) - load_lambda(parent, (*m_objects)[obj_idx], part_names, is_modifier); + load_lambda((*m_objects)[obj_idx], part_names, is_modifier); else - load_part(parent, (*m_objects)[obj_idx], part_names, is_modifier); + load_part((*m_objects)[obj_idx], part_names, is_modifier); parts_changed(obj_idx); diff --git a/xs/src/slic3r/GUI/GUI_ObjectParts.hpp b/xs/src/slic3r/GUI/GUI_ObjectParts.hpp index 5d94ecc3d..ae12a4b2e 100644 --- a/xs/src/slic3r/GUI/GUI_ObjectParts.hpp +++ b/xs/src/slic3r/GUI/GUI_ObjectParts.hpp @@ -91,13 +91,14 @@ void set_objects_from_model(Model &model); bool is_parts_changed(); bool is_part_settings_changed(); -void load_part( wxWindow* parent, ModelObject* model_object, +void load_part( ModelObject* model_object, wxArrayString& part_names, const bool is_modifier); -void load_lambda(wxWindow* parent, ModelObject* model_object, - wxArrayString& part_names, const bool is_modifier); +void load_lambda( ModelObject* model_object, + wxArrayString& part_names, const bool is_modifier); +void load_lambda( const std::string& type_name); -void on_btn_load(wxWindow* parent, bool is_modifier = false, bool is_lambda = false); +void on_btn_load(bool is_modifier = false, bool is_lambda = false); void on_btn_del(); void on_btn_split(const bool split_part); void on_btn_move_up(); diff --git a/xs/src/slic3r/GUI/LambdaObjectDialog.cpp b/xs/src/slic3r/GUI/LambdaObjectDialog.cpp index 7543821c0..7d741be7f 100644 --- a/xs/src/slic3r/GUI/LambdaObjectDialog.cpp +++ b/xs/src/slic3r/GUI/LambdaObjectDialog.cpp @@ -10,10 +10,12 @@ namespace GUI { static wxString dots("…", wxConvUTF8); -LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent) +LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent, + const wxString type_name): + m_type_name(type_name) { Create(parent, wxID_ANY, _(L("Lambda Object")), - wxDefaultPosition, wxDefaultSize, + parent->GetScreenPosition(), wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER); // instead of double dim[3] = { 1.0, 1.0, 1.0 }; @@ -24,11 +26,20 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent) sizer = new wxBoxSizer(wxVERTICAL); // modificator options - m_modificator_options_book = new wxChoicebook( this, wxID_ANY, wxDefaultPosition, - wxDefaultSize, wxCHB_TOP); - sizer->Add(m_modificator_options_book, 1, wxEXPAND| wxALL, 10); + if (m_type_name == wxEmptyString) { + m_modificator_options_book = new wxChoicebook( this, wxID_ANY, wxDefaultPosition, + wxDefaultSize, wxCHB_TOP); + sizer->Add(m_modificator_options_book, 1, wxEXPAND | wxALL, 10); + } + else { + m_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize); + sizer->Add(m_panel, 1, wxEXPAND | wxALL, 10); + } + ConfigOptionDef def; + def.width = 70; auto optgroup = init_modificator_options_page(_(L("Box"))); + if (optgroup){ optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){ int opt_id = opt_key == "l" ? 0 : opt_key == "w" ? 1 : @@ -37,8 +48,6 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent) object_parameters.dim[opt_id] = boost::any_cast(value); }; - ConfigOptionDef def; - def.width = 70; def.type = coFloat; def.default_value = new ConfigOptionFloat{ 1.0 }; def.label = L("L"); @@ -52,8 +61,10 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent) def.label = L("H"); option = Option(def, "h"); optgroup->append_single_option_line(option); + } optgroup = init_modificator_options_page(_(L("Cylinder"))); + if (optgroup){ optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){ int val = boost::any_cast(value); if (opt_key == "cyl_r") @@ -66,14 +77,16 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent) def.type = coInt; def.default_value = new ConfigOptionInt{ 1 }; def.label = L("Radius"); - option = Option(def, "cyl_r"); + auto option = Option(def, "cyl_r"); optgroup->append_single_option_line(option); def.label = L("Height"); option = Option(def, "cyl_h"); optgroup->append_single_option_line(option); + } optgroup = init_modificator_options_page(_(L("Sphere"))); + if (optgroup){ optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){ if (opt_key == "sph_rho") object_parameters.sph_rho = boost::any_cast(value); @@ -83,10 +96,12 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent) def.type = coFloat; def.default_value = new ConfigOptionFloat{ 1.0 }; def.label = L("Rho"); - option = Option(def, "sph_rho"); + auto option = Option(def, "sph_rho"); optgroup->append_single_option_line(option); + } optgroup = init_modificator_options_page(_(L("Slab"))); + if (optgroup){ optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){ double val = boost::any_cast(value); if (opt_key == "slab_z") @@ -96,13 +111,16 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent) else return; }; + def.type = coFloat; + def.default_value = new ConfigOptionFloat{ 1.0 }; def.label = L("H"); - option = Option(def, "slab_h"); + auto option = Option(def, "slab_h"); optgroup->append_single_option_line(option); def.label = L("Initial Z"); option = Option(def, "slab_z"); optgroup->append_single_option_line(option); + } Bind(wxEVT_CHOICEBOOK_PAGE_CHANGED, ([this](wxCommandEvent e) { @@ -127,8 +145,7 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent) } })); - - auto button_sizer = CreateStdDialogButtonSizer(wxOK | wxCANCEL); + const auto button_sizer = CreateStdDialogButtonSizer(wxOK | wxCANCEL); wxButton* btn_OK = static_cast(FindWindowById(wxID_OK, this)); btn_OK->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { @@ -155,9 +172,11 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent) // Called from the constructor. // Create a panel for a rectangular / circular / custom bed shape. -ConfigOptionsGroupShp LambdaObjectDialog::init_modificator_options_page(wxString title){ +ConfigOptionsGroupShp LambdaObjectDialog::init_modificator_options_page(const wxString& title){ + if (!m_type_name.IsEmpty() && m_type_name != title) + return nullptr; - auto panel = new wxPanel(m_modificator_options_book); + auto panel = m_type_name.IsEmpty() ? new wxPanel(m_modificator_options_book) : m_panel; ConfigOptionsGroupShp optgroup; optgroup = std::make_shared(panel, _(L("Add")) + " " +title + " " +dots); @@ -165,8 +184,12 @@ ConfigOptionsGroupShp LambdaObjectDialog::init_modificator_options_page(wxString m_optgroups.push_back(optgroup); - panel->SetSizerAndFit(optgroup->sizer); - m_modificator_options_book->AddPage(panel, title); + if (m_type_name.IsEmpty()) { + panel->SetSizerAndFit(optgroup->sizer); + m_modificator_options_book->AddPage(panel, title); + } + else + panel->SetSizer(optgroup->sizer); return optgroup; } diff --git a/xs/src/slic3r/GUI/LambdaObjectDialog.hpp b/xs/src/slic3r/GUI/LambdaObjectDialog.hpp index a70c12449..d9e2e430a 100644 --- a/xs/src/slic3r/GUI/LambdaObjectDialog.hpp +++ b/xs/src/slic3r/GUI/LambdaObjectDialog.hpp @@ -14,16 +14,19 @@ namespace GUI using ConfigOptionsGroupShp = std::shared_ptr; class LambdaObjectDialog : public wxDialog { - wxChoicebook* m_modificator_options_book; + wxChoicebook* m_modificator_options_book = nullptr; std::vector m_optgroups; + wxString m_type_name; + wxPanel* m_panel = nullptr; public: - LambdaObjectDialog(wxWindow* parent); + LambdaObjectDialog(wxWindow* parent, + const wxString type_name = wxEmptyString); ~LambdaObjectDialog(){} bool CanClose() { return true; } // ??? OBJECT_PARAMETERS& ObjectParameters(){ return object_parameters; } - ConfigOptionsGroupShp init_modificator_options_page(wxString title); + ConfigOptionsGroupShp init_modificator_options_page(const wxString& title); // Note whether the window was already closed, so a pending update is not executed. bool m_already_closed = false;