diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 9928e4334..f8f7cb0bc 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4588,11 +4588,19 @@ bool GLCanvas3D::_init_toolbar() if (!m_toolbar.add_separator()) return false; - item.name = "split"; - item.tooltip = GUI::L_str("Split"); + item.name = "splitobjects"; + item.tooltip = GUI::L_str("Split to objects"); item.sprite_id = 6; item.is_toggable = false; - item.action_event = EVT_GLTOOLBAR_SPLIT; + item.action_event = EVT_GLTOOLBAR_SPLIT_OBJECTS; + if (!m_toolbar.add_item(item)) + return false; + + item.name = "splitvolumes"; + item.tooltip = GUI::L_str("Split to parts"); + item.sprite_id = 6; + item.is_toggable = false; + item.action_event = EVT_GLTOOLBAR_SPLIT_VOLUMES; if (!m_toolbar.add_item(item)) return false; diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index 2f75d43fd..0cf34436d 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -848,6 +848,25 @@ void GLGizmoScale3D::on_render(const GLCanvas3D::Selection& selection) const void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const #endif // ENABLE_EXTENDED_SELECTION { +#if ENABLE_EXTENDED_SELECTION + bool single_instance = selection.is_single_full_instance(); + Vec3f scale = single_instance ? 100.0f * selection.get_volume(*selection.get_volume_idxs().begin())->get_scaling_factor().cast() : 100.0f * m_scale.cast(); + + if ((single_instance && ((m_hover_id == 0) || (m_hover_id == 1))) || m_grabbers[0].dragging || m_grabbers[1].dragging) + set_tooltip("X: " + format(scale(0), 4) + "%"); + else if ((single_instance && ((m_hover_id == 2) || (m_hover_id == 3))) || m_grabbers[2].dragging || m_grabbers[3].dragging) + set_tooltip("Y: " + format(scale(1), 4) + "%"); + else if ((single_instance && ((m_hover_id == 4) || (m_hover_id == 5))) || m_grabbers[4].dragging || m_grabbers[5].dragging) + set_tooltip("Z: " + format(scale(2), 4) + "%"); + else if ((single_instance && ((m_hover_id == 6) || (m_hover_id == 7) || (m_hover_id == 8) || (m_hover_id == 9))) + || m_grabbers[6].dragging || m_grabbers[7].dragging || m_grabbers[8].dragging || m_grabbers[9].dragging) + { + std::string tooltip = "X: " + format(scale(0), 4) + "%\n"; + tooltip += "Y: " + format(scale(1), 4) + "%\n"; + tooltip += "Z: " + format(scale(2), 4) + "%"; + set_tooltip(tooltip); + } +#else if (m_grabbers[0].dragging || m_grabbers[1].dragging) set_tooltip("X: " + format(100.0f * m_scale(0), 4) + "%"); else if (m_grabbers[2].dragging || m_grabbers[3].dragging) @@ -861,6 +880,7 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const tooltip += "Z: " + format(100.0f * m_scale(2), 4) + "%"; set_tooltip(tooltip); } +#endif // ENABLE_EXTENDED_SELECTION ::glEnable(GL_DEPTH_TEST); @@ -870,7 +890,7 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const Vec3d angles = Vec3d::Zero(); Transform3d offsets_transform = Transform3d::Identity(); - if (selection.is_from_single_instance()) + if (single_instance) { // calculate bounding box in instance local reference system const GLCanvas3D::Selection::IndicesList& idxs = selection.get_volume_idxs(); @@ -1241,6 +1261,13 @@ void GLGizmoMove3D::on_start_dragging(const BoundingBoxf3& box) } } +#if ENABLE_EXTENDED_SELECTION +void GLGizmoMove3D::on_stop_dragging() +{ + m_displacement = Vec3d::Zero(); +} +#endif // ENABLE_EXTENDED_SELECTION + void GLGizmoMove3D::on_update(const Linef3& mouse_ray) { #if ENABLE_EXTENDED_SELECTION @@ -1267,12 +1294,15 @@ void GLGizmoMove3D::on_render(const BoundingBoxf3& box) const #endif // ENABLE_EXTENDED_SELECTION { #if ENABLE_EXTENDED_SELECTION - if (m_grabbers[0].dragging) - set_tooltip("X: " + format(m_displacement(0), 2)); - else if (m_grabbers[1].dragging) - set_tooltip("Y: " + format(m_displacement(1), 2)); - else if (m_grabbers[2].dragging) - set_tooltip("Z: " + format(m_displacement(2), 2)); + bool show_position = selection.is_single_full_instance(); + const Vec3d& position = selection.get_bounding_box().center(); + + if ((show_position && (m_hover_id == 0)) || m_grabbers[0].dragging) + set_tooltip("X: " + format(show_position ? position(0) : m_displacement(0), 2)); + else if ((show_position && (m_hover_id == 1)) || m_grabbers[1].dragging) + set_tooltip("Y: " + format(show_position ? position(1) : m_displacement(1), 2)); + else if ((show_position && (m_hover_id == 2)) || m_grabbers[2].dragging) + set_tooltip("Z: " + format(show_position ? position(2) : m_displacement(2), 2)); #else if (m_grabbers[0].dragging) set_tooltip("X: " + format(m_position(0), 2)); diff --git a/src/slic3r/GUI/GLGizmo.hpp b/src/slic3r/GUI/GLGizmo.hpp index 1f2b77ab8..38f72598e 100644 --- a/src/slic3r/GUI/GLGizmo.hpp +++ b/src/slic3r/GUI/GLGizmo.hpp @@ -391,6 +391,7 @@ protected: virtual bool on_init(); #if ENABLE_EXTENDED_SELECTION virtual void on_start_dragging(const GLCanvas3D::Selection& selection); + virtual void on_stop_dragging(); #else virtual void on_start_dragging(const BoundingBoxf3& box); #endif // ENABLE_EXTENDED_SELECTION diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index e094e1105..71ff3cf48 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -22,7 +22,8 @@ wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_ARRANGE, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_MORE, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_FEWER, SimpleEvent); -wxDEFINE_EVENT(EVT_GLTOOLBAR_SPLIT, SimpleEvent); +wxDEFINE_EVENT(EVT_GLTOOLBAR_SPLIT_OBJECTS, SimpleEvent); +wxDEFINE_EVENT(EVT_GLTOOLBAR_SPLIT_VOLUMES, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_CUT, SimpleEvent); #if !ENABLE_EXTENDED_SELECTION wxDEFINE_EVENT(EVT_GLTOOLBAR_SETTINGS, SimpleEvent); diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp index 216171753..9f3853530 100644 --- a/src/slic3r/GUI/GLToolbar.hpp +++ b/src/slic3r/GUI/GLToolbar.hpp @@ -22,7 +22,8 @@ wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent); wxDECLARE_EVENT(EVT_GLTOOLBAR_ARRANGE, SimpleEvent); wxDECLARE_EVENT(EVT_GLTOOLBAR_MORE, SimpleEvent); wxDECLARE_EVENT(EVT_GLTOOLBAR_FEWER, SimpleEvent); -wxDECLARE_EVENT(EVT_GLTOOLBAR_SPLIT, SimpleEvent); +wxDECLARE_EVENT(EVT_GLTOOLBAR_SPLIT_OBJECTS, SimpleEvent); +wxDECLARE_EVENT(EVT_GLTOOLBAR_SPLIT_VOLUMES, SimpleEvent); wxDECLARE_EVENT(EVT_GLTOOLBAR_CUT, SimpleEvent); #if !ENABLE_EXTENDED_SELECTION wxDECLARE_EVENT(EVT_GLTOOLBAR_SETTINGS, SimpleEvent); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index c1683bba3..cabb57428 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -653,7 +653,7 @@ void GUI_App::load_current_presets() Sidebar& GUI_App::sidebar() { - return mainframe->m_plater->sidebar(); + return plater_->sidebar(); } ObjectManipulation* GUI_App::obj_manipul() @@ -668,17 +668,17 @@ ObjectList* GUI_App::obj_list() Plater* GUI_App::plater() { - return mainframe->m_plater; + return plater_; } wxGLCanvas* GUI_App::canvas3D() { - return mainframe->m_plater->canvas3D(); + return plater_->canvas3D(); } ModelObjectPtrs* GUI_App::model_objects() { - return &mainframe->m_plater->model().objects; + return &plater_->model().objects; } wxNotebook* GUI_App::tab_panel() const diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 52d582690..dcb3685d1 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -139,6 +139,7 @@ public: PresetBundle* preset_bundle{ nullptr }; PresetUpdater* preset_updater{ nullptr }; MainFrame* mainframe{ nullptr }; + Plater* plater_{ nullptr }; wxNotebook* tab_panel() const ; diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 8dd8ac3e2..c15532d70 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -139,6 +139,7 @@ void MainFrame::init_tabpanel() if (!m_no_plater) { m_plater = new Slic3r::GUI::Plater(m_tabpanel, this); + wxGetApp().plater_ = m_plater; m_tabpanel->AddPage(m_plater, _(L("Plater"))); } @@ -149,18 +150,6 @@ void MainFrame::init_tabpanel() // or when the preset's "modified" status changes. Bind(EVT_TAB_PRESETS_CHANGED, &MainFrame::on_presets_changed, this); - - // The following event is emited by the C++ Tab implementation on object selection change. -// EVT_COMMAND($self, -1, $OBJECT_SELECTION_CHANGED_EVENT, sub { -// auto obj_idx = event->GetId(); -// // my $child = $event->GetInt == 1 ? 1 : undef; -// // $self->{plater}->select_object($obj_idx < 0 ? undef : $obj_idx, $child); -// // $self->{plater}->item_changed_selection($obj_idx); -// -// auto vol_idx = event->GetInt(); -// m_plater->select_object_from_cpp(obj_idx < 0 ? undef : obj_idx, vol_idx < 0 ? -1 : vol_idx); -// }); - create_preset_tabs(); std::vector tab_names = { "print", "filament", "sla_material", "printer" }; for (auto tab_name : tab_names) @@ -225,9 +214,6 @@ void MainFrame::add_created_tab(Tab* panel) { panel->create_preset_tab(); - // Load the currently selected preset into the GUI, update the preset selection box. - panel->load_current_preset(); - const wxString& tab_name = panel->GetName(); bool add_panel = true; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 8fdb5fd3b..2de1cfbf1 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -244,6 +244,7 @@ public: ~FreqChangedParams() {} wxButton* get_wiping_dialog_button() { return m_wiping_dialog_button; } + void Show(const bool show); }; FreqChangedParams::FreqChangedParams(wxWindow* parent, const int label_width) : @@ -368,6 +369,16 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent, const int label_width) : } +void FreqChangedParams::Show(const bool show) +{ + bool is_wdb_shown = m_wiping_dialog_button->IsShown(); + m_og->sizer->Show(show); + + // correct showing of the FreqChangedParams sizer when m_wiping_dialog_button is hidden + if (show && !is_wdb_shown) + m_wiping_dialog_button->Hide(); +} + // Sidebar / private struct Sidebar::priv @@ -416,7 +427,7 @@ void Sidebar::priv::show_preset_comboboxes() sizer_presets->Show(4, showSLA); sizer_presets->Show(5, showSLA); - frequently_changed_parameters->get_sizer()->Show(!showSLA); + frequently_changed_parameters->Show(!showSLA); wxGetApp().plater()->Layout(); wxGetApp().mainframe->Layout(); @@ -795,6 +806,7 @@ struct Plater::priv #endif // !ENABLE_EXTENDED_SELECTION void arrange(); void split_object(); + void split_volume(); void schedule_background_process(); void async_apply_config(); void start_background_process(); @@ -812,7 +824,8 @@ struct Plater::priv void on_layer_editing_toggled(bool enable); void on_action_add(SimpleEvent&); - void on_action_split(SimpleEvent&); + void on_action_split_objects(SimpleEvent&); + void on_action_split_volumes(SimpleEvent&); void on_action_cut(SimpleEvent&); #if !ENABLE_EXTENDED_SELECTION void on_action_settings(SimpleEvent&); @@ -844,7 +857,8 @@ private: bool can_delete_object() const; bool can_increase_instances() const; bool can_decrease_instances() const; - bool can_split_object() const; + bool can_split_to_objects() const; + bool can_split_to_volumes() const; bool can_cut_object() const; bool layers_height_allowed() const; bool can_delete_all() const; @@ -958,7 +972,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : canvas3D->Bind(EVT_GLTOOLBAR_ARRANGE, [this](SimpleEvent&) { arrange(); }); canvas3D->Bind(EVT_GLTOOLBAR_MORE, [q](SimpleEvent&) { q->increase_instances(); }); canvas3D->Bind(EVT_GLTOOLBAR_FEWER, [q](SimpleEvent&) { q->decrease_instances(); }); - canvas3D->Bind(EVT_GLTOOLBAR_SPLIT, &priv::on_action_split, this); + canvas3D->Bind(EVT_GLTOOLBAR_SPLIT_OBJECTS, &priv::on_action_split_objects, this); + canvas3D->Bind(EVT_GLTOOLBAR_SPLIT_VOLUMES, &priv::on_action_split_volumes, this); canvas3D->Bind(EVT_GLTOOLBAR_CUT, &priv::on_action_cut, this); #if !ENABLE_EXTENDED_SELECTION canvas3D->Bind(EVT_GLTOOLBAR_SETTINGS, &priv::on_action_settings, this); @@ -1356,12 +1371,14 @@ void Plater::priv::selection_changed() _3DScene::enable_toolbar_item(canvas3D, "delete", can_delete_object()); _3DScene::enable_toolbar_item(canvas3D, "more", can_increase_instances()); _3DScene::enable_toolbar_item(canvas3D, "fewer", can_decrease_instances()); - _3DScene::enable_toolbar_item(canvas3D, "split", can_split_object()); + _3DScene::enable_toolbar_item(canvas3D, "splitobjects", can_split_to_objects()); + _3DScene::enable_toolbar_item(canvas3D, "splitvolumes", can_split_to_volumes()); _3DScene::enable_toolbar_item(canvas3D, "cut", can_cut_object()); _3DScene::enable_toolbar_item(canvas3D, "layersediting", layers_height_allowed()); #else _3DScene::enable_toolbar_item(canvas3D, "fewer", have_sel); - _3DScene::enable_toolbar_item(canvas3D, "split", have_sel); + _3DScene::enable_toolbar_item(canvas3D, "splitobjects", have_sel); + _3DScene::enable_toolbar_item(canvas3D, "splitvolumes", have_sel); _3DScene::enable_toolbar_item(canvas3D, "cut", have_sel); _3DScene::enable_toolbar_item(canvas3D, "settings", have_sel); _3DScene::enable_toolbar_item(canvas3D, "layersediting", have_sel && config->opt_bool("variable_layer_height") && _3DScene::is_layers_editing_allowed(canvas3D)); @@ -1617,8 +1634,10 @@ void Plater::priv::split_object() } else { + unsigned int counter = 1; for (ModelObject* m : new_objects) { + m->name = current_model_object->name + "_" + std::to_string(counter++); m->center_around_origin(); } @@ -1631,6 +1650,11 @@ void Plater::priv::split_object() #endif // ENABLE_EXTENDED_SELECTION } +void Plater::priv::split_volume() +{ + wxGetApp().obj_list()->split(false); +} + void Plater::priv::schedule_background_process() { // Trigger the timer event after 0.5s @@ -1868,11 +1892,16 @@ void Plater::priv::on_action_add(SimpleEvent&) q->add(); } -void Plater::priv::on_action_split(SimpleEvent&) +void Plater::priv::on_action_split_objects(SimpleEvent&) { split_object(); } +void Plater::priv::on_action_split_volumes(SimpleEvent&) +{ + split_volume(); +} + void Plater::priv::on_action_cut(SimpleEvent&) { // TODO @@ -2031,8 +2060,16 @@ bool Plater::priv::init_object_menu() wxMenuItem* item_mirror = append_submenu(&object_menu, mirror_menu, wxID_ANY, _(L("Mirror")), _(L("Mirror the selected object"))); #endif // ENABLE_MIRROR - wxMenuItem* item_split = append_menu_item(&object_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object into individual parts")), - [this](wxCommandEvent&){ split_object(); }, "shape_ungroup.png"); + wxMenu* split_menu = new wxMenu(); + if (split_menu == nullptr) + return false; + + wxMenuItem* item_split_objects = append_menu_item(split_menu, wxID_ANY, _(L("To objects")), _(L("Split the selected object into individual objects")), + [this](wxCommandEvent&){ split_object(); }, "shape_ungroup.png", &object_menu); + wxMenuItem* item_split_volumes = append_menu_item(split_menu, wxID_ANY, _(L("To parts")), _(L("Split the selected object into individual sub-parts")), + [this](wxCommandEvent&){ split_volume(); }, "shape_ungroup.png", &object_menu); + + wxMenuItem* item_split = append_submenu(&object_menu, split_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object")), "shape_ungroup.png"); #if ENABLE_EXTENDED_SELECTION // ui updates needs to be binded to the parent panel @@ -2044,7 +2081,9 @@ bool Plater::priv::init_object_menu() q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete_object()); }, item_delete->GetId()); q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_increase_instances()); }, item_increase->GetId()); q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_decrease_instances()); }, item_decrease->GetId()); - q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split_object()); }, item_split->GetId()); + q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split_to_objects() || can_split_to_volumes()); }, item_split->GetId()); + q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split_to_objects()); }, item_split_objects->GetId()); + q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split_to_volumes()); }, item_split_volumes->GetId()); } #endif // ENABLE_EXTENDED_SELECTION @@ -2070,7 +2109,13 @@ bool Plater::priv::can_decrease_instances() const return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && (model.objects[obj_idx]->instances.size() > 1); } -bool Plater::priv::can_split_object() const +bool Plater::priv::can_split_to_objects() const +{ + int obj_idx = get_selected_object_idx(); + return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && !model.objects[obj_idx]->is_multiparts(); +} + +bool Plater::priv::can_split_to_volumes() const { int obj_idx = get_selected_object_idx(); return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && !model.objects[obj_idx]->is_multiparts(); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 1897b4779..000270e13 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -215,7 +215,9 @@ void Tab::create_preset_tab() // Initialize the DynamicPrintConfig by default keys/values. build(); rebuild_page_tree(); - update(); +// update(); + // Load the currently selected preset into the GUI, update the preset selection box. + load_current_preset(); } void Tab::load_initial_data() @@ -740,9 +742,7 @@ void Tab::update_wiping_button_visibility() { bool multiple_extruders = dynamic_cast((m_preset_bundle->printers.get_edited_preset().config).option("nozzle_diameter"))->values.size() > 1; bool single_extruder_mm = dynamic_cast( (m_preset_bundle->printers.get_edited_preset().config).option("single_extruder_multi_material"))->value; - if (!wxGetApp().mainframe) - return; - auto wiping_dialog_button = wxGetApp().mainframe->m_plater->sidebar().get_wiping_dialog_button(); + auto wiping_dialog_button = wxGetApp().sidebar().get_wiping_dialog_button(); if (wiping_dialog_button) { wiping_dialog_button->Show(wipe_tower_enabled && multiple_extruders && single_extruder_mm); wiping_dialog_button->GetParent()->Layout(); @@ -1862,8 +1862,6 @@ void TabPrinter::extruders_count_changed(size_t extruders_count){ m_preset_bundle->update_multi_material_filament_presets(); build_extruder_pages(); reload_config(); - if (!wxGetApp().mainframe) - return; on_value_change("extruders_count", extruders_count); wxGetApp().sidebar().update_objects_list_extruder_column(extruders_count); }